-
Notifications
You must be signed in to change notification settings - Fork 51
/
coq_elpi_builtins.ml
4134 lines (3779 loc) · 167 KB
/
coq_elpi_builtins.ml
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
(* coq-elpi: Coq terms as the object language of elpi *)
(* license: GNU Lesser General Public License Version 2.1 or later *)
(* ------------------------------------------------------------------------- *)
module API = Elpi.API
module E = API.RawData
module State = API.State
module P = API.RawPp
module Conv = API.Conversion
module CConv = API.ContextualConversion
module B = struct
include API.BuiltInData
include Elpi.Builtin
let ioarg = API.BuiltInPredicate.ioarg
let ioarg_any = API.BuiltInPredicate.ioarg_any
let ioargC = API.BuiltInPredicate.ioargC
let ioargC_flex = API.BuiltInPredicate.ioargC_flex
let ioarg_flex = API.BuiltInPredicate.ioarg_flex
let ioarg_poly s = { ioarg_any with API.Conversion.ty = API.Conversion.TyName s }
end
module Pred = API.BuiltInPredicate
module U = API.Utils
module CNotation = Notation
open Names
open Coq_elpi_utils
open Coq_elpi_HOAS
let string_of_ppcmds options pp =
let b = Buffer.create 512 in
let fmt = Format.formatter_of_buffer b in
Format.pp_set_margin fmt options.ppwidth;
Format.fprintf fmt "@[%a@]" Pp.pp_with pp;
Format.pp_print_flush fmt ();
Buffer.contents b
let with_pp_options o f =
let raw_print = !Flags.raw_print in
let print_universes = !Constrextern.print_universes in
let print_no_symbol = !Constrextern.print_no_symbol in
(* 8.14 let print_primitive_token = !Constrextern.print_primitive_token in*)
let print_implicits = !Constrextern.print_implicits in
let print_coercions = !Constrextern.print_coercions in
let print_parentheses = !Constrextern.print_parentheses in
let print_projections = !Constrextern.print_projections in
let print_evar_arguments = !Detyping.print_evar_arguments in
let f =
match o with
| All ->
Flags.raw_print := true;
f
| Most ->
Flags.raw_print := false;
Constrextern.print_universes := false;
Constrextern.print_no_symbol := true;
(* 8.14 Constrextern.print_primitive_token := true; *)
Constrextern.print_implicits := true;
Constrextern.print_coercions := true;
Constrextern.print_parentheses := true;
Constrextern.print_projections := false;
Detyping.print_evar_arguments := false;
Constrextern.with_meta_as_hole f
| Normal ->
(* If no preference is given, we print using Coq's current value *)
f
in
try
let rc = f () in
Flags.raw_print := raw_print;
Constrextern.print_universes := print_universes;
Constrextern.print_no_symbol := print_no_symbol;
(* 8.14 Constrextern.print_primitive_token := print_primitive_token; *)
Constrextern.print_implicits := print_implicits;
Constrextern.print_coercions := print_coercions;
Constrextern.print_parentheses := print_parentheses;
Constrextern.print_projections := print_projections;
Detyping.print_evar_arguments := print_evar_arguments;
rc
with reraise ->
Flags.raw_print := raw_print;
Constrextern.print_universes := print_universes;
Constrextern.print_no_symbol := print_no_symbol;
(* 8.14 Constrextern.print_primitive_token := print_primitive_token; *)
Constrextern.print_implicits := print_implicits;
Constrextern.print_coercions := print_coercions;
Constrextern.print_parentheses := print_parentheses;
Constrextern.print_projections := print_projections;
Detyping.print_evar_arguments := print_evar_arguments;
raise reraise
let with_no_tc ~no_tc f sigma =
if no_tc then
let typeclass_evars = Evd.get_typeclass_evars sigma in
let sigma = Evd.set_typeclass_evars sigma Evar.Set.empty in
let sigma, rc = f sigma in
let typeclass_evars = Evar.Set.filter (fun x ->
try ignore (Evd.find_undefined sigma x); true
with Not_found -> false) typeclass_evars in
let sigma = Evd.set_typeclass_evars sigma typeclass_evars in
sigma, rc
else f sigma
let pr_econstr_env options env sigma t =
with_pp_options options.pp (fun () ->
let expr = Constrextern.extern_constr env sigma t in
let expr =
let rec aux () ({ CAst.v } as orig) = match v with
| Constrexpr.CEvar _ -> CAst.make @@ Constrexpr.CHole(None)
| _ -> Constrexpr_ops.map_constr_expr_with_binders (fun _ () -> ()) aux () orig in
if options.hoas_holes = Some Heuristic then aux () expr else expr in
Ppconstr.pr_constr_expr_n env sigma options.pplevel expr)
let tactic_mode : bool State.component = State.declare_component ~name:"coq-elpi:tactic-mode" ~descriptor:interp_state
~pp:(fun fmt x -> Format.fprintf fmt "%b" x)
~init:(fun () -> false)
~start:(fun x -> x) ()
let abstract__grab_global_env_keep_sigma api thunk = (); (fun state ->
let uctx, state, result, gls = thunk state in
Coq_elpi_HOAS.grab_global_env ~uctx state, result, gls)
let grab_global_env__drop_sigma_univs_if_option_is_set options api thunk = (); (fun state ->
if State.get tactic_mode state then
Coq_elpi_utils.err Pp.(strbrk ("API " ^ api ^ " cannot be used in tactics"));
let uctx, state, result, gls = thunk state in
match options with
| { keepunivs = Some false } -> Coq_elpi_HOAS.grab_global_env_drop_univs_and_sigma state, result, gls
| _ -> Coq_elpi_HOAS.grab_global_env ~uctx state, result, gls)
let grab_global_env api thunk = (); (fun state ->
if State.get tactic_mode state then
Coq_elpi_utils.err Pp.(strbrk ("API " ^ api ^ " cannot be used in tactics"));
let uctx, state, result, gls = thunk state in
Coq_elpi_HOAS.grab_global_env ~uctx state, result, gls)
(* This is for stuff that is not monotonic in the env, eg section closing *)
let grab_global_env_drop_sigma api thunk = (); (fun state ->
if State.get tactic_mode state then
Coq_elpi_utils.err Pp.(strbrk ("API " ^ api ^ " cannot be used in tactics"));
let state, result, gls = thunk state in
Coq_elpi_HOAS.grab_global_env_drop_sigma state, result, gls)
let grab_global_env_drop_sigma_keep_univs api thunk = (); (fun state ->
if State.get tactic_mode state then
Coq_elpi_utils.err Pp.(strbrk ("API " ^ api ^ " cannot be used in tactics"));
let uctx, state, result, gls = thunk state in
Coq_elpi_HOAS.grab_global_env_drop_sigma_keep_univs ~uctx state, result, gls)
let bool = B.bool
let int = B.int
let list = B.list
let pair = B.pair
let option = B.option
let mk_algebraic_super x = Sorts.super x
(* I don't want the user to even know that algebraic universes exist *)
let univ_super state u v =
let state, u = match u with
| Sorts.Set | Sorts.Prop | Sorts.SProp -> state, u
| Sorts.Type ul | Sorts.QSort (_, ul) ->
if Univ.Universe.is_level ul then state, u
else
let state, (_,w) = new_univ_level_variable state in
let w = Sorts.sort_of_univ w in
add_universe_constraint state (constraint_leq u w), w in
add_universe_constraint state (constraint_leq (mk_algebraic_super u) v)
let univ_product state s1 s2 =
let s = Typeops.sort_of_product (get_global_env state) s1 s2 in
let state, (_,v) = new_univ_level_variable state in
let v = Sorts.sort_of_univ v in
let state = add_universe_constraint state (constraint_leq s v) in
state, v
let constr2lp ~depth hyps constraints state t =
constr2lp ~depth hyps constraints state t
let constr2lp_closed ~depth hyps constraints state t =
constr2lp_closed ~depth hyps constraints state t
let constr2lp_closed_ground ~depth hyps constraints state t =
constr2lp_closed_ground ~depth hyps constraints state t
let clauses_for_later_interp : _ State.component =
State.declare_component ~name:"coq-elpi:clauses_for_later" ~descriptor:interp_state
~init:(fun () -> [])
~start:(fun x -> x)
~pp:(fun fmt l ->
List.iter (fun (dbname, code,vars,scope) ->
Format.fprintf fmt "db:%s code:%a scope:%a\n"
(String.concat "." dbname)
Elpi.API.Pp.Ast.program code Coq_elpi_utils.pp_scope scope) l) ()
let term = {
CConv.ty = Conv.TyName "term";
pp_doc = (fun fmt () -> Format.fprintf fmt "A Coq term containing evars");
pp = (fun fmt t -> Format.fprintf fmt "@[%a@]" Pp.pp_with ( (Printer.pr_econstr_env (Global.env()) Evd.empty t)));
readback = lp2constr;
embed = constr2lp;
}
let failsafe_term = {
CConv.ty = Conv.TyName "term";
pp_doc = (fun fmt () -> Format.fprintf fmt "A Coq term containing evars");
pp = (fun fmt t -> Format.fprintf fmt "@[%a@]" Pp.pp_with ( (Printer.pr_econstr_env (Global.env()) Evd.empty t)));
readback = (fun ~depth coq_ctx csts s t -> lp2constr ~depth { coq_ctx with options = { coq_ctx.options with failsafe = true }} csts s t);
embed = constr2lp;
}
let proof_context : (full coq_context, API.Data.constraints) CConv.ctx_readback =
fun ~depth hyps constraints state ->
let state, proof_context, _, gls = get_current_env_sigma ~depth hyps constraints state in
state, proof_context, constraints, gls
let closed_term = {
CConv.ty = Conv.TyName "term";
pp_doc = (fun fmt () -> Format.fprintf fmt "A closed Coq term");
pp = (fun fmt t -> Format.fprintf fmt "@[%a@]" Pp.pp_with ( (Printer.pr_econstr_env (Global.env()) Evd.empty t)));
readback = lp2constr_closed;
embed = constr2lp_closed
}
let global : (empty coq_context, API.Data.constraints) CConv.ctx_readback =
fun ~depth hyps constraints state ->
let state, proof_context, _, gls = get_global_env_current_sigma ~depth hyps constraints state in
state, proof_context, constraints, gls
let closed_ground_term = {
CConv.ty = Conv.TyName "term";
pp_doc = (fun fmt () -> Format.fprintf fmt "A ground, closed, Coq term");
pp = (fun fmt t -> Format.fprintf fmt "@[%a@]" Pp.pp_with ( (Printer.pr_econstr_env (Global.env()) Evd.empty t)));
readback = lp2constr_closed_ground;
embed = constr2lp_closed_ground
}
let term_skeleton = {
CConv.ty = Conv.TyName "term";
pp_doc = (fun fmt () -> Format.fprintf fmt "A Coq term containing holes");
pp = (fun fmt t ->
let env = Global.env() in
let sigma = Evd.from_env env in
Format.fprintf fmt "@[%a@]" Pp.pp_with ( (Printer.pr_glob_constr_env env sigma t)));
readback = lp2skeleton;
embed = (fun ~depth _ _ _ _ -> assert false);
}
let sealed_goal = {
Conv.ty = Conv.TyName "sealed-goal";
pp_doc = (fun fmt () -> ());
pp = (fun fmt _ -> Format.fprintf fmt "TODO");
embed = sealed_goal2lp;
readback = (fun ~depth _ _ -> assert false);
}
let goal : ( (Coq_elpi_HOAS.full Coq_elpi_HOAS.coq_context * Evar.t * Coq_elpi_arg_HOAS.coq_arg list) , API.Data.hyps, API.Data.constraints) CConv.t = {
CConv.ty = Conv.TyName "goal";
pp_doc = (fun fmt () -> ());
pp = (fun fmt _ -> Format.fprintf fmt "TODO");
embed = (fun ~depth _ _ _ _ -> assert false);
readback = (fun ~depth hyps csts state g ->
let state, ctx, k, raw_args, gls1 = Coq_elpi_HOAS.lp2goal ~depth hyps csts state g in
let state, args, gls2 = U.map_acc (Coq_elpi_arg_HOAS.in_coq_arg ~depth ctx csts) state raw_args in
state, (ctx,k,args), gls1 @ gls2);
}
let tactic_arg : (Coq_elpi_arg_HOAS.coq_arg, Coq_elpi_HOAS.full Coq_elpi_HOAS.coq_context, API.Data.constraints) CConv.t = {
CConv.ty = Conv.TyName "argument";
pp_doc = (fun fmt () -> ());
pp = (fun fmt _ -> Format.fprintf fmt "TODO");
embed = (fun ~depth _ _ _ _ -> assert false);
readback = Coq_elpi_arg_HOAS.in_coq_arg;
}
let id = Coq_elpi_builtins_synterp.id
let flag name = { (B.unspec bool) with Conv.ty = Conv.TyName name }
(* Unfortunately the data type is not symmeteric *)
let indt_decl_in = {
CConv.ty = Conv.TyName "indt-decl";
pp_doc = (fun fmt () -> Format.fprintf fmt "Declaration of an inductive type");
pp = (fun fmt _ -> Format.fprintf fmt "mutual_inductive_entry");
readback = (fun ~depth ctx csts state t -> lp2inductive_entry ~depth ctx csts state t);
embed = (fun ~depth ctx csts state t -> assert false);
}
let indt_decl_out = {
CConv.ty = Conv.TyName "indt-decl";
pp_doc = (fun fmt () -> Format.fprintf fmt "Declaration of an inductive type");
pp = (fun fmt _ -> Format.fprintf fmt "mutual_inductive_entry");
readback = (fun ~depth ctx csts state t -> assert false);
embed = (fun ~depth ctx csts state t -> inductive_decl2lp ~depth ctx csts state t);
}
let is_ground sigma t = Evar.Set.is_empty (Evd.evars_of_term sigma t)
let is_ground_one_inductive_entry sigma { Entries.mind_entry_arity; mind_entry_lc } =
is_ground sigma (EConstr.of_constr mind_entry_arity) &&
List.for_all (is_ground sigma) @@ List.map EConstr.of_constr mind_entry_lc
let is_ground_rel_ctx_entry sigma rc =
is_ground sigma @@ EConstr.of_constr @@ Context.Rel.Declaration.get_type rc &&
Option.cata (fun x -> is_ground sigma @@ EConstr.of_constr x) true @@ Context.Rel.Declaration.get_value rc
let is_mutual_inductive_entry_ground { Entries.mind_entry_params; mind_entry_inds } sigma =
List.for_all (is_ground_rel_ctx_entry sigma) mind_entry_params &&
List.for_all (is_ground_one_inductive_entry sigma) mind_entry_inds
let handle_uinst_option_for_inductive ~depth options i state =
match options.uinstance with
| NoInstance ->
let term, ctx = UnivGen.fresh_global_instance (get_global_env state) (GlobRef.IndRef i) in
let state = update_sigma state (fun sigma -> Evd.merge_sort_context_set UState.univ_flexible_alg sigma ctx) in
snd @@ Constr.destInd term, state, []
| ConcreteInstance i -> i, state, []
| VarInstance (v_head, v_args, v_depth) ->
let v' = U.move ~from:v_depth ~to_:depth (E.mkUnifVar v_head ~args:v_args state) in
let term, ctx =
UnivGen.fresh_global_instance (get_global_env state) (GlobRef.IndRef i) in
let uinst = snd @@ Constr.destInd term in
let state, lp_uinst, extra_goals = uinstance.Conv.embed ~depth state uinst in
let state = update_sigma state (fun sigma -> Evd.merge_sort_context_set UState.univ_flexible_alg sigma ctx) in
uinst, state, API.Conversion.Unify (v', lp_uinst) :: extra_goals
(* FIXME PARTIAL API
*
* Record foo A1..Am := K { f1; .. fn }. -- m params, n fields
* Canonical c (x1 : b1)..(xk : bk) := K p1..pm t1..tn.
*
* fi v1..vm ? rest1 == (ci w1..wr) rest2
*
* ?i : bi
* vi =?= pi[xi/?i]
* wi =?= ui[xi/?i]
* ? == c ?1 .. ?k
* rest1 == rest2
* ?j =<= (ci w1..wr) -- default proj, ti = xj
* ci == gr
*
* unif (const fi) [V1,..VM, C | R1] (const ci) [W1,..WR| R2] M U :-
* of (app[c, ?1,..?k]) _ CR, -- saturate
* hd-beta CR [] (indc _) [P1,..PM,T1,..TN],
* unify-list-U Vi Pi,
* Ti = app[const ci|U1,..,UN],
* unify-list-U Wi Ui,
* unify-eq C CR,
* unify-list-eq R1 R2.
*
*)
let cs_pattern =
let open Conv in let open API.AlgebraicData in let open Structures.ValuePattern in declare {
ty = TyName "cs-pattern";
doc = "Pattern for canonical values";
pp = (fun fmt -> function
| Const_cs x -> Format.fprintf fmt "Const_cs %s" "<todo>"
| Proj_cs x -> Format.fprintf fmt "Proj_cs %s" "<todo>"
| Prod_cs -> Format.fprintf fmt "Prod_cs"
| Sort_cs _ -> Format.fprintf fmt "Sort_cs"
| Default_cs -> Format.fprintf fmt "Default_cs");
constructors = [
K("cs-gref","",A(gref,N),
B (function
| GlobRef.ConstructRef _ | GlobRef.IndRef _ | GlobRef.VarRef _ as x -> Const_cs x
| GlobRef.ConstRef cst as x ->
match Structures.PrimitiveProjections.find_opt cst with
| None -> Const_cs x
| Some p -> Proj_cs p),
M (fun ~ok ~ko -> function Const_cs x -> ok x | Proj_cs p -> ok (GlobRef.ConstRef (Projection.Repr.constant p)) | _ -> ko ()));
K("cs-prod","",N,
B Prod_cs,
M (fun ~ok ~ko -> function Prod_cs -> ok | _ -> ko ()));
K("cs-default","",N,
B Default_cs,
M (fun ~ok ~ko -> function Default_cs -> ok | _ -> ko ()));
K("cs-sort","",A(sort,N),
B (fun s -> Sort_cs (Sorts.family s)),
MS (fun ~ok ~ko p state -> match p with
| Sort_cs Sorts.InSet -> ok Sorts.set state
| Sort_cs Sorts.InProp -> ok Sorts.prop state
| Sort_cs Sorts.InType ->
let state, (_,u) = new_univ_level_variable state in
let u = Sorts.sort_of_univ u in
ok u state
| _ -> ko state))
]
} |> CConv.(!<)
let cs_instance = let open Conv in let open API.AlgebraicData in let open Structures.CSTable in declare {
ty = TyName "cs-instance";
doc = "Canonical Structure instances: (cs-instance Proj ValPat Inst)";
pp = (fun fmt { solution } -> Format.fprintf fmt "@[%a@]" Pp.pp_with ((Printer.pr_global solution)));
constructors = [
K("cs-instance","",A(gref,A(cs_pattern,A(gref,N))),
B (fun p v i -> assert false),
M (fun ~ok ~ko { solution; value; projection } -> ok projection value solution))
]
} |> CConv.(!<)
type tc_priority = Computed of int | UserGiven of int
let tc_priority = let open Conv in let open API.AlgebraicData in declare {
ty = TyName "tc-priority";
doc = "Type class instance priority";
pp = (fun fmt _ -> Format.fprintf fmt "<todo>");
constructors = [
K("tc-priority-given","User given priority",A(int,N),
B (fun i -> UserGiven i),
M (fun ~ok ~ko -> function UserGiven i -> ok i | _ -> ko ()));
K("tc-priority-computed","Coq computed priority", A(int,N),
B (fun i -> Computed i),
M (fun ~ok ~ko -> function Computed i -> ok i | _ -> ko ()));
]} |> CConv.(!<)
type type_class_instance = {
implementation : GlobRef.t;
priority : tc_priority;
}
let tc_instance = let open Conv in let open API.AlgebraicData in declare {
ty = TyName "tc-instance";
doc = "Type class instance with priority";
pp = (fun fmt _ -> Format.fprintf fmt "<todo>");
constructors = [
K("tc-instance","",A(gref,A(tc_priority,N)),
B (fun implementation priority -> { implementation; priority }),
M (fun ~ok ~ko { implementation; priority } -> ok implementation priority));
]} |> CConv.(!<)
[%%if coq = "8.20"]
let clenv_missing sigma ce cty =
let rec nb_hyp sigma c = match EConstr.kind sigma c with
| Prod(_,_,c2) -> if EConstr.Vars.noccurn sigma 1 c2 then 1+(nb_hyp sigma c2) else nb_hyp sigma c2
| _ -> 0 in
let miss = Clenv.clenv_missing ce in
let nmiss = List.length miss in
let hyps = nb_hyp sigma cty in
nmiss, hyps
[%%else]
let clenv_missing _ ce _ =
let miss, hyps = Clenv.clenv_missing ce in
List.length miss, hyps
[%%endif]
let get_instance_prio gr env sigma (hint_priority : int option) : tc_priority =
match hint_priority with
| Some p -> UserGiven p
| None ->
let merge_context_set_opt sigma ctx =
match ctx with
| None -> sigma
| Some ctx -> Evd.merge_sort_context_set Evd.univ_flexible sigma ctx
in
let fresh_global_or_constr env sigma =
let (c, ctx) = UnivGen.fresh_global_instance env gr in
let ctx = if Environ.is_polymorphic env gr then Some ctx else None in
(EConstr.of_constr c, ctx) in
let c, ctx = fresh_global_or_constr env sigma in
let cty = Retyping.get_type_of env sigma c in
let cty = Reductionops.nf_betaiota env sigma cty in
let sigma' = merge_context_set_opt sigma ctx in
let ce = Clenv.mk_clenv_from env sigma' (c,cty) in
let nmiss, nhyps = clenv_missing sigma' ce cty in
Computed (nhyps + nmiss)
(* TODO: this algorithm is quite inefficient since we have not yet the
possibility to get the implementation of an instance from its gref in
coq. Currently we have to get all the instances of the tc and the find
its implementation.
*)
let get_isntances_of_tc env sigma (tc : GlobRef.t) =
let inst_of_tc = (* contains all the instances of a type class *)
Typeclasses.instances_exn env sigma tc |>
List.fold_left (fun m i -> GlobRef.Map.add i.Typeclasses.is_impl i m) GlobRef.Map.empty in
inst_of_tc
let get_instance env sigma inst_of_tc instance : type_class_instance =
let instances_grefs2istance inst_gr : type_class_instance =
let open Typeclasses in
let user_hint_prio =
(* Note: in general we deal with an instance I of a type class. Here we
look if the user has given a priority to I. However, external
hints are not in the inst_of_tc (the Not_found exception) *)
try (GlobRef.Map.find inst_gr inst_of_tc).is_info.hint_priority
with Not_found -> None in
let priority = get_instance_prio inst_gr env sigma user_hint_prio in
{ implementation = inst_gr; priority }
in
instances_grefs2istance instance
let warning_tc_hints = CWarnings.create ~name:"elpi.TC.hints" ~category:elpi_cat Pp.str
let get_instances (env: Environ.env) (sigma: Evd.evar_map) tc : type_class_instance list =
let hint_db = Hints.searchtable_map "typeclass_instances" in
let secvars : Names.Id.Pred.t = Names.Id.Pred.full in
let full_hints = Hints.Hint_db.map_all ~secvars:secvars tc hint_db in
(* let hint_asts = List.map Hints.FullHint.repr full_hints in *)
let hints = List.filter_map (fun (e : Hints.FullHint.t) -> match Hints.FullHint.repr e with
| Hints.Res_pf a | ERes_pf a | Give_exact a -> Some a (* Respectively Hint Apply | EApply | Exact *)
| Extern _ ->
warning_tc_hints (Printf.sprintf "There is an hint extern in the typeclass db: \n%s" (Pp.string_of_ppcmds @@ Hints.FullHint.print env sigma e));
None
| Res_pf_THEN_trivial_fail _ -> (* Hint Immediate *)
warning_tc_hints (Printf.sprintf "There is an hint immediate in the typeclass db: \n%s" (Pp.string_of_ppcmds @@ Hints.FullHint.print env sigma e));
None
| Unfold_nth _ ->
warning_tc_hints (Printf.sprintf "There is an hint unfold in the typeclass db: \n%s" (Pp.string_of_ppcmds @@ Hints.FullHint.print env sigma e));
None) full_hints in
let constrs = List.map (fun a -> Hints.hint_as_term a |> snd) hints in
(* Printer.pr_global tc |> Pp.string_of_ppcmds |> Printf.printf "%s\n"; *)
let instances_grefs = List.filter_map (fun e ->
match EConstr.kind sigma e with
| Constr.Ind (a, _) -> Some (Names.GlobRef.IndRef a)
| Constr.Const (a, _) -> Some (Names.GlobRef.ConstRef a)
| Constr.Construct (a, _) -> Some (Names.GlobRef.ConstructRef a)
| _ -> None) constrs in
let isnt_of_tc = get_isntances_of_tc env sigma tc in
List.map (get_instance env sigma isnt_of_tc) instances_grefs
let set_accumulate_to_db_interp, get_accumulate_to_db_interp =
let f = ref (fun _ -> assert false) in
(fun x -> f := x),
(fun () -> !f)
[%%if coq = "8.20"]
let is_global_level env u =
try
let set = Univ.Level.Set.singleton u in
let () = UGraph.check_declared_universes (Environ.universes env) set in
true
with UGraph.UndeclaredLevel _ -> false
let global_push_context_set x = Global.push_context_set ~strict:true x
[%%else]
let is_global_level env u =
let set = Univ.Level.Set.singleton u in
match UGraph.check_declared_universes (Environ.universes env) set with
| Ok () -> true
| Error _ -> false
let global_push_context_set x = Global.push_context_set x
[%%endif]
let err_if_contains_alg_univ ~depth t =
let env = Global.env () in
let is_global u =
match Univ.Universe.level u with
| None -> true
| Some l -> is_global_level env l in
let rec aux ~depth acc t =
match E.look ~depth t with
| E.CData c when isuniv c ->
let u = univout c in
if is_global u then acc
else
begin match Univ.Universe.level u with
| None ->
err Pp.(strbrk "The hypothetical clause contains terms of type univ which are not global, you should abstract them out or replace them by global ones: " ++
Univ.Universe.pr UnivNames.pr_level_with_global_universes u)
| _ -> Univ.Universe.Set.add u acc
end
| x -> Coq_elpi_utils.fold_elpi_term aux acc ~depth x
in
let univs = aux ~depth Univ.Universe.Set.empty t in
univs
let preprocess_clause ~depth clause =
let levels_to_abstract = err_if_contains_alg_univ ~depth clause in
let levels_to_abstract_no = Univ.Universe.Set.cardinal levels_to_abstract in
let rec subst ~depth m t =
match E.look ~depth t with
| E.CData c when isuniv c ->
begin try E.mkBound (Univ.Universe.Map.find (univout c) m)
with Not_found -> t end
| E.App(c,x,xs) ->
E.mkApp c (subst ~depth m x) (List.map (subst ~depth m) xs)
| E.Cons(x,xs) ->
E.mkCons (subst ~depth m x) (subst ~depth m xs)
| E.Lam x ->
E.mkLam (subst ~depth:(depth+1) m x)
| E.Builtin(c,xs) ->
E.mkBuiltin c (List.map (subst ~depth m) xs)
| E.UnifVar _ -> CErrors.user_err Pp.(str"The clause begin accumulated contains unification variables, this is forbidden. You must quantify them out using 'pi'.")
| E.Const _ | E.Nil | E.CData _ -> t
in
let clause =
let rec bind d map = function
| [] ->
subst ~depth:d map
(API.Utils.move ~from:depth ~to_:(depth + levels_to_abstract_no) clause)
| l :: ls ->
E.mkApp E.Constants.pic (E.mkLam (* pi x\ *)
(bind (d+1) (Univ.Universe.Map.add l d map) ls)) []
in
bind depth Univ.Universe.Map.empty
(Univ.Universe.Set.elements levels_to_abstract)
in
let vars = collect_term_variables ~depth clause in
vars, clause
let argument_mode = let open Conv in let open API.AlgebraicData in declare {
ty = TyName "argument_mode";
doc = "Specify if a predicate argument is in input or output mode";
pp = (fun fmt _ -> Format.fprintf fmt "<todo>");
constructors = [
K("in","",N,
B `Input,
M (fun ~ok ~ko -> function `Input -> ok | _ -> ko ()));
K("out","",N,
B `Output,
M (fun ~ok ~ko -> function `Output -> ok | _ -> ko ()));
]
} |> CConv.(!<)
let set_accumulate_text_to_db_interp, get_accumulate_text_to_db_interp =
let f = ref (fun _ _ _ -> assert false) in
(fun x -> f := x),
(fun () -> !f)
let class_ = let open Conv in let open API.AlgebraicData in let open Coercionops in declare {
ty = TyName "class";
doc = "Node of the coercion graph";
pp = (fun fmt _ -> Format.fprintf fmt "<todo>");
constructors = [
K("funclass","",N,
B CL_FUN,
M (fun ~ok ~ko -> function Coercionops.CL_FUN -> ok | _ -> ko ()));
K("sortclass","",N,
B CL_SORT,
M (fun ~ok ~ko -> function CL_SORT -> ok | _ -> ko ()));
K("grefclass","",A(gref,N),
B ComCoercion.class_of_global,
M (fun ~ok ~ko -> function
| CL_SECVAR v -> ok (GlobRef.VarRef v)
| CL_CONST c -> ok (GlobRef.ConstRef c)
| CL_IND i -> ok (GlobRef.IndRef i)
| CL_PROJ p -> ok (GlobRef.ConstRef (Projection.Repr.constant p))
| _ -> ko ()))
]
} |> CConv.(!<)
let src_class_of_class = function
| (Coercionops.CL_FUN | Coercionops.CL_SORT) -> CErrors.anomaly Pp.(str "src_class_of_class on a non source coercion class")
| Coercionops.CL_SECVAR v -> GlobRef.VarRef v
| Coercionops.CL_CONST c -> GlobRef.ConstRef c
| Coercionops.CL_IND i -> GlobRef.IndRef i
| Coercionops.CL_PROJ p -> GlobRef.ConstRef (Projection.Repr.constant p)
let coercion = let open Conv in let open API.AlgebraicData in declare {
ty = TyName "coercion";
doc = "Edge of the coercion graph";
pp = (fun fmt _ -> Format.fprintf fmt "<todo>");
constructors = [
K("coercion","ref, nparams, src, tgt", A(gref,A(B.unspec int,A(B.unspec gref,A(B.unspec class_,N)))),
B (fun t np src tgt -> t,np,src,tgt),
M (fun ~ok ~ko:_ -> function (t,np,src,tgt) -> ok t np src tgt))
]
} |> CConv.(!<)
let implicit_kind : Glob_term.binding_kind Conv.t = let open Conv in let open API.AlgebraicData in let open Glob_term in declare {
ty = TyName "implicit_kind";
doc = "Implicit status of an argument";
pp = (fun fmt -> function
| NonMaxImplicit -> Format.fprintf fmt "implicit"
| Explicit -> Format.fprintf fmt "explicit"
| MaxImplicit -> Format.fprintf fmt "maximal");
constructors = [
K("implicit","regular implicit argument, eg Arguments foo [x]",N,
B NonMaxImplicit,
M (fun ~ok ~ko -> function NonMaxImplicit -> ok | _ -> ko ()));
K("maximal","maximally inserted implicit argument, eg Arguments foo {x}",N,
B MaxImplicit,
M (fun ~ok ~ko -> function MaxImplicit -> ok | _ -> ko ()));
K("explicit","explicit argument, eg Arguments foo x",N,
B Explicit,
M (fun ~ok ~ko -> function Explicit -> ok | _ -> ko ()));
]
} |> CConv.(!<)
let implicit_kind_of_status = function
| None -> Glob_term.Explicit
| Some imp ->
if imp.Impargs.impl_max then Glob_term.MaxImplicit else Glob_term.NonMaxImplicit
let simplification_strategy = let open API.AlgebraicData in let open Reductionops.ReductionBehaviour in declare {
ty = Conv.TyName "simplification_strategy";
doc = "Strategy for simplification tactics";
pp = (fun fmt (x : t) -> Format.fprintf fmt "TODO");
constructors = [
K ("never", "Arguments foo : simpl never",N,
B NeverUnfold,
M (fun ~ok ~ko -> function NeverUnfold -> ok | _ -> ko ()));
K("when","Arguments foo .. / .. ! ..",A(B.list B.int, A(B.option B.int, N)),
B (fun recargs nargs -> UnfoldWhen { recargs; nargs }),
M (fun ~ok ~ko -> function UnfoldWhen { recargs; nargs } -> ok recargs nargs | _ -> ko ()));
K("when-nomatch","Arguments foo .. / .. ! .. : simpl nomatch",A(B.list B.int, A(B.option B.int, N)),
B (fun recargs nargs -> UnfoldWhenNoMatch { recargs; nargs }),
M (fun ~ok ~ko -> function UnfoldWhenNoMatch { recargs; nargs } -> ok recargs nargs | _ -> ko ()));
]
} |> CConv.(!<)
let conversion_strategy = let open API.AlgebraicData in let open Conv_oracle in declare {
ty = Conv.TyName "conversion_strategy";
doc = "Strategy for conversion test\nexpand < ... < level -1 < level 0 < level 1 < ... < opaque";
pp = (fun fmt (x : level) -> Pp.pp_with fmt (pr_level x));
constructors = [
K ("opaque", "",N,
B Opaque,
M (fun ~ok ~ko -> function Opaque -> ok | _ -> ko ()));
K("expand","",N,
B Expand,
M (fun ~ok ~ko -> function Expand -> ok | _ -> ko ()));
K("level","default is 0, aka transparent",A(B.int,N),
B (fun x -> Level x),
M (fun ~ok ~ko -> function Level x -> ok x | _ -> ko ()));
]
} |> CConv.(!<)
let reduction_kind = let open API.AlgebraicData in let open RedFlags in declare {
ty = Conv.TyName "coq.redflag";
doc = "Flags for lazy, cbv, ... reductions";
pp = (fun fmt (x : red_kind) -> Format.fprintf fmt "TODO");
constructors = [
K ("coq.redflags.beta", "",N,
B fBETA,
M (fun ~ok ~ko x -> if x = fBETA then ok else ko ()));
K ("coq.redflags.delta", "if set then coq.redflags.const disables unfolding",N,
B fDELTA,
M (fun ~ok ~ko x -> if x = fDELTA then ok else ko ()));
K ("coq.redflags.match", "",N,
B fMATCH,
M (fun ~ok ~ko x -> if x = fMATCH then ok else ko ()));
K ("coq.redflags.fix", "",N,
B fFIX,
M (fun ~ok ~ko x -> if x = fFIX then ok else ko ()));
K ("coq.redflags.cofix", "",N,
B fCOFIX,
M (fun ~ok ~ko x -> if x = fCOFIX then ok else ko ()));
K ("coq.redflags.zeta", "",N,
B fZETA,
M (fun ~ok ~ko x -> if x = fZETA then ok else ko ()));
K("coq.redflags.const","enable/disable unfolding",A(constant,N),
B (function Constant x -> fCONST x | Variable x -> fVAR x),
M (fun ~ok ~ko x -> nYI "readback for coq.redflags.const"));
]
} |> CConv.(!<)
let module_item = let open API.AlgebraicData in declare {
ty = Conv.TyName "module-item";
doc = "Contents of a module";
pp = (fun fmt a -> Format.fprintf fmt "TODO");
constructors = [
K("submodule","",A(modpath,C(CConv.(!>>) B.list,N)),
B (fun s l -> Module(s,l) ),
M (fun ~ok ~ko -> function Module(s,l) -> ok s l | _ -> ko ()));
K("module-type","",A(modtypath,N),
B (fun s -> ModuleType s),
M (fun ~ok ~ko -> function ModuleType s -> ok s | _ -> ko ()));
K("gref","",A(gref,N),
B (fun s -> Gref s),
M (fun ~ok ~ko -> function Gref x -> ok x | _ -> ko ()));
K("module-functor","",A(modpath,A(B.list modtypath,N)),
B (fun s a -> Functor(s,a)),
M (fun ~ok ~ko -> function Functor(s,a) -> ok s a | _ -> ko ()));
K("module-type-functor","",A(modtypath,A(B.list modtypath,N)),
B (fun s a -> FunctorType(s,a)),
M (fun ~ok ~ko -> function FunctorType(s,a) -> ok s a | _ -> ko ()));
]
} |> CConv.(!<)
let warning = CWarnings.create ~name:"lib" ~category:elpi_cat Pp.str
let keep x = (x = Pred.Keep)
let if_keep x f =
match x with
| Pred.Discard -> None
| Pred.Keep -> Some (f ())
let _if_keep_acc x state f =
match x with
| Pred.Discard -> state, None
| Pred.Keep ->
let state, x = f state in
state, Some x
let gr2id state gr =
let open GlobRef in
match gr with
| VarRef v ->
(Id.to_string v)
| ConstRef c ->
(Id.to_string (Label.to_id (Constant.label c)))
| IndRef (i,j) ->
let open Declarations in
let env = get_global_env state in
let { mind_packets } = Environ.lookup_mind i env in
(Id.to_string (mind_packets.(j).mind_typename))
| ConstructRef ((i,k),j) ->
let open Declarations in
let env = get_global_env state in
let { mind_packets } = Environ.lookup_mind i env in
(Id.to_string (mind_packets.(k).mind_consnames.(j-1)))
let ppbox = let open Conv in let open Pp in let open API.AlgebraicData in declare {
ty = TyName "coq.pp.box";
doc = {|Coq box types for pretty printing:
- Vertical block: each break leads to a new line
- Horizontal block: no line breaking
- Horizontal-vertical block: same as Vertical block, except if this block
is small enough to fit on a single line in which case it is the same
as a Horizontal block
- Horizontal or Vertical block: breaks lead to new line only when
necessary to print the content of the block (the contents flow
inside the box)|};
pp = (fun fmt _ -> Format.fprintf fmt "<todo>");
constructors = [
K("coq.pp.v","",A(B.int,N),
B (fun i -> Pp_vbox i),
M (fun ~ok ~ko -> function Pp_vbox i -> ok i | _ -> ko ()));
K("coq.pp.h","",N,
B Pp_hbox,
M (fun ~ok ~ko -> function Pp_hbox -> ok | _ -> ko ()));
K("coq.pp.hv","",A(B.int,N),
B (fun i -> Pp_hvbox i),
M (fun ~ok ~ko -> function Pp_hvbox i -> ok i | _ -> ko ()));
K("coq.pp.hov","",A(B.int,N),
B (fun i -> Pp_hovbox i),
M (fun ~ok ~ko -> function Pp_hovbox i -> ok i | _ -> ko ()));
]
} |> CConv.(!<)
let ppboxes = let open Conv in let open Pp in let open API.AlgebraicData in declare {
ty = TyName "coq.pp";
doc = {|Coq box model for pretty printing. Items:
- empty
- spc: a spacem, also a breaking hint
- str: a non breakable string
- brk L I: a breaking hint of a given length L contributing I spaces to
indentation when taken
- glue: puts things together
- box B: a box with automatic line breaking according to B
- comment: embedded \\n are turned into nl (see below)
- tag: ignored
- nl: break the line (should not be used)|};
pp = (fun fmt _ -> Format.fprintf fmt "<todo>");
constructors = [
K("coq.pp.empty","",N,
B Ppcmd_empty,
M (fun ~ok ~ko -> function Ppcmd_empty -> ok | _ -> ko ()));
K("coq.pp.spc","",N,
B (Ppcmd_print_break(1,0)),
M (fun ~ok ~ko -> function Ppcmd_print_break(1,0) -> ok | _ -> ko ()));
K("coq.pp.str","",A(B.string,N),
B (fun s -> Ppcmd_string s),
M (fun ~ok ~ko -> function Ppcmd_string s -> ok s | _ -> ko ()));
K("coq.pp.brk","",A(B.int,A(B.int,N)),
B (fun i j -> Ppcmd_print_break(i,j)),
M (fun ~ok ~ko -> function Ppcmd_print_break(i,j) -> ok i j | _ -> ko ()));
K("coq.pp.glue","",C((fun pp -> CConv.(!>>) B.list pp),N),
B (fun l -> Ppcmd_glue (List.map Pp.unrepr l)),
M (fun ~ok ~ko -> function Ppcmd_glue l -> ok (List.map Pp.repr l) | _ -> ko ()));
K("coq.pp.box","",A(ppbox,C((fun pp -> CConv.(!>>) B.list pp),N)),
B (fun b l -> Ppcmd_box(b,Pp.unrepr @@ Ppcmd_glue (List.map Pp.unrepr l))),
M (fun ~ok ~ko -> function
| Ppcmd_box(b,x) ->
begin match Pp.repr x with
| Ppcmd_glue l -> ok b (List.map Pp.repr l)
| x -> ok b [x]
end
| _ -> ko ()));
K("coq.pp.comment","",A(B.list B.string,N),
B (fun l -> Ppcmd_comment l),
M (fun ~ok ~ko -> function Ppcmd_comment l -> ok l | _ -> ko ()));
K("coq.pp.tag","",A(B.string,S N),
B (fun b x -> Ppcmd_tag(b,Pp.unrepr x)),
M (fun ~ok ~ko -> function Ppcmd_tag(b,x) -> ok b (Pp.repr x) | _ -> ko ()));
K("coq.pp.nl","",N,
B Ppcmd_force_newline,
M (fun ~ok ~ko -> function Ppcmd_force_newline -> ok | _ -> ko ()));
]
} |> CConv.(!<)
let warn_deprecated_add_axiom =
CWarnings.create
~name:"elpi.add-const-for-axiom-or-sectionvar"
~category:elpi_depr_cat
Pp.(fun () ->
strbrk ("elpi: Using coq.env.add-const for declaring axioms or " ^
"section variables is deprecated. Use coq.env.add-axiom or " ^
"coq.env.add-section-variable instead"))
let comAssumption_declare_variable id coe ~kind ty ~univs ~impargs impl ~name:_ =
ComAssumption.declare_variable ~coe ~kind ty ~univs ~impargs ~impl ~name:id
let comAssumption_declare_axiom coe ~local ~kind ~univs ~impargs ~inline ~name:_ ~id ty =
ComAssumption.declare_axiom ~coe ~local ~kind ~univs ~impargs ~inline ~name:id ty
let declare_mutual_inductive_with_eliminations ~primitive_expected ~default_dep_elim x y z =
DeclareInd.declare_mutual_inductive_with_eliminations ~primitive_expected ~default_dep_elim x y z
let cinfo_make _ _ _using =
Declare.CInfo.make
let eval_of_constant c =
match c with
| Variable v -> Evaluable.EvalVarRef v
| Constant c ->
match Structures.PrimitiveProjections.find_opt c with
| None -> Evaluable.EvalConstRef c
| Some p -> Evaluable.EvalProjectionRef p
let eval_to_oeval = Evaluable.to_kevaluable
let mkCLocalAssum x y z = Constrexpr.CLocalAssum(x,None,y,z)
let pattern_of_glob_constr env g = Patternops.pattern_of_glob_constr env g
[%%if coq = "8.20"]
let declare_definition hack using ~cinfo ~info ~opaque ~body sigma =
let using = Option.map Proof_using.using_from_string using in
let gr = Declare.declare_definition ~cinfo ~info ~opaque ~body ?using sigma in
gr, Option.get !hack
[%%else]
let declare_definition _ using ~cinfo ~info ~opaque ~body sigma =
let using = Option.map Proof_using.using_from_string using in
Declare.declare_definition_full ~cinfo ~info ~opaque ~body ?using sigma
[%%endif]
[%%if coq = "8.20"]
let warns_of_options options = options.user_warns
[%%else]
let warns_of_options options = options.user_warns |> Option.map UserWarn.with_empty_qf
[%%endif]
let add_axiom_or_variable api id ty local options state =
let state, poly, cumul, udecl, _ = poly_cumul_udecl_variance_of_options state options in
let used = universes_of_term state ty in
let sigma = restricted_sigma_of used state in
if cumul then
err Pp.(str api ++ str": unsupported attribute @udecl-cumul! or @univpoly-cumul!");
if poly && local then
err Pp.(str api ++ str": section variables cannot be universe polymorphic");
let univs = UState.check_univ_decl (Evd.evar_universe_context sigma) udecl ~poly in
let kind = Decls.Logical in
let impargs = [] in
let loc = to_coq_loc @@ State.get Coq_elpi_builtins_synterp.invocation_site_loc state in
let id = Id.of_string id in
let name = CAst.(make ~loc id) in
if not (is_ground sigma ty) then
err Pp.(str"coq.env.add-const: the type must be ground. Did you forge to call coq.typecheck-indt-decl?");
let gr, _ =
if local then begin
Dumpglob.dump_definition name true "var";
comAssumption_declare_variable id Vernacexpr.NoCoercion ~kind (EConstr.to_constr sigma ty) ~univs ~impargs Glob_term.Explicit ~name
end else begin
Dumpglob.dump_definition name false "ax";
comAssumption_declare_axiom Vernacexpr.NoCoercion ~local:Locality.ImportDefaultBehavior ~kind (EConstr.to_constr sigma ty)
~univs ~impargs ~inline:options.inline ~name ~id
end
in
let ucsts = match univs with UState.Monomorphic_entry x, _ -> x | _ -> Univ.ContextSet.empty in
gr, ucsts
;;
type tac_abbrev = {
abbrev_name : qualified_name;
tac_name : qualified_name;
tac_fixed_args : Coq_elpi_arg_HOAS.Tac.glob list;
}
type ('a,'d) gbpmp = Gbpmp : ('d, _, 'b, Loc.t -> 'd) Pcoq.Rule.t * ('a -> 'b) -> ('a,'d) gbpmp
let rec gbpmp f = function
| [x] -> Gbpmp (Pcoq.Rule.next Pcoq.Rule.stop (Pcoq.Symbol.token (Tok.PIDENT(Some x))), (fun a _ -> f a))
| x :: xs ->
let Gbpmp (r, f) = gbpmp f xs in
Gbpmp (Pcoq.Rule.next r (Pcoq.Symbol.token (Tok.PFIELD (Some x))), (fun a _ -> f a))
| [] -> assert false
let cache_abbrev_for_tac { abbrev_name; tac_name = tacname; tac_fixed_args = more_args } =
let action args loc =
let open Ltac_plugin in
let tac =
let open Tacexpr in
let elpi_tac = {
mltac_plugin = "coq-elpi.elpi";
mltac_tactic = "elpi_tac"; } in
let elpi_tac_entry = {
mltac_name = elpi_tac;
mltac_index = 0; } in
let more_args = more_args |> List.map (function
| Coq_elpi_arg_HOAS.Tac.Int _ as t -> t
| Coq_elpi_arg_HOAS.Tac.String _ as t -> t
| Coq_elpi_arg_HOAS.Tac.Term (t,_) ->
let expr = Constrextern.extern_glob_constr Constrextern.empty_extern_env t in
let rec aux () ({ CAst.v } as orig) = match v with
| Constrexpr.CEvar _ -> CAst.make @@ Constrexpr.CHole(None)
| _ -> Constrexpr_ops.map_constr_expr_with_binders (fun _ () -> ()) aux () orig in
Coq_elpi_arg_HOAS.Tac.Term (aux () expr)
| _ -> assert false) in
let tacname = loc, tacname in