-
Notifications
You must be signed in to change notification settings - Fork 63
Expand file tree
/
Copy pathecSection.ml
More file actions
1615 lines (1407 loc) · 54.1 KB
/
ecSection.ml
File metadata and controls
1615 lines (1407 loc) · 54.1 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
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
(* -------------------------------------------------------------------- *)
open EcUtils
open EcSymbols
open EcPath
open EcAst
open EcTypes
open EcDecl
open EcModules
open EcTheory
open EcFol
module Sid = EcIdent.Sid
module Mid = EcIdent.Mid
module MSym = EcSymbols.Msym
(* -------------------------------------------------------------------- *)
type cbarg = [
| `Type of path
| `Op of path
| `Ax of path
| `Module of mpath
| `ModuleType of path
| `Typeclass of path
| `Instance of tcinstance
]
type cb = cbarg -> unit
(* -------------------------------------------------------------------- *)
type dep_error =
{ e_env : EcEnv.env;
e_who : locality * cbarg;
e_dep : locality * cbarg;
}
let pp_cbarg env fmt (who : cbarg) =
let ppe = EcPrinting.PPEnv.ofenv env in
match who with
| `Type p -> Format.fprintf fmt "type %a" (EcPrinting.pp_tyname ppe) p
| `Op p ->
begin
let op = EcEnv.Op.by_path p env in
match op.op_kind with
| OB_oper (Some (OP_Exn _)) ->
Format.fprintf fmt "exception %a" (EcPrinting.pp_opname ppe) p
| _ -> Format.fprintf fmt "operator %a" (EcPrinting.pp_opname ppe) p
end
| `Ax p -> Format.fprintf fmt "lemma/axiom %a" (EcPrinting.pp_axname ppe) p
| `Module mp ->
let ppe =
match mp.m_top with
| `Local id ->
if EcEnv.Mod.is_declared id env then
ppe
else EcPrinting.PPEnv.add_locals ppe [id]
| _ -> ppe in
Format.fprintf fmt "module %a" (EcPrinting.pp_topmod ppe) mp
| `ModuleType p ->
let mty = EcEnv.ModTy.modtype p env in
Format.fprintf fmt "module type %a" (EcPrinting.pp_modtype1 ppe) mty
| `Typeclass p ->
Format.fprintf fmt "typeclass %a" (EcPrinting.pp_tcname ppe) p
| `Instance tci ->
match tci with
| `Ring _ -> Format.fprintf fmt "ring instance"
| `Field _ -> Format.fprintf fmt "field instance"
| `General _ -> Format.fprintf fmt "instance"
let pp_locality fmt = function
| `Local -> Format.fprintf fmt "local"
| `Global -> ()
| `Declare -> Format.fprintf fmt "declared"
let pp_lc_cbarg env fmt (lc, who) =
Format.fprintf fmt "%a %a" pp_locality lc (pp_cbarg env) who
let pp_error fmt err =
let pp = pp_lc_cbarg err.e_env in
Format.fprintf fmt "%a cannot depend on %a" pp err.e_who pp err.e_dep
(* -------------------------------------------------------------------- *)
exception SectionError of string
let pp_section_error fmt exn =
match exn with
| SectionError s ->
Format.fprintf fmt "%s" s
| _ -> raise exn
let _ = EcPException.register pp_section_error
let hierror fmt =
let buf = Buffer.create 127 in
let bfmt = Format.formatter_of_buffer buf in
Format.kfprintf
(fun _ ->
Format.pp_print_flush bfmt ();
raise (SectionError (Buffer.contents buf)))
bfmt fmt
(* -------------------------------------------------------------------- *)
type aenv = {
env : EcEnv.env; (* Global environment for dep. analysis *)
cb : cb; (* Dep. analysis callback *)
cache : acache ref; (* Dep. analysis cache *)
}
and acache = {
op : Sp.t; (* Operator declaration already handled *)
type_ : Sp.t; (* Type declaration already handled *)
}
(* -------------------------------------------------------------------- *)
let empty_acache : acache =
{ op = Sp.empty; type_ = Sp.empty; }
(* -------------------------------------------------------------------- *)
let mkaenv (env : EcEnv.env) (cb : cb) : aenv =
{ env; cb; cache = ref empty_acache; }
(* -------------------------------------------------------------------- *)
let rec on_mp (aenv : aenv) (mp : mpath) =
aenv.cb (`Module (m_functor mp));
List.iter (on_mp aenv) mp.m_args
(* -------------------------------------------------------------------- *)
and on_xp (aenv : aenv) (xp : xpath) =
on_mp aenv xp.x_top
(* -------------------------------------------------------------------- *)
and on_memtype (aenv : aenv) (mt : EcMemory.memtype) =
EcMemory.mt_iter_ty (on_ty aenv) mt
(* -------------------------------------------------------------------- *)
and on_memenv (aenv : aenv) (m : EcMemory.memenv) =
on_memtype aenv (snd m)
(* -------------------------------------------------------------------- *)
and on_pv (aenv : aenv) (pv : prog_var)=
match pv with
| PVglob xp -> on_xp aenv xp
| _ -> ()
(* -------------------------------------------------------------------- *)
and on_lp (aenv : aenv) (lp : lpattern) =
match lp with
| LSymbol (_, ty) -> on_ty aenv ty
| LTuple xs -> List.iter (fun (_, ty) -> on_ty aenv ty) xs
| LRecord (_, xs) -> List.iter (on_ty aenv -| snd) xs
(* -------------------------------------------------------------------- *)
and on_binding (aenv : aenv) ((_, ty) : (EcIdent.t * ty)) =
on_ty aenv ty
(* -------------------------------------------------------------------- *)
and on_bindings (aenv : aenv) (bds : (EcIdent.t * ty) list) =
List.iter (on_binding aenv) bds
(* -------------------------------------------------------------------- *)
and on_ty (aenv : aenv) (ty : ty) =
match ty.ty_node with
| Tunivar _ -> ()
| Tvar _ -> ()
| Tglob m -> aenv.cb (`Module (mident m))
| Ttuple tys -> List.iter (on_ty aenv) tys
| Tconstr (p, tys) -> on_tyname aenv p; List.iter (on_ty aenv) tys
| Tfun (ty1, ty2) -> List.iter (on_ty aenv) [ty1; ty2]
(* -------------------------------------------------------------------- *)
and on_tyname (aenv : aenv) (p : path) =
aenv.cb (`Type p);
if not (Sp.mem p !(aenv.cache).type_) then begin
let cache = { !(aenv.cache) with type_ = Sp.add p !(aenv.cache).type_ } in
aenv.cache := cache;
on_tydecl aenv (EcEnv.Ty.by_path p aenv.env)
end
(* -------------------------------------------------------------------- *)
and on_opname (aenv : aenv) (p : EcPath.path) =
aenv.cb (`Op p);
if not (Sp.mem p !(aenv.cache).op) then begin
let cache = { !(aenv.cache) with op = Sp.add p !(aenv.cache).op } in
aenv.cache := cache;
on_opdecl aenv (EcEnv.Op.by_path p aenv.env);
end
(* -------------------------------------------------------------------- *)
and on_expr (aenv : aenv) (e : expr) =
let cbrec = on_expr aenv in
let fornode () =
match e.e_node with
| Eint _ -> ()
| Elocal _ -> ()
| Equant (_, bds, e) -> on_bindings aenv bds; cbrec e
| Evar pv -> on_pv aenv pv
| Elet (lp, e1, e2) -> on_lp aenv lp; List.iter cbrec [e1; e2]
| Etuple es -> List.iter cbrec es
| Eapp (e, es) -> List.iter cbrec (e :: es)
| Eif (c, e1, e2) -> List.iter cbrec [c; e1; e2]
| Ematch (e, es, ty) -> on_ty aenv ty; List.iter cbrec (e :: es)
| Eproj (e, _) -> cbrec e
| Eop (p, tys) -> begin
on_opname aenv p;
List.iter (on_ty aenv) tys;
end
in on_ty aenv e.e_ty; fornode ()
(* -------------------------------------------------------------------- *)
and on_lv (aenv : aenv) (lv : lvalue) =
let for1 (pv, ty) = on_pv aenv pv; on_ty aenv ty in
match lv with
| LvVar pv -> for1 pv
| LvTuple pvs -> List.iter for1 pvs
(* -------------------------------------------------------------------- *)
and on_instr (aenv : aenv) (i : instr)=
match i.i_node with
| Srnd (lv, e) | Sasgn (lv, e) ->
on_lv aenv lv;
on_expr aenv e
| Sraise e ->
on_expr aenv e
| Scall (lv, f, args) ->
oiter (on_lv aenv) lv;
on_xp aenv f;
List.iter (on_expr aenv) args
| Sif (e, s1, s2) ->
on_expr aenv e;
List.iter (on_stmt aenv) [s1; s2]
| Swhile (e, s) ->
on_expr aenv e;
on_stmt aenv s
| Smatch (e, b) ->
let forb (bs, s) =
List.iter (on_ty aenv -| snd) bs;
on_stmt aenv s
in on_expr aenv e; List.iter forb b
| Sabstract _ -> ()
(* -------------------------------------------------------------------- *)
and on_stmt (aenv : aenv) (s : stmt) =
List.iter (on_instr aenv) s.s_node
(* -------------------------------------------------------------------- *)
and on_form (aenv : aenv) (f : EcFol.form) =
let cbrec = on_form aenv in
let rec fornode () =
match f.EcAst.f_node with
| EcAst.Fint _ -> ()
| EcAst.Flocal _ -> ()
| EcAst.Fquant (_, b, f) -> on_gbindings aenv b; cbrec f
| EcAst.Fif (f1, f2, f3) -> List.iter cbrec [f1; f2; f3]
| EcAst.Fmatch (b, fs, ty) -> on_ty aenv ty; List.iter cbrec (b :: fs)
| EcAst.Flet (lp, f1, f2) -> on_lp aenv lp; List.iter cbrec [f1; f2]
| EcAst.Fapp (f, fs) -> List.iter cbrec (f :: fs)
| EcAst.Ftuple fs -> List.iter cbrec fs
| EcAst.Fproj (f, _) -> cbrec f
| EcAst.Fpvar (pv, _) -> on_pv aenv pv
| EcAst.Fglob _ -> ()
| EcAst.FhoareF hf -> on_hf aenv hf
| EcAst.FhoareS hs -> on_hs aenv hs
| EcAst.FeHoareF hf -> on_ehf aenv hf
| EcAst.FeHoareS hs -> on_ehs aenv hs
| EcAst.FequivF ef -> on_ef aenv ef
| EcAst.FequivS es -> on_es aenv es
| EcAst.FeagerF eg -> on_eg aenv eg
| EcAst.FbdHoareS bhs -> on_bhs aenv bhs
| EcAst.FbdHoareF bhf -> on_bhf aenv bhf
| EcAst.Fpr pr -> on_pr aenv pr
| EcAst.Fop (p, tys) -> begin
on_opname aenv p;
List.iter (on_ty aenv) tys;
end
and on_hf (aenv : aenv) hf =
on_form aenv (hf_pr hf).inv;
POE.iter (on_form aenv) (hf_po hf).hsi_inv;
on_xp aenv hf.EcAst.hf_f
and on_hs (aenv : aenv) hs =
on_form aenv (hs_pr hs).inv;
POE.iter (on_form aenv) (hs_po hs).hsi_inv;
on_stmt aenv hs.EcAst.hs_s;
on_memenv aenv hs.EcAst.hs_m
and on_ef (aenv : aenv) ef =
on_form aenv (EcAst.ef_pr ef).inv;
on_form aenv (EcAst.ef_po ef).inv;
on_xp aenv ef.EcAst.ef_fl;
on_xp aenv ef.EcAst.ef_fr
and on_es (aenv : aenv) es =
on_form aenv (EcAst.es_pr es).inv;
on_form aenv (EcAst.es_po es).inv;
on_stmt aenv es.EcAst.es_sl;
on_stmt aenv es.EcAst.es_sr;
on_memenv aenv es.EcAst.es_ml;
on_memenv aenv es.EcAst.es_mr
and on_eg (aenv : aenv) eg =
on_form aenv (EcAst.eg_pr eg).inv;
on_form aenv (EcAst.eg_po eg).inv;
on_xp aenv eg.EcAst.eg_fl;
on_xp aenv eg.EcAst.eg_fr;
on_stmt aenv eg.EcAst.eg_sl;
on_stmt aenv eg.EcAst.eg_sr;
and on_ehf (aenv : aenv) hf =
on_form aenv (EcAst.ehf_pr hf).inv;
on_form aenv (EcAst.ehf_po hf).inv;
on_xp aenv hf.EcAst.ehf_f
and on_ehs (aenv : aenv) hs =
on_form aenv (EcAst.ehs_pr hs).inv;
on_form aenv (EcAst.ehs_po hs).inv;
on_stmt aenv hs.EcAst.ehs_s;
on_memenv aenv hs.EcAst.ehs_m
and on_bhf (aenv : aenv) bhf =
on_form aenv (EcAst.bhf_pr bhf).inv;
on_form aenv (EcAst.bhf_po bhf).inv;
on_form aenv (EcAst.bhf_bd bhf).inv;
on_xp aenv bhf.EcAst.bhf_f
and on_bhs (aenv : aenv) bhs =
on_form aenv (EcAst.bhs_pr bhs).inv;
on_form aenv (EcAst.bhs_po bhs).inv;
on_form aenv (EcAst.bhs_bd bhs).inv;
on_stmt aenv bhs.EcAst.bhs_s;
on_memenv aenv bhs.EcAst.bhs_m
and on_pr (aenv : aenv) pr =
on_xp aenv pr.EcAst.pr_fun;
List.iter (on_form aenv) [pr.EcAst.pr_event.inv; pr.EcAst.pr_args]
in
on_ty aenv f.EcAst.f_ty; fornode ()
(* -------------------------------------------------------------------- *)
and on_restr (aenv : aenv) (restr : mod_restr) =
let doit (xs, ms) = Sx.iter (on_xp aenv) xs; Sm.iter (on_mp aenv) ms in
oiter doit restr.ur_pos;
doit restr.ur_neg
(* -------------------------------------------------------------------- *)
and on_modty (aenv : aenv) (mty : module_type) =
aenv.cb (`ModuleType mty.mt_name);
List.iter (fun (_, mty) -> on_modty aenv mty) mty.mt_params;
List.iter (on_mp aenv) mty.mt_args
(* -------------------------------------------------------------------- *)
and on_mty_mr (aenv : aenv) ((mty, mr) : mty_mr) =
on_modty aenv mty; on_restr aenv mr
(* -------------------------------------------------------------------- *)
and on_gbinding (aenv : aenv) (b : gty) =
match b with
| EcAst.GTty ty ->
on_ty aenv ty
| EcAst.GTmodty mty ->
on_mty_mr aenv mty
| EcAst.GTmem m ->
on_memtype aenv m
(* -------------------------------------------------------------------- *)
and on_gbindings (aenv : aenv) (b : (EcIdent.t * gty) list) =
List.iter (fun (_, b) -> on_gbinding aenv b) b
(* -------------------------------------------------------------------- *)
and on_module (aenv : aenv) (me : module_expr) =
match me.me_body with
| ME_Alias (_, mp) -> on_mp aenv mp
| ME_Structure st -> on_mstruct aenv st
| ME_Decl mty -> on_mty_mr aenv mty
(* -------------------------------------------------------------------- *)
and on_mstruct (aenv : aenv) (st : module_structure) =
List.iter (on_mstruct1 aenv) st.ms_body
(* -------------------------------------------------------------------- *)
and on_mstruct1 (aenv : aenv) (item : module_item) =
match item with
| MI_Module me -> on_module aenv me
| MI_Variable x -> on_ty aenv x.v_type
| MI_Function f -> on_fun aenv f
(* -------------------------------------------------------------------- *)
and on_fun (aenv : aenv) (fun_ : function_) =
on_fun_sig aenv fun_.f_sig;
on_fun_body aenv fun_.f_def
(* -------------------------------------------------------------------- *)
and on_fun_sig (aenv : aenv) (fsig : funsig) =
on_ty aenv fsig.fs_arg;
on_ty aenv fsig.fs_ret
(* -------------------------------------------------------------------- *)
and on_fun_body (aenv : aenv) (fbody : function_body) =
match fbody with
| FBalias xp -> on_xp aenv xp
| FBdef fdef -> on_fun_def aenv fdef
| FBabs oi -> on_oi aenv oi
(* -------------------------------------------------------------------- *)
and on_fun_def (aenv : aenv) (fdef : function_def) =
List.iter (fun v -> on_ty aenv v.v_type) fdef.f_locals;
on_stmt aenv fdef.f_body;
fdef.f_ret |> oiter (on_expr aenv);
on_uses aenv fdef.f_uses
(* -------------------------------------------------------------------- *)
and on_uses (aenv : aenv) (uses : uses) =
List.iter (on_xp aenv) uses.us_calls;
Sx.iter (on_xp aenv) uses.us_reads;
Sx.iter (on_xp aenv) uses.us_writes
(* -------------------------------------------------------------------- *)
and on_oi (aenv : aenv) (oi : OI.t) =
List.iter (on_xp aenv) (OI.allowed oi)
(* -------------------------------------------------------------------- *)
and on_typarams (_aenv : aenv) (_typarams : ty_params) =
()
(* -------------------------------------------------------------------- *)
and on_tydecl (aenv : aenv) (tyd : tydecl) =
on_typarams aenv tyd.tyd_params;
match tyd.tyd_type with
| Concrete ty -> on_ty aenv ty
| Abstract -> ()
| Record (f, fds) ->
on_form aenv f;
List.iter (on_ty aenv -| snd) fds
| Datatype dt ->
List.iter (List.iter (on_ty aenv) -| snd) dt.tydt_ctors;
List.iter (on_form aenv) [dt.tydt_schelim; dt.tydt_schcase]
and on_typeclass (aenv : aenv) tc =
oiter (fun p -> aenv.cb (`Typeclass p)) tc.tc_prt;
List.iter (fun (_,ty) -> on_ty aenv ty) tc.tc_ops;
List.iter (fun (_,f) -> on_form aenv f) tc.tc_axs
(* -------------------------------------------------------------------- *)
and on_opdecl (aenv : aenv) (opdecl : operator) =
on_typarams aenv opdecl.op_tparams;
let for_kind () =
match opdecl.op_kind with
| OB_pred None -> ()
| OB_pred (Some (PR_Plain f)) ->
on_form aenv f
| OB_pred (Some (PR_Ind pri)) ->
on_bindings aenv pri.pri_args;
List.iter (fun ctor ->
on_gbindings aenv ctor.prc_bds;
List.iter (on_form aenv) ctor.prc_spec)
pri.pri_ctors
| OB_nott nott ->
List.iter (on_ty aenv -| snd) nott.ont_args;
on_ty aenv nott.ont_resty;
on_expr aenv nott.ont_body
| OB_oper None -> ()
| OB_oper Some b ->
match b with
| OP_Exn ty -> List.iter (on_ty aenv) ty
| OP_Constr _ | OP_Record _ | OP_Proj _ | OP_TC -> ()
| OP_Plain f -> on_form aenv f
| OP_Fix f ->
let rec on_mpath_branches br =
match br with
| OPB_Leaf (bds, e) ->
List.iter (on_bindings aenv) bds;
on_expr aenv e
| OPB_Branch br ->
Parray.iter on_mpath_branch br
and on_mpath_branch br =
on_mpath_branches br.opb_sub
in on_mpath_branches f.opf_branches
in on_ty aenv opdecl.op_ty; for_kind ()
(* -------------------------------------------------------------------- *)
and on_axiom (aenv : aenv) (ax : axiom) =
on_typarams aenv ax.ax_tparams;
on_form aenv ax.ax_spec
(* -------------------------------------------------------------------- *)
and on_modsig (aenv : aenv) (ms:module_sig) =
List.iter (fun (_,mt) -> on_modty aenv mt) ms.mis_params;
List.iter (fun (Tys_function fs) ->
on_ty aenv fs.fs_arg;
List.iter (fun x -> on_ty aenv x.ov_type) fs.fs_anames;
on_ty aenv fs.fs_ret;) ms.mis_body;
Msym.iter (fun _ oi -> on_oi aenv oi) ms.mis_oinfos
(* -------------------------------------------------------------------- *)
and on_ring (aenv : aenv) (r : ring) =
on_ty aenv r.r_type;
let on_p p = on_opname aenv p in
List.iter on_p [r.r_zero; r.r_one; r.r_add; r.r_mul];
List.iter (oiter on_p) [r.r_opp; r.r_exp; r.r_sub];
match r.r_embed with
| `Direct | `Default -> ()
| `Embed p -> on_p p
(* -------------------------------------------------------------------- *)
and on_field (aenv : aenv) (f : field) =
on_ring aenv f.f_ring;
let on_p p = on_opname aenv p in
on_p f.f_inv; oiter on_p f.f_div
(* -------------------------------------------------------------------- *)
and on_instance (aenv : aenv) ty tci =
on_typarams aenv (fst ty);
on_ty aenv (snd ty);
match tci with
| `Ring r -> on_ring aenv r
| `Field f -> on_field aenv f
| `General p ->
(* FIXME section: ring/field use type class that do not exists *)
aenv.cb (`Typeclass p)
(* -------------------------------------------------------------------- *)
type sc_name =
| Th of symbol * is_local * thmode
| Sc of symbol option
| Top
type scenv = {
sc_env : EcEnv.env;
sc_top : scenv option;
sc_loca : is_local;
sc_name : sc_name;
sc_insec : bool;
sc_abstr : bool;
sc_items : sc_items;
}
and sc_item =
| SC_th_item of EcTheory.theory_item
| SC_th of EcEnv.Theory.compiled_theory
| SC_decl_mod of EcIdent.t * mty_mr
and sc_items =
sc_item list
let initial env =
{ sc_env = env;
sc_top = None;
sc_loca = `Global;
sc_name = Top;
sc_insec = false;
sc_abstr = false;
sc_items = [];
}
let env scenv = scenv.sc_env
(* -------------------------------------------------------------------- *)
let pp_axname scenv =
EcPrinting.pp_axname (EcPrinting.PPEnv.ofenv scenv.sc_env)
let pp_thname scenv =
EcPrinting.pp_thname (EcPrinting.PPEnv.ofenv scenv.sc_env)
(* -------------------------------------------------------------------- *)
let locality (env : EcEnv.env) (who : cbarg) =
match who with
| `Type p -> (EcEnv.Ty.by_path p env).tyd_loca
| `Op p -> (EcEnv.Op.by_path p env).op_loca
| `Ax p -> (EcEnv.Ax.by_path p env).ax_loca
| `Typeclass p -> ((EcEnv.TypeClass.by_path p env).tc_loca :> locality)
| `Module mp -> begin
match EcEnv.Mod.by_mpath_opt mp env with
| Some (_, Some lc) -> lc
| _ ->
let id = EcPath.mget_ident mp in
if EcEnv.Mod.is_declared id env then `Declare else `Global
end
| `ModuleType p -> ((EcEnv.ModTy.by_path p env).tms_loca :> locality)
| `Instance _ -> assert false
(* -------------------------------------------------------------------- *)
type to_clear =
{ lc_theory : Sp.t;
lc_axioms : Sp.t;
lc_baserw : Sp.t; }
type to_gen =
{ tg_env : scenv;
tg_params : ty_params;
tg_binds : bind list;
tg_subst : EcSubst.subst;
tg_clear : to_clear; }
and bind =
| Binding of binding
| Imply of form
let empty_locals =
{ lc_theory = Sp.empty;
lc_axioms = Sp.empty;
lc_baserw = Sp.empty; }
let add_clear to_gen who =
let tg_clear = to_gen.tg_clear in
let tg_clear =
match who with
| `Th p -> {tg_clear with lc_theory = Sp.add p tg_clear.lc_theory }
| `Ax p -> {tg_clear with lc_axioms = Sp.add p tg_clear.lc_axioms }
| `Baserw p -> {tg_clear with lc_baserw = Sp.add p tg_clear.lc_baserw }
in
{ to_gen with tg_clear }
let add_bind binds bd = binds @ [Binding bd]
let add_imp binds f = binds @ [Imply f]
let to_clear to_gen who =
match who with
| `Th p -> Sp.mem p to_gen.tg_clear.lc_theory
| `Ax p -> Sp.mem p to_gen.tg_clear.lc_axioms
| `Baserw p -> Sp.mem p to_gen.tg_clear.lc_baserw
let to_keep to_gen who = not (to_clear to_gen who)
let generalize_type to_gen ty =
EcSubst.subst_ty to_gen.tg_subst ty
let add_declared_mod to_gen id modty =
{ to_gen with
tg_binds = add_bind to_gen.tg_binds (id, gtmodty modty);
tg_subst = EcSubst.add_module to_gen.tg_subst id (mpath_abs id [])
}
let add_declared_ty to_gen path tydecl =
assert (tydecl.tyd_params = []);
let name = "'" ^ basename path in
let id = EcIdent.create name in
{ to_gen with
tg_params = to_gen.tg_params @ [id];
tg_subst = EcSubst.add_tydef to_gen.tg_subst path ([], tvar id);
}
let add_declared_op to_gen path opdecl =
assert (
opdecl.op_tparams = [] &&
match opdecl.op_kind with
| OB_oper None | OB_pred None -> true
| _ -> false);
let name = basename path in
let id = EcIdent.create name in
let ty = generalize_type to_gen opdecl.op_ty in
{
to_gen with
tg_binds = add_bind to_gen.tg_binds (id, gtty ty);
tg_subst =
match opdecl.op_kind with
| OB_oper _ -> EcSubst.add_opdef to_gen.tg_subst path ([], e_local id ty)
| OB_pred _ -> EcSubst.add_pddef to_gen.tg_subst path ([], f_local id ty)
| _ -> assert false }
let tvar_fv ty = Mid.map (fun () -> 1) (EcTypes.Tvar.fv ty)
let fv_and_tvar_e e =
let rec aux fv e =
let fv = EcIdent.fv_union fv (tvar_fv e.e_ty) in
match e.e_node with
| Eop(_, tys) -> List.fold_left (fun fv ty -> EcIdent.fv_union fv (tvar_fv ty)) fv tys
| Equant(_,d,e) ->
let fv = List.fold_left (fun fv (_,ty) -> EcIdent.fv_union fv (tvar_fv ty)) fv d in
aux fv e
| _ -> e_fold aux fv e
in aux e.e_fv e
let rec gty_fv_and_tvar : gty -> int Mid.t = function
| GTty ty ->
EcTypes.ty_fv_and_tvar ty
| GTmodty mty ->
EcAst.mty_mr_fv mty
| GTmem mt ->
EcMemory.mt_fv mt
and fv_and_tvar_f f =
let fv = ref f.f_fv in
let rec aux f =
fv := EcIdent.fv_union !fv (tvar_fv f.f_ty);
match f.f_node with
| Fop(_, tys) -> fv := List.fold_left (fun fv ty -> EcIdent.fv_union fv (tvar_fv ty)) !fv tys
| Fquant(_, d, f) ->
fv := List.fold_left (fun fv (_,gty) -> EcIdent.fv_union fv (gty_fv_and_tvar gty)) !fv d;
aux f
| Fmatch (b, bs, ty) ->
fv := EcIdent.fv_union (tvar_fv ty) !fv;
List.iter aux (b :: bs)
| _ -> EcFol.f_iter aux f
in
aux f; !fv
let tydecl_fv tyd =
let fv =
match tyd.tyd_type with
| Concrete ty -> ty_fv_and_tvar ty
| Abstract -> Mid.empty
| Datatype tydt ->
List.fold_left (fun fv (_, l) ->
List.fold_left (fun fv ty ->
EcIdent.fv_union fv (ty_fv_and_tvar ty)) fv l)
Mid.empty tydt.tydt_ctors
| Record (_f, l) ->
List.fold_left (fun fv (_, ty) ->
EcIdent.fv_union fv (ty_fv_and_tvar ty)) Mid.empty l in
let fv =
match tyd.tyd_subtype with
| None -> fv
| Some (carrier, pred) ->
EcIdent.fv_union
(EcIdent.fv_union fv (ty_fv_and_tvar carrier))
(fv_and_tvar_f pred) in
List.fold_left (fun fv id -> Mid.remove id fv) fv tyd.tyd_params
let op_body_fv body ty =
let fv = ty_fv_and_tvar ty in
match body with
| OP_Plain f -> EcIdent.fv_union fv (fv_and_tvar_f f)
| OP_Constr _ | OP_Record _ | OP_Proj _ | OP_TC | OP_Exn _ -> fv
| OP_Fix opfix ->
let fv =
List.fold_left (fun fv (_, ty) -> EcIdent.fv_union fv (ty_fv_and_tvar ty))
fv opfix.opf_args in
let fv = EcIdent.fv_union fv (ty_fv_and_tvar opfix.opf_resty) in
let rec fv_branches fv = function
| OPB_Leaf (l, e) ->
let fv = EcIdent.fv_union fv (fv_and_tvar_e e) in
List.fold_left (fun fv l ->
List.fold_left (fun fv (_, ty) ->
EcIdent.fv_union fv (ty_fv_and_tvar ty)) fv l) fv l
| OPB_Branch p ->
Parray.fold_left (fun fv ob -> fv_branches fv ob.opb_sub) fv p in
fv_branches fv opfix.opf_branches
let pr_body_fv body ty =
let fv = ty_fv_and_tvar ty in
match body with
| PR_Plain f -> EcIdent.fv_union fv (fv_and_tvar_f f)
| PR_Ind pri ->
let fv =
List.fold_left (fun fv (_, ty) -> EcIdent.fv_union fv (ty_fv_and_tvar ty))
fv pri.pri_args in
let fv_prctor fv ctor =
let fv1 =
List.fold_left (fun fv f -> EcIdent.fv_union fv (fv_and_tvar_f f))
Mid.empty ctor.prc_spec in
let fv1 = List.fold_left (fun fv (id, gty) ->
EcIdent.fv_union (Mid.remove id fv) (gty_fv_and_tvar gty)) fv1 ctor.prc_bds in
EcIdent.fv_union fv fv1 in
List.fold_left fv_prctor fv pri.pri_ctors
let notation_fv nota =
let fv = EcIdent.fv_union (fv_and_tvar_e nota.ont_body) (ty_fv_and_tvar nota.ont_resty) in
List.fold_left (fun fv (id,ty) ->
EcIdent.fv_union (Mid.remove id fv) (ty_fv_and_tvar ty)) fv nota.ont_args
let generalize_extra_ty to_gen fv =
List.filter (fun id -> Mid.mem id fv) to_gen.tg_params
let rec generalize_extra_args binds fv =
match binds with
| [] -> []
| Binding (id, gt) :: binds ->
let args = generalize_extra_args binds fv in
if Mid.mem id fv then
match gt with
| GTty ty -> (id, ty) :: args
| GTmodty _ -> assert false
| GTmem _ -> assert false
else args
| Imply _ :: binds -> generalize_extra_args binds fv
let rec generalize_extra_forall ~imply binds f =
match binds with
| [] -> f
| Binding (id,gt) :: binds ->
let f = generalize_extra_forall ~imply binds f in
if Mid.mem id f.f_fv then
f_forall [id,gt] f
else f
| Imply f1 :: binds ->
let f = generalize_extra_forall ~imply binds f in
if imply then f_imp f1 f else f
let generalize_tydecl to_gen prefix (name, tydecl) =
let path = pqname prefix name in
match tydecl.tyd_loca with
| `Local -> to_gen, None
| `Global ->
let tydecl = EcSubst.subst_tydecl to_gen.tg_subst tydecl in
let fv = tydecl_fv tydecl in
let extra = generalize_extra_ty to_gen fv in
let tyd_params = extra @ tydecl.tyd_params in
let args = List.map tvar tyd_params in
let params = tydecl.tyd_params in
let tosubst = params, tconstr path args in
let tg_subst, tyd_type =
match tydecl.tyd_type with
| Concrete _ | Abstract ->
EcSubst.add_tydef to_gen.tg_subst path tosubst, tydecl.tyd_type
| Record (f, prs) ->
let subst = EcSubst.empty in
let tg_subst = to_gen.tg_subst in
let subst = EcSubst.add_tydef subst path tosubst in
let tg_subst = EcSubst.add_tydef tg_subst path tosubst in
let rsubst = ref subst in
let rtg_subst = ref tg_subst in
let tin = tconstr path args in
let add_op (s, ty) =
let p = pqname prefix s in
let tosubst = params, e_op p args (tfun tin ty) in
rsubst := EcSubst.add_opdef !rsubst p tosubst;
rtg_subst := EcSubst.add_opdef !rtg_subst p tosubst;
s, ty
in
let prs = List.map add_op prs in
let f = EcSubst.subst_form !rsubst f in
!rtg_subst, Record (f, prs)
| Datatype dt ->
let subst = EcSubst.empty in
let tg_subst = to_gen.tg_subst in
let subst = EcSubst.add_tydef subst path tosubst in
let tg_subst = EcSubst.add_tydef tg_subst path tosubst in
let subst_ty = EcSubst.subst_ty subst in
let rsubst = ref subst in
let rtg_subst = ref tg_subst in
let tout = tconstr path args in
let add_op (s,tys) =
let tys = List.map subst_ty tys in
let p = pqname prefix s in
let pty = toarrow tys tout in
let tosubst = params, e_op p args pty in
rsubst := EcSubst.add_opdef !rsubst p tosubst;
rtg_subst := EcSubst.add_opdef !rtg_subst p tosubst ;
s, tys in
let tydt_ctors = List.map add_op dt.tydt_ctors in
let tydt_schelim = EcSubst.subst_form !rsubst dt.tydt_schelim in
let tydt_schcase = EcSubst.subst_form !rsubst dt.tydt_schcase in
!rtg_subst, Datatype {tydt_ctors; tydt_schelim; tydt_schcase }
in
let to_gen = { to_gen with tg_subst} in
let tydecl = {
tyd_params; tyd_type;
tyd_loca = `Global;
tyd_subtype = tydecl.tyd_subtype; } in
to_gen, Some (Th_type (name, tydecl))
| `Declare ->
let to_gen = add_declared_ty to_gen path tydecl in
to_gen, None
let generalize_opdecl to_gen prefix (name, operator) =
let path = pqname prefix name in
match operator.op_loca with
| `Local -> to_gen, None
| `Global ->
let operator = EcSubst.subst_op to_gen.tg_subst operator in
let tg_subst, operator =
match operator.op_kind with
| OB_oper None ->
let fv = ty_fv_and_tvar operator.op_ty in
let extra = generalize_extra_ty to_gen fv in
let tparams = extra @ operator.op_tparams in
let opty = operator.op_ty in
let args = List.map tvar tparams in
let tosubst = (operator.op_tparams, e_op path args opty) in
let tg_subst =
EcSubst.add_opdef to_gen.tg_subst path tosubst in
tg_subst, mk_op ~opaque:operator.op_opaque tparams opty None `Global
| OB_pred None ->
let fv = ty_fv_and_tvar operator.op_ty in
let extra = generalize_extra_ty to_gen fv in
let tparams = extra @ operator.op_tparams in
let opty = operator.op_ty in
let args = List.map tvar tparams in
let tosubst = (operator.op_tparams, f_op path args opty) in
let tg_subst =
EcSubst.add_pddef to_gen.tg_subst path tosubst in
tg_subst, mk_op ~opaque:operator.op_opaque tparams opty None `Global
| OB_oper (Some body) ->
let fv = op_body_fv body operator.op_ty in
let extra_t = generalize_extra_ty to_gen fv in
let tparams = extra_t @ operator.op_tparams in
let extra_a = generalize_extra_args to_gen.tg_binds fv in
let opty = toarrow (List.map snd extra_a) operator.op_ty in
let t_args = List.map tvar tparams in
let eop = e_op path t_args opty in
let e =
e_app eop (List.map (fun (id,ty) -> e_local id ty) extra_a)
operator.op_ty in
let tosubst = (operator.op_tparams, e) in
let tg_subst =
EcSubst.add_opdef to_gen.tg_subst path tosubst in
let body =
match body with
| OP_Constr _ | OP_Record _ | OP_Proj _ | OP_Exn _ -> assert false
| OP_TC -> assert false (* ??? *)
| OP_Plain f ->
OP_Plain (f_lambda (List.map (fun (x, ty) -> (x, GTty ty)) extra_a) f)
| OP_Fix opfix ->
let subst = EcSubst.add_opdef EcSubst.empty path tosubst in
let nb_extra = List.length extra_a in
let opf_struct =
let (l,i) = opfix.opf_struct in
(List.map (fun i -> i + nb_extra) l, i + nb_extra) in
OP_Fix {
opf_recp = opfix.opf_recp;
opf_args = extra_a @ opfix.opf_args;
opf_resty = opfix.opf_resty;
opf_struct;
opf_branches = EcSubst.subst_branches subst opfix.opf_branches;
}
in
let operator =
mk_op ~opaque:operator.op_opaque tparams opty (Some body) `Global in
tg_subst, operator
| OB_pred (Some body) ->
let fv = pr_body_fv body operator.op_ty in
let extra_t = generalize_extra_ty to_gen fv in
let op_tparams = extra_t @ operator.op_tparams in
let extra_a = generalize_extra_args to_gen.tg_binds fv in
let op_ty = toarrow (List.map snd extra_a) operator.op_ty in
let t_args = List.map tvar op_tparams in
let fop = f_op path t_args op_ty in
let f =
f_app fop (List.map (fun (id,ty) -> f_local id ty) extra_a)
operator.op_ty in
let tosubst = (operator.op_tparams, f) in
let tg_subst =
EcSubst.add_pddef to_gen.tg_subst path tosubst in
let body =
match body with
| PR_Plain f ->
PR_Plain (f_lambda (List.map (fun (x,ty) -> (x,GTty ty)) extra_a) f)
| PR_Ind pri ->
let pri_args = extra_a @ pri.pri_args in
PR_Ind { pri with pri_args }
in
let operator =
{ op_tparams; op_ty;
op_kind = OB_pred (Some body);
op_loca = `Global;
op_opaque = operator.op_opaque;
op_clinline = operator.op_clinline;
op_unfold = operator.op_unfold; } in
tg_subst, operator
| OB_nott nott ->
let fv = notation_fv nott in
let extra_t = generalize_extra_ty to_gen fv in
let op_tparams = extra_t @ operator.op_tparams in
let extra_a = generalize_extra_args to_gen.tg_binds fv in
let op_ty = toarrow (List.map snd extra_a) operator.op_ty in
let nott = { nott with ont_args = extra_a @ nott.ont_args; } in
to_gen.tg_subst,
{ op_tparams; op_ty;
op_kind = OB_nott nott;
op_loca = `Global;
op_opaque = operator.op_opaque;
op_clinline = operator.op_clinline;
op_unfold = operator.op_unfold; }
in
let to_gen = {to_gen with tg_subst} in
to_gen, Some (Th_operator (name, operator))
| `Declare ->
let to_gen = add_declared_op to_gen path operator in
to_gen, None