You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: tutorial/PulseByExample.md
+14-12
Original file line number
Diff line number
Diff line change
@@ -1,22 +1,22 @@
1
1
# Pulse By Example
2
2
3
3
Pulse is a syntax extension and typechecker extension of F*.
4
-
A pulse program is embedded in an F* program, delimited by the syntax extension notation ````pulse ... ````.
4
+
A pulse program is embedded in an F* program, delimited by the syntax extension notation ` ... `.
5
5
The first code snippet demonstrates an embedded Pulse program `five`, which produces the integer 5.
6
6
The rest of the file is a normal F* program.
7
7
8
8
Pulse programs accept one or more arguments, where the `unit` type can be used to thunk a computation.
9
9
The specification of a Pulse program includes a precondition (`requires ...`), postcondition (`ensures ...`), and (optional) return type.
10
10
The pre- and post-conditions are propositions, like F* propositions but with a twise: Pulse leverages [separation logic](https://en.wikipedia.org/wiki/Separation_logic) to simplify reasoning about heap mutation.
11
11
12
-
Propositions in Pulse (called `vprop`s) enjoy separation logic operators like `**`, the separating conjunction.
13
-
A `vprop` may include a traditional F*`prop` by surrounding it with the `pure` keyword.
14
-
Generally, pure `prop`s are used to specify mathematical/logical constraints and anything having to do with references or memory sits outside in the surrounding `vprop`.
12
+
Propositions in Pulse (called `slprop`s) enjoy separation logic operators like `**`, the separating conjunction.
13
+
A `slprop` may include a traditional F*`prop` by surrounding it with the `pure` keyword.
14
+
Generally, pure `prop`s are used to specify mathematical/logical constraints and anything having to do with references or memory sits outside in the surrounding `slprop`.
15
15
16
16
Returning to our code snippet, the separation logic proposition `emp` means that the program does not own any resources or have any knowledge.
17
17
So the Pulse program `five` begins with no resources/knowledge and returns with the knowledge that the return value is logically equal to 5.
18
18
19
-
```ocaml
19
+
ocaml
20
20
module PM = Pulse.Main
21
21
open Pulse.Lib.Core
22
22
@@ -31,7 +31,7 @@ fn five ()
31
31
5
32
32
}
33
33
``
34
-
```
34
+
35
35
36
36
Let's make things more interesting.
37
37
The next code snippet `ref_swap` swaps the values of two integer references.
@@ -47,7 +47,7 @@ Pulse syntax spotlight: The program body demonstrates Pulse syntax for
47
47
- reference read: `!r1`
48
48
- reference write: `r1 := ...`
49
49
50
-
```ocaml
50
+
ocaml
51
51
open Pulse.Lib.Reference
52
52
module R = Pulse.Lib.Reference
53
53
@@ -64,12 +64,14 @@ fn ref_swap (r1 r2:ref int)
64
64
r2 := v1
65
65
}
66
66
``
67
-
```
67
+
68
68
69
69
You've seen references; now we'll introduce arrays.
70
70
But first, a note on integers.
71
71
In the following code snippet, we use non-primitive integers for the first time: `FStar.SizeT` is a module for machine integers of at least 16 bits, depending on the machine.
72
+
#lang-pulse
72
73
The module `Pulse.Class.BoundedIntegers` offers arithmetic operations on various types of bounded integers, including `FStar.SizeT` and `FStar.U32`.
74
+
#lang-pulse
73
75
The bounded integer class overloads arithmetic operators, like `<`, to allow, e.g., the comparison of `SizeT`s `i < n` on line X and comparison of `nat`s `k < v n` on line X (`v` elaborates to `SZ.v` and converts a `SizeT` to a nat).
74
76
75
77
Let's get back to arrays.
@@ -85,7 +87,7 @@ Pulse syntax spotlight: The program body demonstrates Pulse syntax for
85
87
- array read: `a.(i)`
86
88
- array write: `a.(i) <- ...`
87
89
88
-
```ocaml
90
+
ocaml
89
91
open Pulse.Lib.Array
90
92
module A = Pulse.Lib.Array
91
93
module SZ = FStar.SizeT
@@ -109,7 +111,7 @@ fn arr_swap (#t:Type0) (n i j:SZ.t) (a:larray t (v n))
109
111
a.(j) <- vi;
110
112
}
111
113
``
112
-
```
114
+
113
115
114
116
The last example introduces loops.
115
117
The Pulse program `max` computes the maximum value in an array of `nat`s.
@@ -147,7 +149,7 @@ Pulse syntax spotlight: The program body demonstrates Pulse syntax for
147
149
- loop invariant: `invariant b ...`
148
150
- custom proof syntax: `with ... assert ...`
149
151
150
-
```ocaml
152
+
ocaml
151
153
``pulse
152
154
fn max (n:SZ.t) (a:larray nat (v n))
153
155
requires A.pts_to a #'p 's ** pure (Seq.length 's == v n)
@@ -185,7 +187,7 @@ fn max (n:SZ.t) (a:larray nat (v n))
185
187
vmax
186
188
}
187
189
``
188
-
```
190
+
189
191
190
192
In this tutorial, you have seen custom Pulse proof syntax:
0 commit comments