forked from LPCIC/coq-elpi
-
Notifications
You must be signed in to change notification settings - Fork 0
/
coq-builtin.elpi
2248 lines (1773 loc) · 89.5 KB
/
coq-builtin.elpi
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 terms as the object language of elpi and basic API to access Coq
% license: GNU Lesser General Public License Version 2.1 or later
% -------------------------------------------------------------------------
% This file is automatically generated from
% - coq-HOAS.elpi
% - coq_elpi_builtin.ml
% and contains the description of the data type of Coq terms and the
% API to access Coq.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%% coq-arg-HOAS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This section contains the low level data types linking Coq and elpi.
% In particular the entry points for commands
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Entry points
%
% Command and tactic invocation
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Entry point for commands. Eg. "#[att=true] Elpi mycommand foo 3 (f x)." becomes
% main [str "foo", int 3, trm (app[f,x])]
% in a context where
% attributes [attribute "att" (leaf "true")]
% holds. The encoding of terms is described below.
% See also the coq.parse-attributes utility.
pred main i:list argument.
pred main-interp i:list argument, i:any.
pred main-synterp i:list argument, o:any.
pred usage.
pred attributes o:list attribute.
% see coq-lib.elpi for coq.parse-attributes generating the options below
type get-option string -> A -> prop.
% The data type of arguments (for commands or tactics)
kind argument type.
type int int -> argument. % Eg. 1 -2.
type str string -> argument. % Eg. x "y" z.w. or any Coq keyword/symbol
type trm term -> argument. % Eg. (t).
type open-trm int -> term -> argument.
% Extra arguments for commands. [Definition], [Axiom], [Record] and [Context]
% take precedence over the [str] argument above (when not "quoted").
%
% Eg. Record or Inductive
type indt-decl indt-decl -> argument.
% Eg. #[universes(polymorphic,...)] Record or Inductive
type upoly-indt-decl indt-decl -> upoly-decl -> argument.
type upoly-indt-decl indt-decl -> upoly-decl-cumul -> argument.
% Eg. Definition or Axiom (when the body is none)
type const-decl id -> option term -> arity -> argument.
% Eg. #[universes(polymorphic,...)] Definition or Axiom
type upoly-const-decl id -> option term -> arity -> upoly-decl -> argument.
% Eg. Context A (b : A).
type ctx-decl context-decl -> argument.
% Declaration of inductive types %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
kind indt-decl type.
kind indc-decl type.
kind record-decl type.
% An arity is written, in Coq syntax, as:
% (x : T1) .. (xn : Tn) : S1 -> ... -> Sn -> U
% This syntax is used, for example, in the type of an inductive type or
% in the type of constructors. We call the abstractions on the left of ":"
% "parameters" while we call the type following the ":" (proper) arity.
% Note: in some contexts, like the type of an inductive type constructor,
% Coq makes no distinction between these two writings
% (xn : Tn) : forall y1 : S1, ... and (xn : Tn) (y1 : S1) : ...
% while Elpi is a bit more restrictive, since it understands user directives
% such as the implicit status of an arguments (eg, using {} instead of () around
% the binder), only on parameters.
% Moreover parameters carry the name given by the user as an "id", while binders
% in terms only carry it as a "name", an irrelevant pretty pringintg hint (see
% also the HOAS of terms). A user command can hence only use the names of
% parameters, and not the names of "forall" quantified variables in the arity.
%
% See also the arity->term predicate in coq-lib.elpi
kind arity type.
type parameter id -> implicit_kind -> term -> (term -> arity) -> arity.
type arity term -> arity.
type parameter id -> implicit_kind -> term -> (term -> indt-decl) -> indt-decl.
type inductive id -> bool -> arity -> (term -> list indc-decl) -> indt-decl. % tt means inductive, ff coinductive
type record id -> term -> id -> record-decl -> indt-decl.
type constructor id -> arity -> indc-decl.
type field field-attributes -> id -> term -> (term -> record-decl) -> record-decl.
type end-record record-decl.
% Example.
% Remark that A is a regular parameter; y is a non-uniform parameter and t
% also features an index of type bool.
%
% Inductive t (A : Type) | (y : nat) : bool -> Type :=
% | K1 (x : A) {n : nat} : S n = y -> t A n true -> t A y true
% | K2 : t A y false
%
% is written
%
% (parameter "A" explicit {{ Type }} a\
% inductive "t" tt (parameter "y" explicit {{ nat }} _\
% arity {{ bool -> Type }})
% t\
% [ constructor "K1"
% (parameter "y" explicit {{ nat }} y\
% (parameter "x" explicit a x\
% (parameter "n" maximal {{ nat }} n\
% arity {{ S lp:n = lp:y -> lp:t lp:n true -> lp:t lp:y true }})))
% , constructor "K2"
% (parameter "y" explicit {{ nat }} y\
% arity {{ lp:t lp:y false }}) ])
%
% Remark that the uniform parameters are not passed to occurrences of t, since
% they never change, while non-uniform parameters are both abstracted
% in each constructor type and passed as arguments to t.
%
% The coq.typecheck-indt-decl API can be used to fill in implicit arguments
% an infer universe constraints in the declaration above (e.g. the hidden
% argument of "=" in the arity of K1).
%
% Note: when and inductive type declaration is passed as an argument to an
% Elpi command non uniform parameters must be separated from the uniform ones
% with a | (a syntax introduced in Coq 8.12 and accepted by coq-elpi since
% version 1.4, in Coq this separator is optional, but not in Elpi).
% Context declaration (used as an argument to Elpi commands)
kind context-decl type.
% Eg. (x : T) or (x := B), body is optional, type may be a variable
type context-item id -> implicit_kind -> term -> option term -> (term -> context-decl) -> context-decl.
type context-end context-decl.
typeabbrev field-attributes (list field-attribute).
macro @global! :- get-option "coq:locality" "global".
macro @local! :- get-option "coq:locality" "local".
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% coq-HOAS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This section contains the low level data types linking Coq and elpi.
% In particular the data type for terms and the evar_map entries (a sequent)
% and the entry points for tactics
% Entry point for tactics. Eg. "elpi mytactic foo 3 (f x)." becomes
% solve <goal> <new goals>
% Where [str "foo", int 3, trm (app[f,x])] is part of <goal>.
% The encoding of goals is described below.
% msolve is for tactics that operate on multiple goals (called via all: ).
pred solve i:goal, o:list sealed-goal.
pred msolve i:list sealed-goal, o:list sealed-goal.
% Extra arguments for tactics
type tac ltac1-tactic -> argument.
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Coq's terms
%
% Types of term formers
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% -- terms --------------------------------------------------------------------
kind term type.
type sort sort -> term. % Prop, Type@{i}
% constants: inductive types, inductive constructors, definitions
type global gref -> term.
type pglobal gref -> univ-instance -> term.
% binders: to form functions, arities and local definitions
type fun name -> term -> (term -> term) -> term. % fun x : t =>
type prod name -> term -> (term -> term) -> term. % forall x : t,
type let name -> term -> term -> (term -> term) -> term. % let x : T := v in
% other term formers: function application, pattern matching and recursion
type app list term -> term. % app [hd|args]
type match term -> term -> list term -> term. % match t p [branch])
type fix name -> int -> term -> (term -> term) -> term. % fix name rno ty bo
type primitive primitive-value -> term.
% NYI
%type cofix name -> term -> (term -> term) -> term. % cofix name ty bo
% Notes about (match Scrutinee TypingFunction Branches) when
% Inductive i A : A -> nat -> Type := K : forall a : A, i A a 0
% and
% Scrutinee be a term of type (i bool true 7)
%
% - TypingFunction has a very rigid shape that depends on i. Namely
% as many lambdas as indexes plus one lambda for the inductive itself
% where the value of the parameters are taken from the type of the scrutinee:
% fun `a` (indt "bool") a\
% fun `n` (indt "nat) n\
% fun `i` (app[indt "i", indt "bool", a n) i\ ..
% Such spine of fun cannot be omitted; else elpi cannot read the term back.
% See also coq.bind-ind-arity-no-let in coq-lib.elpi, that builds such spine for you,
% or the higher level api coq.build-match (same file) that also takes
% care of branches.
% - Branches is a list of terms, the order is the canonical one (the order
% of the constructors as they were declared). If the constructor has arguments
% (excluding the parameters) then the corresponding term shall be a Coq
% function. In this case
% fun `x` (indt "bool") x\ ..
% -- helpers ------------------------------------------------------------------
macro @cast T TY :- (let `cast` TY T x\x).
% -- misc ---------------------------------------------------------------------
% When one writes Constraint Handling Rules unification variables are "frozen",
% i.e. represented by a fresh constant (the evar key) and a list of terms
% (typically the variables in scope).
kind evarkey type.
type uvar evarkey -> list term -> term.
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Coq's evar_map
%
% Context and evar declaration
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% An evar_info (displayed as a Coq goal) is essentially a sequent:
%
% x : t
% y := v : x
% ----------
% p x y
%
% is coded as an Elpi query
%
% pi x1\ decl x1 `x` <t> =>
% pi x2\ def x2 `y` x1 <v> =>
% declare-evar
% [def x2 `y` x1 <v> , decl x1 `x` <t>]
% (RawEvar x1 x2) (<p> x1 x2) (Ev x1 x2)
%
% where, by default, declare-evar creates a syntactic constraint as
%
% {x1 x2} :
% decl x1 `x` <t>, def x2 `y` x1 <v> ?-
% evar (RawEvar x1 x2) (<p> x1 x2) (Ev x1 x2) /* suspended on RawEvar, Ev */
%
% When the program is over, a remaining syntactic constraint like the one above
% is read back and transformed into the corresponding evar_info.
pred decl i:term, o:name, o:term. % Var Name Ty
pred def i:term, o:name, o:term, o:term. % Var Name Ty Bo
pred declare-evar i:list prop, i:term, i:term, i:term. % Ctx RawEvar Ty Evar
:name "default-declare-evar"
declare-evar Ctx RawEv Ty Ev :-
declare_constraint (declare-evar Ctx RawEv Ty Ev) [RawEv].
% When a goal (evar _ _ _) is turned into a constraint the context is filtered
% to only contain decl, def, pp. For now no handling rules for this set of
% constraints other than one to remove a constraint
pred rm-evar i:term, i:term.
rm-evar (uvar as X) (uvar as Y):- !, declare_constraint (rm-evar X Y) [X,Y].
rm-evar _ _.
constraint declare-evar evar def decl cache rm-evar {
% Override the actual context
rule \ (declare-evar Ctx RawEv Ty Ev) <=> (Ctx => evar RawEv Ty Ev).
rule \ (rm-evar (uvar X _) (uvar Y _)) (evar (uvar X _) _ (uvar Y _)).
rule \ (rm-evar (uvar X _) (uvar Y _)).
}
% The (evar R Ty E) predicate suspends when R and E are flexible,
% and is solved otherwise.
% The client may want to provide an alternative implementation of
% the clause "default-assign-evar", for example to typechecks that the
% term assigned to E has type Ty, or that the term assigned to R
% elaborates to a term of type Ty that gets assigned to E.
% In tactic mode, elpi/coq-elaborator.elpi wires things up that way.
pred evar i:term, i:term, o:term. % Evar Ty RefinedSolution
evar (uvar as X) T S :- var S _ VL, !,
prune T VL, prune X VL, declare_constraint (evar X T S) [X, S].
:name "default-assign-evar"
evar _ _ _. % volatile, only unresolved evars are considered as evars
% To ease the creation of a context with decl and def
% Eg. @pi-decl `x` <t> x1\ @pi-def `y` <t> <v> y\ ...
macro @pi-decl N T F :- pi x\ decl x N T => F x.
macro @pi-def N T B F :- pi x\ def x N T B => cache x B_ => F x.
macro @pi-parameter ID T F :-
sigma N\ (coq.id->name ID N, pi x\ decl x N T => F x).
macro @pi-inductive ID A F :-
sigma N\ (coq.id->name ID N, coq.arity->term A T, pi x\ decl x N T => F x).
% Sometimes it can be useful to pass to Coq a term with unification variables
% representing "untyped holes" like an implicit argument _. In particular
% a unification variable may exit the so called pattern fragment (applied
% to distinct variables) and hence cannot be reliably mapped to Coq as an evar,
% but can still be considered as an implicit argument.
% By loading in the context get-option "HOAS:holes" tt one forces that
% behavior. Here a convenience macro to be put on the LHS of =>
macro @holes! :- get-option "HOAS:holes" tt.
% Similarly, some APIs take a term skeleton in input. In that case unification
% variables are totally disregarded (not even mapped to Coq evars). They are
% interpreted as the {{ lib:elpi.hole }} constant, which represents an implicit
% argument. As a consequence these APIs don't modify the input term at all, but
% rather return a copy. Note that if {{ lib:elpi.hole }} is used directly, then
% it has to be applied to all variables in scope, since Coq erases variables
% that are not used. For example using {{ forall x : nat, lib:elpi.hole }} as
% a term skeleton is equivalent to {{ nat -> lib:elpi.hole }}, while
% {{ forall x : nat, lib:elpi.hole x lib:elpi.hole more args }} puts x in
% the scope of the hole (and passes to is more args).
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Coq's goals and tactic invocation
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% A Coq goal is essentially a sequent, like the evar_info above, but since it
% has to be manipulated as first class Elpi data, it is represented in a slightly
% different way. For example
%
% x : t
% y := v : x
% ----------
% g x y
%
% is represented by the following term of type sealed-goal
%
% nabla x1\
% nabla x2\
% seal
% (goal
% [def x2 `y` x1 <v> , decl x1 `x` <t>]
% (RawEvar x1 x2) (<g> x1 x2) (Evar x1 x2)
% (Arguments x1 x2))
kind goal type.
kind sealed-goal type.
type nabla (term -> sealed-goal) -> sealed-goal.
type seal goal -> sealed-goal.
typeabbrev goal-ctx (list prop).
type goal goal-ctx -> term -> term -> term -> list argument -> goal.
% A sealed-goal closes with nabla the bound names of a
%
% (goal Ctx RawSolution Ty Solution Arguments)
%
% where Ctx is a list of decl or def and Solution is a unification variable
% to be assigned to a term of type Ty in order to make progress.
% RawSolution is used as a trigger: when a term is assigned to it, it is
% elaborated against Ty and the resulting term is assigned to Solution.
%
% Arguments contains data attached to the goal, which lives in its context
% and can be used by tactics to solve the goals.
% A tactic (an elpi predicate which makes progress on a Coq goal) is
% a predicate of type
% sealed-goal -> list sealed-goal -> prop
%
% while the main entry point for a tactic written in Elpi is solve
% which has type
% goal -> list sealed-goal -> prop
%
% The utility (coq.ltac.open T G GL) postulates all the variables bounds
% by nabla and loads the goal context before calling T on the unsealed
% goal. The invocation of a tactic with arguments
% 3 x "y" (h x)
% on the previous goal results in the following Elpi query:
%
% (pi x1\ decl x1 `x` <t> =>
% pi x2\ def x2 `y` x1 <v> =>
% declare-evar
% [def x2 `y` x1 <v> , decl x1 `x` <t>]
% (RawEvar x1 x2) (<g> x1 x2) (Evar x1 x2)),
% (coq.ltac.open solve
% (nabla x1\ nabla x2\ seal
% (goal
% [def x2 `y` x1 <v> , decl x1 `x` <t>]
% (RawEvar x1 x2) (<g> x1 x2) (Evar x1 x2)
% [int 3, str `x`, str`y`, trm (app[const `h`,x1])]))
% NewGoals)
%
% If the goal sequent contains other evars, then a tactic invocation is
% an Elpi query made of the conjunction of all the declare-evar queries
% corresponding to these evars and the query corresponding to the goal
% sequent. NewGoals can be assigned to a list of goals that should be
% declared as open. Omitted goals are shelved. If NewGoals is not
% assigned, then all unresolved evars become new goals, but the order
% of such goals is not specified.
% The file elpi-ltac.elpi provides a few combinators (other than coq.ltac.open)
% in the tradition of LCF tacticals. The main difference is that the arguments
% of custom written tactics must not be passed as predicate arguments but rather
% put in the goal they receive. Indeed these arguments can contain terms, and
% their bound variables cannot escape the seal. coq.ltac.set-goal-arguments
% can be used to put an argument from the current goal context into another
% goal. The coq.ltac.call utility can call Ltac1 code (written in Coq) and
% pass arguments via this mechanism.
% Last, since Elpi is already a logic programming language with primitive
% support for unification variables, most of the work of a tactic can be
% performed without using tacticals (which work on sealed goals) but rather
% in the context of the original goal. The last step is typically to call
% the refine utility with a term synthesized by the tactic or invoke some
% Ltac1 code on that term (e.g. to call vm_compute, see also the example
% on the reflexive tactic).
% ----- Multi goals tactics. ----
% Coq provides goal selectors, such as all:, to pass to a tactic more than one
% goal. In order to write such a tactic, Coq-Elpi provides another entry point
% called msolve. To be precise, if there are two goals under focus, say <g1> and
% <g2>, then all: elpi tac <t> runs the following query
%
% msolve [<g1>,<g2>] NewGoals ; % note the disjunction
% coq.ltac.all (coq.ltac.open solve) [<g1>,<g2>] NewGoals
%
% So, if msolve has no clause, Coq-Elpi will use solve on all the goals
% independently. If msolve has a clause, then it can manipulate the entire list
% of sealed goals. Note that the argument <t> is in both <g1> and <g2> but
% it is interpreted in both contexts independently. If both goals have a proof
% variable named "x" then passing (@eq_refl _ x) as <t> equips both goals with
% a (raw) proof that "x = x", no matter what their type is.
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Declarations for Coq's API (environment read/write access, etc).
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% tt = Yes, ff = No, unspecified = No (unspecified means "_" or a variable).
typeabbrev opaque? bool. macro @opaque! :- tt. macro @transparent! :- ff.
%%%%%%% Attributes to be passed to APIs as in @local! => coq.something %%%%%%%%
macro @primitive! :- get-option "coq:primitive" tt. % primitive records
macro @reversible! :- get-option "coq:reversible" tt. % coercions
macro @no-tc! :- get-option "coq:no_tc" tt. % skip typeclass inference
macro @uinstance! I :- get-option "coq:uinstance" I. % universe instance
% declaration of universe polymorphic constants
% The first list is the one of the universe variables being bound
% The first boolean is tt if this list can be extended by Coq (or it has to
% mention all universes actually used)
% The second list is the one with the constraints amond where universes
% The second boolean is tt if this list can be extended by Coq or it has to
% mention all universe constraints actually required to type check the
% declaration)
macro @udecl! Vs LV Cs LC :- get-option "coq:udecl" (upoly-decl Vs LV Cs LC).
macro @udecl-cumul! Vs LV Cs LC :- get-option "coq:udecl-cumul" (upoly-decl-cumul Vs LV Cs LC).
macro @univpoly! :- @udecl! [] tt [] tt.
macro @univpoly-cumul! :- @udecl-cumul! [] tt [] tt.
macro @ppwidth! N :- get-option "coq:ppwidth" N. % printing width
macro @ppall! :- get-option "coq:pp" "all". % printing all
macro @ppmost! :- get-option "coq:pp" "most". % printing most of contents
macro @pplevel! N :- get-option "coq:pplevel" N. % printing precedence (for parentheses)
macro @keepunivs! :- get-option "coq:keepunivs" tt. % skeletons elaboration
macro @dropunivs! :- get-option "coq:keepunivs" ff. % add-indt/add-const
macro @using! S :- get-option "coq:using" S. % like the #[using=S] attribute
macro @inline-at! N :- get-option "coq:inline" (coq.inline.at N). % like Inline(N)
macro @inline! N :- get-option "coq:inline" coq.inline.default. % like
macro @redflags! F :- get-option "coq:redflags" F. % for whd & co
% both arguments are strings eg "8.12.0" "use foo instead"
macro @deprecated! Since Msg :-
get-option "coq:deprecated" (pr Since Msg).
macro @ltacfail! N :- get-option "ltac:fail" N.
% retrocompatibility macro for Coq v8.10
macro @coercion! :- [coercion reversible].
% Attributes for a record field. Can be left unspecified, see defaults
% below.
kind field-attribute type.
type coercion coercion-status -> field-attribute. % default off
type canonical bool -> field-attribute. % default true, if field is named
% Status of a record field w.r.t. coercions
kind coercion-status type.
type regular coercion-status.
type reversible coercion-status.
type off coercion-status.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% builtins %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This section contains the API to access Coq
% The marker *E* means *experimental*, i.e. use at your own risk, it may change
% substantially or even disappear in future versions.
% -- Misc ---------------------------------------------------------
% [coq.info ...] Prints an info message
external type coq.info variadic any prop.
% [coq.notice ...] Prints a notice message
external type coq.notice variadic any prop.
% [coq.say ...] Prints a notice message
external type coq.say variadic any prop.
% [coq.debug ...] Prints a debug message
external type coq.debug variadic any prop.
% [coq.warn ...] Prints a generic warning message
external type coq.warn variadic any prop.
% [coq.warning Category Name ...]
% Prints a warning message with a Name and Category which can be used
% to silence this warning or turn it into an error. See coqc -w command
% line option
external type coq.warning string -> string -> variadic any prop.
% [coq.error ...] Prints and *aborts* the program. It is a fatal error for
% Elpi and Ltac
external type coq.error variadic any prop.
% [coq.version VersionString Major Minor Patch] Fetches the version of Coq,
% as a string and as 3 numbers
external pred coq.version o:string, o:int, o:int, o:int.
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% API for objects belonging to the logic
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% -- Environment: names -----------------------------------------------
% To make the API more precise we use different data types for the names
% of global objects.
% Note: [ctype "bla"] is an opaque data type and by convention it is written
% [@bla].
% Global constant name
kind constant type.
% Inductive type name
kind inductive type.
% Inductive constructor name
kind constructor type.
% Global objects: inductive types, inductive constructors, definitions
kind gref type.
type const constant -> gref. % Nat.add, List.append, ...
type indt inductive -> gref. % nat, list, ...
type indc constructor -> gref. % O, S, nil, cons, ...
% [id] is a name that matters, we piggy back on Elpi's strings.
% Note: [name] is a name that does not matter.
typeabbrev id string.
% Name of a module /*E*/
kind modpath type.
% Name of a module type /*E*/
kind modtypath type.
% Result of coq.locate-all
kind located type.
type loc-gref gref -> located.
type loc-modpath modpath -> located.
type loc-modtypath modtypath -> located.
type loc-abbreviation abbreviation -> located.
% [coq.locate-all Name Located] finds all possible meanings of a string.
% Does not fail.
external pred coq.locate-all i:id, o:list located.
% [coq.locate Name GlobalReference] locates a global definition, inductive
% type or constructor via its name.
% It unfolds syntactic notations, e.g. "Notation old_name := new_name."
% It understands qualified names, e.g. "Nat.t".
% It understands Coqlib Registered names using the "lib:" prefix,
% eg "lib:core.bool.true".
% It's a fatal error if Name cannot be located.
external pred coq.locate i:id, o:gref.
% -- Environment: read ------------------------------------------------
% Note: The type [term] is defined in coq-HOAS.elpi
% [coq.env.typeof GR Ty] reads the type Ty of a global reference.
% Supported attributes:
% - @uinstance! I (default: fresh instance I)
external pred coq.env.typeof i:gref, o:term.
% [coq.env.global GR T] turns a global reference GR into a term, or
% viceversa.
% T = (global GR) or, if GR points to a universe polymorphic term,
% T = (pglobal GR I).
% Supported attributes:
% - @uinstance! I (default: fresh instance I)
external pred coq.env.global o:gref, o:term.
external pred coq.env.indt % reads the inductive type declaration for the environment.
% Supported attributes:
% - @uinstance! I (default: fresh instance I)
i:inductive, % reference to the inductive type
o:bool, % tt if the type is inductive (ff for co-inductive)
o:int, % number of parameters
o:int, % number of parameters that are uniform (<= parameters)
o:term, % type of the inductive type constructor including parameters
o:list constructor, % list of constructor names
o:list term. % list of the types of the constructors (type of KNames) including parameters
external pred coq.env.indt-decl % reads the inductive type declaration for the environment.
% Supported attributes:
% - @uinstance! I (default: fresh instance I)
i:inductive, % reference to the inductive type
o:indt-decl. % HOAS description of the inductive type
% [coq.env.indc->indt K I N] finds the inductive I to which constructor K
% belongs and its position N among the other constructors
external pred coq.env.indc->indt i:constructor, o:inductive, o:int.
% [coq.env.indc GR ParamNo UnifParamNo Kno Ty] reads the type Ty of an
% inductive constructor GR, as well as
% the number of parameters ParamNo and uniform parameters
% UnifParamNo and the number of the constructor Kno (0 based).
% Supported attributes:
% - @uinstance! I (default: fresh instance I)
external pred coq.env.indc i:constructor, o:int, o:int, o:int, o:term.
% [coq.env.informative? Ind] Checks if Ind is informative, that is, if
% it can be eliminated to build a Type. Inductive types in Type
% are
% informative, as well a singleton types in Prop (which are
% regarded as not non-informative).
external pred coq.env.informative? i:inductive.
% [coq.env.record? Ind PrimProjs] checks if Ind is a record (PrimProjs = tt
% if Ind has primitive projections)
external pred coq.env.record? i:inductive, o:bool.
% [coq.env.recursive? Ind] checks if Ind is recursive
external pred coq.env.recursive? i:inductive.
% [coq.env.opaque? GR] checks if GR is an opaque constant
external pred coq.env.opaque? i:constant.
% [coq.env.univpoly? GR PolyArity] checks if GR is universe polymorphic and
% if so returns the number of universe variables
external pred coq.env.univpoly? i:gref, o:int.
% [coq.env.const GR Bo Ty] reads the type Ty and the body Bo of constant
% GR.
% Opaque constants have Bo = none.
% Supported attributes:
% - @uinstance! I (default: fresh instance I)
external pred coq.env.const i:constant, o:option term, o:term.
% [coq.env.const-body GR Bo] reads the body of a constant, even if it is
% opaque.
% If such body is none, then the constant is a true axiom.
% Supported attributes:
% - @uinstance! I (default: fresh instance I)
external pred coq.env.const-body i:constant, o:option term.
% [coq.env.primitive? GR] tests if GR is a primitive constant (like uin63
% addition) or a primitive type (like uint63)
external pred coq.env.primitive? i:constant.
% [coq.locate-module ModName ModPath] locates a module. It's a fatal error
% if ModName cannot be located. *E*
external pred coq.locate-module i:id, o:modpath.
% [coq.locate-module-type ModName ModPath] locates a module. It's a fatal
% error if ModName cannot be located. *E*
external pred coq.locate-module-type i:id, o:modtypath.
% Contents of a module
kind module-item type.
type submodule modpath -> list module-item -> module-item.
type module-type modtypath -> module-item.
type gref gref -> module-item.
type module-functor modpath -> list modtypath -> module-item.
type module-type-functor modtypath -> list modtypath -> module-item.
% [coq.env.module MP Contents] lists the contents of a module (recurses on
% submodules) *E*
external pred coq.env.module i:modpath, o:list module-item.
% [coq.env.module-type MTP Entries] lists the items made visible by module
% type (does not recurse on submodules) *E*
external pred coq.env.module-type i:modtypath, o:list id.
% [coq.env.section GlobalObjects] lists the global objects that are marked
% as to be abstracted at the end of the enclosing sections
external pred coq.env.section o:list constant.
% [coq.env.dependencies GR MP Deps] Computes the direct dependencies of GR.
% If MP is given, Deps only contains grefs from that module
external pred coq.env.dependencies i:gref, i:modpath, o:coq.gref.set.
% [coq.env.transitive-dependencies GR MP Deps] Computes the transitive
% dependencies of GR. If MP is given, Deps only contains grefs from that
% module
external pred coq.env.transitive-dependencies i:gref, i:modpath,
o:coq.gref.set.
% [coq.env.term-dependencies T S] Computes all the grefs S occurring in the
% term T
external pred coq.env.term-dependencies i:term, o:coq.gref.set.
% [coq.env.current-path Path] lists the current module path
external pred coq.env.current-path o:list string.
% [coq.env.current-section-path Path] lists the current section path
external pred coq.env.current-section-path o:list string.
% Deprecated, use coq.env.opaque?
pred coq.env.const-opaque? i:constant.
coq.env.const-opaque? C :-
coq.warning "elpi.deprecated" "elpi.const-opaque" "use coq.env.opaque? in place of coq.env.const-opaque?",
coq.env.opaque? C.
% Deprecated, use coq.env.primitive?
pred coq.env.const-primitive? i:constant.
coq.env.const-primitive? C :-
coq.warning "elpi.deprecated" "elpi.const-primitive" "use coq.env.primitive? in place of coq.env.const-primitive?",
coq.env.primitive? C.
% -- Environment: write -----------------------------------------------
% Note: (monomorphic) universe constraints are taken from ELPI's
% constraints store. Use coq.univ-* in order to add constraints (or any
% higher level facility as coq.typecheck). Load in the context attributes
% such as @univpoly!, @univpoly-cumul!, @udecl! or @udecl-cumul! in order to
% declare universe polymorphic constants or inductives.
% [coq.env.add-const Name Bo Ty Opaque C] Declare a new constant: C gets a
% constant derived from Name
% and the current module; Ty can be left unspecified and in that case
% the
% inferred one is taken (as in writing Definition x := t); Bo can be
% left
% unspecified and in that case an axiom is added (or a section variable,
% if a section is open and @local! is used). Omitting the body and the type
% is
% an error. Note: using this API for declaring an axiom or a section
% variable is
% deprecated, use coq.env.add-axiom or coq.env.add-section-variable
% instead.
% Supported attributes:
% - @local! (default: false)
% - @using! (default: section variables actually used)
% - @univpoly! (default unset)
% - @udecl! (default unset)
% - @dropunivs! (default: false, drops all universe constraints from the
% store after the definition)
%
external pred coq.env.add-const i:id, i:term, i:term, i:opaque?,
o:constant.
% [coq.env.add-axiom Name Ty C] Declare a new axiom: C gets a constant
% derived from Name
% and the current module.
% Supported attributes:
% - @local! (default: false)
% - @univpoly! (default unset)
% - @using! (default: section variables actually used)
% - @inline! (default: no inlining)
% - @inline-at! N (default: no inlining)
external pred coq.env.add-axiom i:id, i:term, o:constant.
% [coq.env.add-section-variable Name Ty C] Declare a new section variable: C
% gets a constant derived from Name
% and the current module.
%
external pred coq.env.add-section-variable i:id, i:term, o:constant.
% [coq.env.add-indt Decl I] Declares an inductive type.
% Supported attributes:
% - @dropunivs! (default: false, drops all universe constraints from the
% store after the definition)
% - @primitive! (default: false, makes records primitive)
external pred coq.env.add-indt i:indt-decl, o:inductive.
% Interactive module construction
% Coq Module inline directive
kind coq.inline type.
type coq.inline.no coq.inline. % Coq's [no inline] (aka !)
type coq.inline.default coq.inline. % The default, can be omitted
type coq.inline.at int -> coq.inline. % Coq's [inline at <num>]
% [coq.env.fresh-global-id ID FID] Generates an id FID which is fresh in
% the current module and looks similar to ID, i.e. it is ID concatenated
% with a number, starting from 1.
% [coq.env.fresh-global-id X X] can be used to check if X is taken
external pred coq.env.fresh-global-id i:id, o:id.
external pred coq.env.begin-module-functor % Starts a functor. bla bla
i:id, % The name of the functor
i:option modtypath, % Its module type (optional)
i:list (pair id modtypath). % Parameters of the functor (optional)
pred coq.env.begin-module i:id, i:option modtypath.
coq.env.begin-module Name MP :- coq.env.begin-module-functor Name MP [].
% [coq.env.end-module ModPath] end the current module that becomes known as
% ModPath *E*. bla bla
external pred coq.env.end-module o:modpath.
external pred coq.env.begin-module-type-functor % Starts a module type functor *E*. bla bla
i:id, % The name of the functor
i:list (pair id modtypath). % The parameters of the functor (optional)
pred coq.env.begin-module-type i:id.
coq.env.begin-module-type Name :-
coq.env.begin-module-type-functor Name [].
% [coq.env.end-module-type ModTyPath] end the current module type that
% becomes known as ModPath *E*. bla bla
external pred coq.env.end-module-type o:modtypath.
external pred coq.env.apply-module-functor % Applies a functor *E*. bla bla
i:id, % The name of the new module
i:option modtypath, % Its module type (optional)
i:modpath, % The functor being applied (optional)
i:list modpath, % Its arguments (optional)
i:coq.inline, % Arguments inlining (optional)
o:modpath. % The modpath of the new module
external pred coq.env.apply-module-type-functor % Applies a type functor *E*. bla bla
i:id, % The name of the new module type
i:modtypath, % The functor (optional)
i:list modpath, % Its arguments (optional)
i:coq.inline, % Arguments inlining (optional)
o:modtypath. % The modtypath of the new module type
% [coq.env.include-module ModPath Inline (optional)] is like the vernacular
% Include, Inline can be omitted *E*. bla bla
external pred coq.env.include-module i:modpath, i:coq.inline.
% [coq.env.include-module-type ModTyPath Inline (optional)] is like the
% vernacular Include Type, Inline can be omitted *E*. bla bla
external pred coq.env.include-module-type i:modtypath, i:coq.inline.
% [coq.env.import-module ModPath] is like the vernacular Import *E*
external pred coq.env.import-module i:modpath.
% [coq.env.export-module ModPath] is like the vernacular Export *E*
external pred coq.env.export-module i:modpath.
% Support for sections is limited, in particular sections and
% Coq quotations may interact in surprising ways. For example
% Section Test.
% Variable x : nat.
% Elpi Query lp:{{ coq.say {{ x }} }}.
% works since x is a global Coq term while
% Elpi Query lp:{{
% coq.env.begin-section "Test",
% coq.env.add-const "x" _ {{ nat }} _ @local! GRX,
% coq.say {{ x }}
% }}.
% may work in a surprising way or may not work at all since
% x is resolved before the section is started hence it cannot
% denote the same x as before.
% [coq.env.begin-section Name] starts a section named Name *E*
external pred coq.env.begin-section i:id.
% [coq.env.end-section] end the current section *E*
external pred coq.env.end-section .
% [coq.env.projections StructureName Projections] given a record
% StructureName lists all projections
external pred coq.env.projections i:inductive, o:list (option constant).
% [coq.env.projection? Constant Number of parameters] if the constant is a
% projection, returns the number of parameters of its record.
external pred coq.env.projection? i:constant, o:int.
% [coq.env.primitive-projections StructureName Projections] given a record
% StructureName lists all primitive projections
external pred coq.env.primitive-projections i:inductive,
o:list (option (pair projection int)).
% [coq.env.primitive-projection? Projection Compatibility constant] relates
% a projection to its compatibility constant.
external pred coq.env.primitive-projection? i:projection, o:constant.
% -- Sorts (and their universe level, if applicable) ----------------
% Warning: universe polymorphism has to be considered experimental *E* as
% a feature, not just as a set of APIs. Unfortunately some of the
% current complexity is exposed to the programmer, bare with us.
%
% The big bang is that in Coq one has terms, types and sorts (which are
% the types of types). Some sorts (as of today only Type) some with
% a universe level, on paper Type_i for some i. At the sort level
% Coq features some form of subtyping: a function expecting a function
% to Type, e.g. nat -> Type, can receive a function to Prop, since
% Prop <= Type. So far, so good. But what are these levels i
% exactly?
%
% Universe levels are said to be "algebraic", they are made of
% variables (see the next section) and the two operators +1 and max.
% This is a sort of internal optimization that leaks to the
% user/programmer. Indeed these universe levels cannot be (directly) used
% in all APIs morally expecting a universe level "i", in particular
% the current constraint engine cannot handle constraint with an
% algebraic level on the right, e.g. i <= j+1. Since some APIs only
% accept universe variables, we provide the coq.univ.variable API
% which is able to craft a universe variable which is roughly
% equivalent to an algebraic universe, e.g. k such that j+1 = k.
%
% Coq-Elpi systematically purges algebraic universes from terms (and
% types and sorts) when one reads them from the environment. This
% makes the embedding of terms less precise than what it could be.
% The different data types stay, since Coq will eventually become
% able to handle algebraic universes consistently, making this purging
% phase unnecessary.
% universe level (algebraic: max, +1, univ.variable)
kind univ type.
% Sorts (kinds of types)
kind sort type.
type prop sort. % impredicative sort of propositions
type sprop sort. % impredicative sort of propositions with definitional proof irrelevance
type typ univ ->
sort. % predicative sort of data (carries a universe level)
% [coq.sort.leq S1 S2] constrains S1 <= S2
external pred coq.sort.leq o:sort, o:sort.
% [coq.sort.eq S1 S2] constrains S1 = S2
external pred coq.sort.eq o:sort, o:sort.
% [coq.sort.sup S1 S2] constrains S2 = S1 + 1
external pred coq.sort.sup o:sort, o:sort.
% [coq.sort.pts-triple S1 S2 S3] constrains S3 = sort of product with domain
% in S1 and codomain in S2
external pred coq.sort.pts-triple o:sort, o:sort, o:sort.
% [coq.univ.print] prints the set of universe constraints
external pred coq.univ.print .
% [coq.univ.new U] A fresh universe.
external pred coq.univ.new o:univ.
% [coq.univ Name U] Finds a named unvierse. Can fail.
external pred coq.univ o:id, o:univ.
% [coq.univ.global? U] succeeds if U is a global universe
external pred coq.univ.global? i:univ.
% [coq.univ.constraints CL] gives the list of constraints, see also
% coq.univ.variable.constraints
external pred coq.univ.constraints o:list univ-constraint.