Skip to content

Commit 81ff5f5

Browse files
authored
Merge pull request #804 from lweqx/keep-alg-univs
Add coq.univ.alg-super, @keep-alg-univs!
2 parents a0fad1e + a1d6264 commit 81ff5f5

File tree

9 files changed

+175
-103
lines changed

9 files changed

+175
-103
lines changed

Changelog.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@
55
- derive: support for `is_true` in `param1_trivial` (based on pre-existing
66
special support for `is_eq` and `is_bool`)
77

8+
### API
9+
- New `coq.univ.alg-super` that relates a univ `U` to its algebraic successor
10+
`V`, that is `U+1` and not any `V` s.t. `U < V`
11+
12+
### HOAS
13+
- New `@keep-alg-univs!` option for all APIs taking terms. By default algebraic
14+
universes are replaced by named universes. See the `coq.univ.alg-super` API.
15+
816
# [2.5.0] 18/2/2025
917

1018
Requires Elpi 2.0.7 and Coq 8.20 or Rocq 9.0.

builtin-doc/coq-builtin.elpi

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,8 @@ typeabbrev opaque? bool. macro @opaque! :- tt. macro @transparent! :- ff.
454454

455455
%%%%%%% Attributes to be passed to APIs as in @local! => coq.something %%%%%%%%
456456

457+
macro @keep-alg-univs! :- get-option "coq:keepalgunivs" tt.
458+
457459
macro @primitive! :- get-option "coq:primitive" tt. % primitive records
458460
macro @reversible! :- get-option "coq:reversible" tt. % coercions
459461
macro @no-tc! :- get-option "coq:no_tc" tt. % skip typeclass inference
@@ -978,8 +980,7 @@ kind univ type.
978980
kind sort type.
979981
type prop sort. % impredicative sort of propositions
980982
type sprop sort. % impredicative sort of propositions with definitional proof irrelevance
981-
type typ univ ->
982-
sort. % predicative sort of data (carries a universe level)
983+
type typ univ -> sort. % predicative sort of data (carries a universe level)
983984

984985
% [coq.sort.leq S1 S2] constrains S1 <= S2
985986
external pred coq.sort.leq o:sort, o:sort.
@@ -1000,6 +1001,10 @@ external pred coq.univ.print .
10001001
% [coq.univ.new U] A fresh universe.
10011002
external pred coq.univ.new o:univ.
10021003

1004+
% [coq.univ.alg-super U V] relates a univ U to its algebraic successor V,
1005+
% that is U+1 and not any V s.t. U < V
1006+
external pred coq.univ.alg-super i:univ, o:univ.
1007+
10031008
% [coq.univ Name U] Finds a named unvierse. Can fail.
10041009
external pred coq.univ o:id, o:univ.
10051010

elpi/coq-HOAS.elpi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,8 @@ typeabbrev opaque? bool. macro @opaque! :- tt. macro @transparent! :- ff.
301301

302302
%%%%%%% Attributes to be passed to APIs as in @local! => coq.something %%%%%%%%
303303

304+
macro @keep-alg-univs! :- get-option "coq:keepalgunivs" tt.
305+
304306
macro @primitive! :- get-option "coq:primitive" tt. % primitive records
305307
macro @reversible! :- get-option "coq:reversible" tt. % coercions
306308
macro @no-tc! :- get-option "coq:no_tc" tt. % skip typeclass inference

src/rocq_elpi_HOAS.ml

Lines changed: 82 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -174,53 +174,6 @@ let isuniv, univout, univino, (univ : Univ.Universe.t API.Conversion.t) =
174174
end
175175
}
176176

177-
let propc = E.Constants.declare_global_symbol "prop"
178-
let spropc = E.Constants.declare_global_symbol "sprop"
179-
let typc = E.Constants.declare_global_symbol "typ"
180-
181-
let sort =
182-
let open API.AlgebraicData in declare {
183-
ty = API.Conversion.TyName "sort";
184-
doc = "Sorts (kinds of types)";
185-
pp = (fun fmt -> function
186-
| Sorts.Type _ -> Format.fprintf fmt "Type"
187-
| Sorts.Set -> Format.fprintf fmt "Set"
188-
| Sorts.Prop -> Format.fprintf fmt "Prop"
189-
| Sorts.SProp -> Format.fprintf fmt "SProp"
190-
| Sorts.QSort _ -> Format.fprintf fmt "Type");
191-
constructors = [
192-
K("prop","impredicative sort of propositions",N,
193-
B Sorts.prop,
194-
M (fun ~ok ~ko -> function Sorts.Prop -> ok | _ -> ko ()));
195-
K("sprop","impredicative sort of propositions with definitional proof irrelevance",N,
196-
B Sorts.sprop,
197-
M (fun ~ok ~ko -> function Sorts.SProp -> ok | _ -> ko ()));
198-
K("typ","predicative sort of data (carries a universe level)",A(univ,N),
199-
B (fun x -> Sorts.sort_of_univ x),
200-
M (fun ~ok ~ko -> function
201-
| Sorts.Type x -> ok x
202-
| Sorts.Set -> ok Univ.Universe.type0
203-
| _ -> ko ()));
204-
K("uvar","",A(F.uvar,N),
205-
BS (fun (k,_) state ->
206-
let m = S.get um state in
207-
try
208-
let u = UM.host k m in
209-
state, Sorts.sort_of_univ u
210-
with Not_found ->
211-
let state, (_,u) = new_univ_level_variable state in
212-
let state = S.update um state (UM.add k u) in
213-
state, Sorts.sort_of_univ u),
214-
M (fun ~ok ~ko _ -> ko ()));
215-
]
216-
} |> API.ContextualConversion.(!<)
217-
218-
let ast_sort ~loc = function
219-
| Sorts.Prop -> A.mkGlobal ~loc propc
220-
| Sorts.SProp -> A.mkGlobal ~loc spropc
221-
| Sorts.Set -> A.mkAppGlobal ~loc typc (A.mkOpaque ~loc @@ univino Univ.Universe.type0) []
222-
| Sorts.Type u -> A.mkAppGlobal ~loc typc (A.mkOpaque ~loc @@ univino u) []
223-
| _ -> assert false
224177

225178
let universe_level_variable =
226179
let { CD.cin = levelin }, universe_level_variable_to_patch = CD.declare {
@@ -364,6 +317,7 @@ type options = {
364317
keepunivs : bool option;
365318
redflags : RedFlags.reds option;
366319
no_tc: bool option;
320+
algunivs : bool option;
367321
}
368322
let default_options () = {
369323
hoas_holes = Some Verbatim;
@@ -382,14 +336,15 @@ let default_options () = {
382336
keepunivs = None;
383337
redflags = None;
384338
no_tc = None;
339+
algunivs = None;
385340
}
386341
let make_options ~hoas_holes ~local ~warn ~depr ~primitive ~failsafe ~ppwidth
387342
~pp ~pplevel ~using ~inline ~uinstance ~universe_decl ~reversible ~keepunivs
388-
~redflags ~no_tc =
343+
~redflags ~no_tc ~algunivs =
389344
let user_warns = Some UserWarn.{ depr; warn } in
390345
{ hoas_holes; local; user_warns; primitive; failsafe; ppwidth; pp;
391346
pplevel; using; inline; uinstance; universe_decl; reversible; keepunivs;
392-
redflags; no_tc; }
347+
redflags; no_tc; algunivs; }
393348
let make_warn = UserWarn.make_warn
394349

395350
type 'a coq_context = {
@@ -422,6 +377,67 @@ let pr_coq_ctx { env; db2name; db2rel } sigma =
422377
v 0 (Printer.pr_rel_context_of env sigma) ++ cut ()
423378
)
424379

380+
let propc = E.Constants.declare_global_symbol "prop"
381+
let spropc = E.Constants.declare_global_symbol "sprop"
382+
let typc = E.Constants.declare_global_symbol "typ"
383+
384+
385+
let sort : (Sorts.t, _ coq_context, API.Data.constraints) API.ContextualConversion.t =
386+
let open API.ContextualConversion in
387+
{
388+
ty = API.Conversion.TyName "sort";
389+
pp_doc = (fun fmt () ->
390+
Format.fprintf fmt "%% Sorts (kinds of types)\n";
391+
Format.fprintf fmt "kind sort type.\n";
392+
Format.fprintf fmt "type prop sort. %% impredicative sort of propositions\n";
393+
Format.fprintf fmt "type sprop sort. %% impredicative sort of propositions with definitional proof irrelevance\n";
394+
Format.fprintf fmt "type typ univ -> sort. %% predicative sort of data (carries a universe level)\n";
395+
);
396+
pp = (fun fmt -> function
397+
| Sorts.Type _ -> Format.fprintf fmt "Type"
398+
| Sorts.Set -> Format.fprintf fmt "Set"
399+
| Sorts.Prop -> Format.fprintf fmt "Prop"
400+
| Sorts.SProp -> Format.fprintf fmt "SProp"
401+
| Sorts.QSort _ -> Format.fprintf fmt "QSort");
402+
embed = (fun ~depth { options } _ state s ->
403+
match s with
404+
| Sorts.Prop -> state, E.mkConst propc, []
405+
| Sorts.SProp -> state, E.mkConst spropc, []
406+
| Sorts.Set ->
407+
let state, u, gls = univ.embed ~depth state Univ.Universe.type0 in
408+
state, E.mkApp typc u [], gls
409+
| Sorts.Type u ->
410+
let state, u, gls = univ.embed ~depth state u in
411+
state, E.mkApp typc u [], gls
412+
| Sorts.QSort _ -> nYI "sort polymorphism");
413+
readback = (fun ~depth { options } _ state t ->
414+
match E.look ~depth t with
415+
| E.Const c when c == propc -> state, Sorts.prop, []
416+
| E.Const c when c == spropc -> state, Sorts.sprop, []
417+
| E.App(c,u,[]) when c == typc ->
418+
let state, u, gls = univ.readback ~depth state u in
419+
state, Sorts.sort_of_univ u ,gls
420+
| E.UnifVar(k,_) -> begin
421+
let m = S.get um state in
422+
try
423+
let u = UM.host k m in
424+
state, Sorts.sort_of_univ u, []
425+
with Not_found ->
426+
let state, (_,u) = new_univ_level_variable state in
427+
let state = S.update um state (UM.add k u) in
428+
state, Sorts.sort_of_univ u, []
429+
end
430+
| _ -> raise API.Conversion.(TypeErr(TyName"sort",depth,t)));
431+
}
432+
433+
let ast_sort ~loc = function
434+
| Sorts.Prop -> A.mkGlobal ~loc propc
435+
| Sorts.SProp -> A.mkGlobal ~loc spropc
436+
| Sorts.Set -> A.mkAppGlobal ~loc typc (A.mkOpaque ~loc @@ univino Univ.Universe.type0) []
437+
| Sorts.Type u -> A.mkAppGlobal ~loc typc (A.mkOpaque ~loc @@ univino u) []
438+
| _ -> assert false
439+
440+
425441
let in_coq_fresh ~id_only =
426442
let mk_fresh dbl =
427443
Id.of_string_soft
@@ -1052,7 +1068,6 @@ let section_ids env =
10521068
~init:[] named_ctx
10531069

10541070
let sortc = E.Constants.declare_global_symbol "sort"
1055-
let typc = E.Constants.declare_global_symbol "typ"
10561071

10571072
let force_level_of_universe state u =
10581073
match Univ.Universe.level u with
@@ -1074,14 +1089,18 @@ let in_elpi_flex_sort t = E.mkApp sortc (E.mkApp typc t []) []
10741089
let in_elpiast_flex_sort ~loc t =
10751090
A.mkAppGlobal ~loc sortc (A.mkAppGlobal ~loc typc t []) []
10761091

1077-
let sort = { sort with API.Conversion.embed = (fun ~depth state s ->
1078-
let state, s = purge_algebraic_univs_sort state (EConstr.ESorts.make s) in
1079-
sort.API.Conversion.embed ~depth state s) }
1092+
let sort = { sort with API.ContextualConversion.embed = (fun ~depth ctx csts state s ->
1093+
let state, s =
1094+
if ctx.options.algunivs = None || ctx.options.algunivs = Some false then
1095+
purge_algebraic_univs_sort state (EConstr.ESorts.make s)
1096+
else
1097+
state, s in
1098+
sort.API.ContextualConversion.embed ~depth ctx csts state s) }
10801099

1081-
let in_elpi_sort ~depth state s =
1082-
let state, s, gl = sort.API.Conversion.embed ~depth state s in
1100+
let in_elpi_sort ~depth ctx csts state s =
1101+
let state, s, gl = sort.API.ContextualConversion.embed ~depth ctx csts state s in
10831102
assert(gl=[]);
1084-
state, E.mkApp sortc s []
1103+
state, E.mkApp sortc s [], gl
10851104

10861105
let in_elpiast_sort ~loc state s =
10871106
A.mkAppGlobal ~loc sortc (ast_sort ~loc s) []
@@ -1301,10 +1320,10 @@ let get_options ~depth hyps state =
13011320
let no_tc = get_bool_option "coq:no_tc" in
13021321
let keepunivs = get_bool_option "coq:keepunivs" in
13031322
let redflags = get_redflags_option () in
1323+
let algunivs = get_bool_option "coq:keepalgunivs" in
13041324
make_options ~hoas_holes ~local ~warn ~depr ~primitive ~failsafe ~ppwidth
13051325
~pp ~pplevel ~using ~inline ~uinstance ~universe_decl ~reversible ~keepunivs
1306-
~redflags ~no_tc
1307-
1326+
~redflags ~no_tc ~algunivs
13081327
let mk_coq_context ~options state =
13091328
let env = get_global_env state in
13101329
let section = section_ids env in
@@ -1452,7 +1471,10 @@ let rec constr2lp coq_ctx ~calldepth ~depth state t =
14521471
let args = CList.firstn argno args in
14531472
let state, args = CList.fold_left_map (aux ~depth env) state args in
14541473
state, E.mkUnifVar elpi_uvk ~args:(List.rev args) state
1455-
| C.Sort s -> in_elpi_sort ~depth state (EC.ESorts.kind sigma s)
1474+
| C.Sort s ->
1475+
let state, s, gl = in_elpi_sort ~depth coq_ctx API.RawData.no_constraints state (EC.ESorts.kind sigma s) in
1476+
gls := gl @ !gls;
1477+
state, s
14561478
| C.Cast (t,_,ty0) ->
14571479
let state, t = aux ~depth env state t in
14581480
let state, ty = aux ~depth env state ty0 in
@@ -1962,7 +1984,7 @@ and lp2constr ~calldepth syntactic_constraints coq_ctx ~depth state ?(on_ty=fals
19621984
debug Pp.(fun () -> str"lp2term@" ++ int depth ++ str":" ++ str(pp2string (P.term depth) t));
19631985
match E.look ~depth t with
19641986
| E.App(s,p,[]) when sortc == s ->
1965-
let state, u, gsl = sort.API.Conversion.readback ~depth state p in
1987+
let state, u, gsl = sort.API.ContextualConversion.readback ~depth coq_ctx syntactic_constraints state p in
19661988
state, EC.mkSort (EC.ESorts.make u), gsl
19671989
(* constants *)
19681990
| E.App(c,d,[]) when globalc == c ->

src/rocq_elpi_HOAS.mli

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ type options = {
4848
keepunivs : bool option;
4949
redflags : RedFlags.reds option;
5050
no_tc: bool option;
51+
algunivs : bool option;
5152
}
5253

5354
type 'a coq_context = {
@@ -154,7 +155,7 @@ val in_elpi_gr : depth:int -> State.t -> Names.GlobRef.t -> term
154155
val in_elpi_poly_gr : depth:int -> State.t -> Names.GlobRef.t -> term -> term
155156
val in_elpi_poly_gr_instance : depth:int -> State.t -> Names.GlobRef.t -> UVars.Instance.t -> term
156157
val in_elpi_flex_sort : term -> term
157-
val in_elpi_sort : depth:int -> state -> Sorts.t -> state * term
158+
val in_elpi_sort : depth:int -> 'a coq_context -> constraints -> state -> Sorts.t -> state * term * Conversion.extra_goals
158159
val in_elpi_prod : Name.t -> term -> term -> term
159160
val in_elpi_lam : Name.t -> term -> term -> term
160161
val in_elpi_let : Name.t -> term -> term -> term -> term
@@ -197,7 +198,7 @@ val gref : Names.GlobRef.t Conversion.t
197198
val inductive : inductive Conversion.t
198199
val constructor : constructor Conversion.t
199200
val constant : global_constant Conversion.t
200-
val sort : Sorts.t Conversion.t
201+
val sort : (Sorts.t,'a coq_context,constraints) ContextualConversion.t
201202
val global_constant_of_globref : Names.GlobRef.t -> global_constant
202203
val abbreviation : Globnames.abbreviation Conversion.t
203204
val implicit_kind : Glob_term.binding_kind Conversion.t

0 commit comments

Comments
 (0)