-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathpkg_notation.v
333 lines (270 loc) · 10.5 KB
/
pkg_notation.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
(** Package notations
In this module we define a functor to export user-friendly notations for
packages and package codes.
The user doesn't need to instantiate the functor here, and should only rely
on the Package functor which exports the notations as well.
Scope of the notations: package_scope
delimited with %pack.
Please look at package_usage_example.v for examples of how to use those.
- Notation for choice types in the choice universe
This module provides a specific notation for inhabiting the choice
universe, but only in certain positions that will be described in the
following notations.
These types can be described using a syntax closer to the usual Coq
syntax:
'nat
'bool
'unit
'option A
'fin n
A × B
{map A → B}
where A and B follow again the same syntax and n is a natural number
given using the regular Coq syntax.
- Notation to provide an inhabitant of 'fin n
gfin m will try to inhabit 'fin n
It is best used in a #[program] environment to make sure the proof
obligation is automatically discharged.
- Sequence notation for interfaces
An interface can be provided using the following sequence notation:
[interface d1 ; ... ; dn]
where d1 to dn are prototypes or function signatures of the form
#val #[n] : S → T
where S and T are both given using the type syntax above
and n is a natural number used as an identifier.
- Sequence notation for packages
A package can bve provided using the following sequence notation;
[package d1 ; ... dn]
where d1 to dn are function declarations of the form
#def #[n] (x : A) : B {
e
}
where n is a natural number used as an identifier, A and B are types
following the syntax above and e is a regular Coq expression which has
x of type (chElement A) in scope.
- Notation for the code monad
Additionally we provide some useful notations for writing codes.
All notations with a binder (x ← ...) can be instantiated with patterns
instead of new identifiers (e.g. '(x,y) ← ...).
- Bind:
x ← c ;; k
corresponds to binding c to x and continuing with k, an expression
that may contain x.
In case k doesn't mention x, we provide a special notation
c ;; k
- Managing state:
#put n := u ;; c
x ← get n ;; c
correspond respectively to updating and reading the state location n.
- Sampling:
x ← sample o ;; c
obtains x from sampling o and continues with c (which may mention x).
Alternatively one can use the synonymous notation
x <$ o ;; c
from easycrypt.
It will only be used for parsing, and will still print as
x ← sample o ;; c.
- Imported operators:
x ← op [ o ] n ;; c
will apply imported operator o to argument n, store the result in x and
continue with c.
o is given of the form
#[ f ] : A → B
which is the same as declarations in interfaces.
For instance one can write
n ← op [ #[0] : nat → nat ] n ;; ret n
**)
From Coq Require Import Utf8 Lia.
Set Warnings "-notation-overridden,-ambiguous-paths".
From mathcomp Require Import ssrnat ssreflect ssrfun ssrbool ssrnum eqtype
choice seq.
Set Warnings "notation-overridden,ambiguous-paths".
From extructures Require Import ord fset fmap.
From SSProve.Crypt Require Import Prelude Axioms ChoiceAsOrd RulesStateProb
choice_type pkg_core_definition pkg_composition.
#[local] Open Scope fset.
#[local] Open Scope fset_scope.
Declare Custom Entry pack_type.
Declare Custom Entry interface.
Declare Custom Entry package.
Declare Custom Entry pack_op.
Module PackageNotation.
(**
The `custom entry` engine does not allow a name to be a symbol without
it being a symbol in the global grammar.
As a workaround, we define 'bool and such to avoid making it impossible
to refer to bool by making it a keyword.
*)
Notation " 'nat " := (chNat) (in custom pack_type at level 2).
Notation " 'bool " := (chBool) (in custom pack_type at level 2).
Notation " 'unit " := (chUnit) (in custom pack_type at level 2).
Notation " 'option x " := (chOption x) (in custom pack_type at level 2).
Notation " 'fin n " :=
(chFin (mkpos n))
(in custom pack_type at level 2, n constr).
Notation "{map x → y }" :=
(chMap x y)
(in custom pack_type at level 2, format "{map x → y }").
Notation " x × y " := (chProd x y) (in custom pack_type at level 2).
Notation "( x )" := x (in custom pack_type, x at level 2).
(** Repeat the above notations here for package_scope. *)
Notation " 'nat " := (chNat) (at level 2) : package_scope.
Notation " 'bool " := (chBool) (at level 2) : package_scope.
Notation " 'unit " := (chUnit) (at level 2) : package_scope.
Notation " 'option x " := (chOption x) (at level 2) : package_scope.
Notation " 'fin x " :=
(chFin (mkpos x))
(at level 2) : package_scope.
(* Conflicts with this one. *)
(* Notation "{map x → y }" :=
(chMap x y)
(at level 80, format "{map x → y }") : package_scope. *)
Notation " x × y " := (chProd x y) (at level 80) : package_scope.
Notation "[ 'interface' ]" :=
(fset [::])
(at level 0, only parsing)
: package_scope.
Notation "[ 'interface' x1 ]" :=
(fset (x1 :: [::]))
(at level 0, x1 custom interface at level 2,
format "[ interface x1 ]")
: package_scope.
Notation "[ 'interface' x1 ; x2 ; .. ; xn ]" :=
(fset (x1 :: x2 :: .. [:: xn] ..))
(at level 0,
x1 custom interface at level 2,
x2 custom interface at level 2,
xn custom interface at level 2,
format "[ interface '[' x1 ; '/' x2 ; '/' .. ; '/' xn ']' ]")
: package_scope.
Notation "'#val' #[ f ] : A → B" :=
(f, (A, B))
(in custom interface at level 0,
f constr, A custom pack_type, B custom pack_type,
format "#val #[ f ] : A → B").
Notation "[ 'package' ]" :=
(mkpackage (mkfmap [::]) _)
(at level 0, only parsing)
: package_scope.
Notation "[ 'package' x1 ]" :=
(mkpackage (mkfmap (x1 :: [::])) _)
(at level 0, x1 custom package at level 2, format "[ package x1 ]")
: package_scope.
Notation "[ 'package' x1 ; x2 ; .. ; xn ]" :=
(mkpackage (mkfmap (x1 :: x2 :: .. [:: xn] ..)) _)
(at level 0,
x1 custom package at level 2,
x2 custom package at level 2,
xn custom package at level 2,
format "[ package '[' x1 ; '/' x2 ; '/' .. ; '/' xn ']' ]")
: package_scope.
Notation " '#def' #[ f ] ( x : A ) : B { e }" :=
((f, mkdef A B (λ x, e)))
(in custom package at level 0,
f constr, e constr, x name, A custom pack_type, B custom pack_type,
format "#def #[ f ] ( x : A ) : B { '[' '/' e '/' ']' }")
: package_scope.
Notation " '#def' #[ f ] ( ' p : A ) : B { e }" :=
((f, mkdef A B (λ x, let p := x in e)))
(in custom package at level 0,
f constr, e constr, p pattern, A custom pack_type, B custom pack_type,
format "#def #[ f ] ( ' p : A ) : B { '[' '/' e '/' ']' }")
: package_scope.
Notation "#[ f ] : A → B" :=
(mkopsig f A B)
(in custom pack_op at level 0,
f constr, A custom pack_type, B custom pack_type,
format "#[ f ] : A → B").
Notation "{ 'sig' o }" :=
(o)
(at level 0, o custom pack_op at level 2, format "{ sig o }")
: package_scope.
Notation "x ← c1 ;; c2" :=
(bind c1 (λ x, c2))
(at level 100, c1 at next level, right associativity,
format "x ← c1 ;; '//' c2")
: package_scope.
Notation "' p ← c1 ;; c2" :=
(bind c1 (λ x, let p := x in c2))
(at level 100, p pattern, c1 at next level, right associativity,
format "' p ← c1 ;; '//' c2")
: package_scope.
Notation "e1 ;; e2" :=
(_ ← e1 ;; e2)%pack
(at level 100, right associativity,
format "e1 ;; '//' e2")
: package_scope.
Notation "'#put' n ':=' u ;; c" :=
(putr n u c)
(at level 100, u at next level, right associativity,
format "#put n := u ;; '//' c")
: package_scope.
Notation "x ← 'get' n ;; c" :=
(getr n (λ x, c))
(at level 100, n at next level, right associativity,
format "x ← get n ;; '//' c")
: package_scope.
Notation "' p ← 'get' n ;; c" :=
(getr n (λ x, let p := x in c))
(at level 100, p pattern, n at next level, right associativity,
format "' p ← get n ;; '//' c")
: package_scope.
Notation "x ← 'op' o ⋅ n ;; c" :=
(opr o n (λ x, c))
(at level 100, n at next level, o at next level,
right associativity,
format "x ← op o ⋅ n ;; '//' c")
: package_scope.
Notation "' p ← 'op' o ⋅ n ;; c" :=
(opr o n (λ x, let p := x in c))
(at level 100, p pattern, n at next level, o at next level,
right associativity,
format "' p ← op o ⋅ n ;; '//' c")
: package_scope.
Notation "x ← 'sample' o ;; c" :=
(sampler o (λ x, c))
(at level 100, o at next level, right associativity,
format "x ← sample o ;; '//' c")
: package_scope.
Notation "' p ← 'sample' o ;; c" :=
(sampler o (λ x, let p := x in c))
(at level 100, p pattern, o at next level, right associativity,
format "' p ← sample o ;; '//' c")
: package_scope.
Notation "x <$ o ;; c" :=
(x ← sample o ;; c)%pack
(at level 100, o at next level, right associativity,
(* format "x <$ o ;; '//' c", *) only parsing)
: package_scope.
Notation "x ← 'cmd' o ;; c" :=
(cmd_bind o (λ x, c))
(at level 100, o at next level, right associativity,
format "x ← cmd o ;; '//' c")
: package_scope.
Notation "' p ← 'cmd' o ;; c" :=
(cmd_bind o (λ x, let p := x in c))
(at level 100, p pattern, o at next level, right associativity,
format "' p ← cmd o ;; '//' c")
: package_scope.
(* TODO Use ;; for this, and a longer notation or none at all for
bind. Bind is just a tool to compose codes while this is to compose
commands and code, much more practical.
*)
Notation "e1 ;' e2" :=
(_ ← cmd e1 ;; e2)%pack
(at level 100, right associativity,
format "e1 ;' '//' e2")
: package_scope.
Notation "'#import' s 'as' id ;; t" :=
(let id := λ x, opr s x (λ y, ret y) in t)
(at level 100, id name, s at next level, right associativity,
format "#import s as id ;; '//' t")
: package_scope.
(** Utility for fin types *)
(** m : 'fin n *)
Lemma give_fin {m} (n : nat) {h : Lt n m} : ('fin m)%pack.
Proof.
cbn. exists n. exact h.
Defined.
Notation gfin n := (give_fin n).
End PackageNotation.