-
Notifications
You must be signed in to change notification settings - Fork 63
Expand file tree
/
Copy pathecDecl.ml
More file actions
357 lines (293 loc) · 8.85 KB
/
ecDecl.ml
File metadata and controls
357 lines (293 loc) · 8.85 KB
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
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
(* -------------------------------------------------------------------- *)
open EcUtils
open EcAst
open EcTypes
open EcCoreFol
module Sp = EcPath.Sp
module TC = EcTypeClass
module BI = EcBigInt
module Ssym = EcSymbols.Ssym
module CS = EcCoreSubst
(* -------------------------------------------------------------------- *)
type ty_param = EcIdent.t
type ty_params = ty_param list
type ty_pctor = [ `Int of int | `Named of ty_params ]
type ty_record =
EcCoreFol.form * (EcSymbols.symbol * EcTypes.ty) list
type ty_dtype_ctor =
EcSymbols.symbol * EcTypes.ty list
type ty_dtype = {
tydt_ctors : ty_dtype_ctor list;
tydt_schelim : EcCoreFol.form;
tydt_schcase : EcCoreFol.form;
}
type ty_body =
| Concrete of EcTypes.ty
| Abstract
| Datatype of ty_dtype
| Record of ty_record
type tydecl = {
tyd_params : ty_params;
tyd_type : ty_body;
tyd_loca : locality;
}
let tydecl_as_concrete (td : tydecl) =
match td.tyd_type with Concrete x -> Some x | _ -> None
let tydecl_as_abstract (td : tydecl) =
match td.tyd_type with Abstract -> Some () | _ -> None
let tydecl_as_datatype (td : tydecl) =
match td.tyd_type with Datatype x -> Some x | _ -> None
let tydecl_as_record (td : tydecl) =
match td.tyd_type with Record (x, y) -> Some (x, y) | _ -> None
(* -------------------------------------------------------------------- *)
let abs_tydecl ?(params = `Int 0) lc =
let params =
match params with
| `Named params ->
params
| `Int n ->
let fmt = fun x -> Printf.sprintf "'%s" x in
List.map
(fun x -> (EcIdent.create x))
(EcUid.NameGen.bulk ~fmt n)
in
{ tyd_params = params; tyd_type = Abstract; tyd_loca = lc; }
(* -------------------------------------------------------------------- *)
let ty_instantiate (params : ty_params) (args : ty list) (ty : ty) =
let subst = CS.Tvar.init params args in
CS.Tvar.subst subst ty
(* -------------------------------------------------------------------- *)
type locals = EcIdent.t list
type operator_kind =
| OB_oper of opbody option
| OB_pred of prbody option
| OB_nott of notation
and opbody =
| OP_Plain of EcCoreFol.form
| OP_Constr of EcPath.path * int
| OP_Record of EcPath.path
| OP_Proj of EcPath.path * int * int
| OP_Fix of opfix
| OP_TC
and prbody =
| PR_Plain of form
| PR_Ind of prind
and opfix = {
opf_recp : EcPath.path;
opf_args : (EcIdent.t * EcTypes.ty) list;
opf_resty : EcTypes.ty;
opf_struct : int list * int;
opf_branches : opbranches;
}
and opbranches =
| OPB_Leaf of ((EcIdent.t * EcTypes.ty) list) list * EcTypes.expr
| OPB_Branch of opbranch Parray.parray
and opbranch = {
opb_ctor : EcPath.path * int;
opb_sub : opbranches;
}
and notation = {
ont_args : (EcIdent.t * EcTypes.ty) list;
ont_resty : EcTypes.ty;
ont_body : expr;
ont_ponly : bool;
}
and prind = {
pri_args : (EcIdent.t * EcTypes.ty) list;
pri_ctors : prctor list;
}
and prctor = {
prc_ctor : EcSymbols.symbol;
prc_bds : (EcIdent.t * gty) list;
prc_spec : form list;
}
type operator = {
op_tparams : ty_params;
op_ty : EcTypes.ty;
op_kind : operator_kind;
op_loca : locality;
op_opaque : opopaque;
op_clinline : bool;
op_unfold : int option;
}
and opopaque = { smt: bool; reduction: bool; }
(* -------------------------------------------------------------------- *)
type axiom_kind = [`Axiom of (Ssym.t * bool) | `Lemma]
type axiom = {
ax_tparams : ty_params;
ax_spec : EcCoreFol.form;
ax_kind : axiom_kind;
ax_loca : locality;
ax_smt : bool; }
let is_axiom (x : axiom_kind) = match x with `Axiom _ -> true | _ -> false
let is_lemma (x : axiom_kind) = match x with `Lemma -> true | _ -> false
(* -------------------------------------------------------------------- *)
let op_ty op = op.op_ty
let is_oper op =
match op.op_kind with
| OB_oper _ -> true
| _ -> false
let is_pred op =
match op.op_kind with
| OB_pred _ -> true
| _ -> false
let is_ctor op =
match op.op_kind with
| OB_oper (Some (OP_Constr _)) -> true
| _ -> false
let is_proj op =
match op.op_kind with
| OB_oper (Some (OP_Proj _)) -> true
| _ -> false
let is_rcrd op =
match op.op_kind with
| OB_oper (Some (OP_Record _)) -> true
| _ -> false
let is_fix op =
match op.op_kind with
| OB_oper (Some (OP_Fix _)) -> true
| _ -> false
let is_abbrev op =
match op.op_kind with
| OB_nott _ -> true
| _ -> false
let is_prind op =
match op.op_kind with
| OB_pred (Some (PR_Ind _)) -> true
| _ -> false
let gen_op ?(clinline = false) ?unfold ~opaque tparams ty kind lc = {
op_tparams = tparams;
op_ty = ty;
op_kind = kind;
op_loca = lc;
op_opaque = opaque;
op_clinline = clinline;
op_unfold = unfold;
}
let mk_pred ?clinline ?unfold ~opaque tparams dom body lc =
let kind = OB_pred body in
let ty = (EcTypes.toarrow dom EcTypes.tbool) in
gen_op ?clinline ?unfold ~opaque tparams ty kind lc
let optransparent : opopaque =
{ smt = false; reduction = false; }
let mk_op ?clinline ?unfold ~opaque tparams ty body lc =
let kind = OB_oper body in
gen_op ?clinline ?unfold ~opaque tparams ty kind lc
let mk_abbrev ?(ponly = false) tparams xs (codom, body) lc =
let kind = {
ont_args = xs;
ont_resty = codom;
ont_body = body;
ont_ponly = ponly;
} in
gen_op ~opaque:optransparent tparams
(EcTypes.toarrow (List.map snd xs) codom) (OB_nott kind) lc
let operator_as_ctor (op : operator) =
match op.op_kind with
| OB_oper (Some (OP_Constr (indp, ctor))) -> (indp, ctor)
| _ -> assert false
let operator_as_proj (op : operator) =
match op.op_kind with
| OB_oper (Some (OP_Proj (recp, i1, i2))) -> (recp, i1, i2)
| _ -> assert false
let operator_as_rcrd (op : operator) =
match op.op_kind with
| OB_oper (Some (OP_Record recp)) -> recp
| _ -> assert false
let operator_as_fix (op : operator) =
match op.op_kind with
| OB_oper (Some (OP_Fix fix)) -> fix
| _ -> assert false
let operator_as_prind (op : operator) =
match op.op_kind with
| OB_pred (Some (PR_Ind pri)) -> pri
| _ -> assert false
(* -------------------------------------------------------------------- *)
let axiomatized_op
?(nargs = 0)
?(nosmt = false)
(path : EcPath.path)
((tparams, axbd) : ty_params * form)
(lc : locality)
: axiom
=
let axbd, axpm =
let bdpm = tparams in
let axpm = List.map EcIdent.fresh bdpm in
(CS.Tvar.f_subst ~freshen:true bdpm (List.map EcTypes.tvar axpm) axbd,
axpm)
in
let args, axbd =
match axbd.f_node with
| Fquant (Llambda, bds, axbd) ->
let bds, flam = List.split_at nargs bds in
(bds, f_lambda flam axbd)
| _ -> [], axbd
in
let opargs = List.map (fun (x, ty) -> f_local x (gty_as_ty ty)) args in
let tyargs = List.map EcTypes.tvar axpm in
let op = f_op path tyargs (toarrow (List.map f_ty opargs) axbd.EcAst.f_ty) in
let op = f_app op opargs axbd.f_ty in
let axspec = f_forall args (f_eq op axbd) in
{ ax_tparams = axpm;
ax_spec = axspec;
ax_kind = `Axiom (Ssym.empty, false);
ax_loca = lc;
ax_smt = not nosmt; }
(* -------------------------------------------------------------------- *)
type typeclass = {
tc_prt : EcPath.path option;
tc_ops : (EcIdent.t * EcTypes.ty) list;
tc_axs : (EcSymbols.symbol * EcCoreFol.form) list;
tc_loca: is_local;
}
(* -------------------------------------------------------------------- *)
type rkind = [
| `Boolean
| `Integer
| `Modulus of (BI.zint option) pair
]
type ring = {
r_type : EcTypes.ty;
r_zero : EcPath.path;
r_one : EcPath.path;
r_add : EcPath.path;
r_opp : EcPath.path option;
r_mul : EcPath.path;
r_exp : EcPath.path option;
r_sub : EcPath.path option;
r_embed : [ `Direct | `Embed of EcPath.path | `Default];
r_kind : rkind;
}
let kind_equal k1 k2 =
match k1, k2 with
| `Boolean, `Boolean -> true
| `Integer, `Integer -> true
| `Modulus (n1, p1), `Modulus (n2, p2) ->
opt_equal BI.equal n1 n2
&& opt_equal BI.equal p1 p2
| _, _ -> false
let ring_equal r1 r2 =
EcTypes.ty_equal r1.r_type r2.r_type
&& EcPath.p_equal r1.r_zero r2.r_zero
&& EcPath.p_equal r1.r_one r2.r_one
&& EcPath.p_equal r1.r_add r2.r_add
&& EcUtils.oall2 EcPath.p_equal r1.r_opp r2.r_opp
&& EcPath.p_equal r1.r_mul r2.r_mul
&& EcUtils.oall2 EcPath.p_equal r1.r_exp r2.r_exp
&& EcUtils.oall2 EcPath.p_equal r1.r_sub r2.r_sub
&& kind_equal r1.r_kind r2.r_kind
&& match r1.r_embed, r2.r_embed with
| `Direct , `Direct -> true
| `Embed p1, `Embed p2 -> EcPath.p_equal p1 p2
| `Default , `Default -> true
| _ , _ -> false
type field = {
f_ring : ring;
f_inv : EcPath.path;
f_div : EcPath.path option;
}
let field_equal f1 f2 =
ring_equal f1.f_ring f2.f_ring
&& EcPath.p_equal f1.f_inv f2.f_inv
&& EcUtils.oall2 EcPath.p_equal f1.f_div f2.f_div