Skip to content

Commit a5d5a91

Browse files
LuciegaresecranceMERCECohenCyril
committed
Add coq.univ.alg-super, @keep-alg-univs!
This is LPCIC#585 rebased on master. Co-Authored-By: Enrico Tassi <[email protected]> Co-Authored-By: Enzo Crance <[email protected]> Co-Authored-By: Cyril Cohen <[email protected]>
1 parent a0fad1e commit a5d5a91

File tree

9 files changed

+167
-55
lines changed

9 files changed

+167
-55
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: 74 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ type options = {
364364
keepunivs : bool option;
365365
redflags : RedFlags.reds option;
366366
no_tc: bool option;
367+
algunivs : bool option;
367368
}
368369
let default_options () = {
369370
hoas_holes = Some Verbatim;
@@ -382,14 +383,15 @@ let default_options () = {
382383
keepunivs = None;
383384
redflags = None;
384385
no_tc = None;
386+
algunivs = None;
385387
}
386388
let make_options ~hoas_holes ~local ~warn ~depr ~primitive ~failsafe ~ppwidth
387389
~pp ~pplevel ~using ~inline ~uinstance ~universe_decl ~reversible ~keepunivs
388-
~redflags ~no_tc =
390+
~redflags ~no_tc ~algunivs =
389391
let user_warns = Some UserWarn.{ depr; warn } in
390392
{ hoas_holes; local; user_warns; primitive; failsafe; ppwidth; pp;
391393
pplevel; using; inline; uinstance; universe_decl; reversible; keepunivs;
392-
redflags; no_tc; }
394+
redflags; no_tc; algunivs; }
393395
let make_warn = UserWarn.make_warn
394396

395397
type 'a coq_context = {
@@ -422,6 +424,59 @@ let pr_coq_ctx { env; db2name; db2rel } sigma =
422424
v 0 (Printer.pr_rel_context_of env sigma) ++ cut ()
423425
)
424426

427+
let propc = E.Constants.declare_global_symbol "prop"
428+
let spropc = E.Constants.declare_global_symbol "sprop"
429+
let typc = E.Constants.declare_global_symbol "typ"
430+
431+
432+
let sort : (Sorts.t, _ coq_context, API.Data.constraints) API.ContextualConversion.t =
433+
let open API.ContextualConversion in
434+
{
435+
ty = API.Conversion.TyName "sort";
436+
pp_doc = (fun fmt () ->
437+
Format.fprintf fmt "%% Sorts (kinds of types)\n";
438+
Format.fprintf fmt "kind sort type.\n";
439+
Format.fprintf fmt "type prop sort. %% impredicative sort of propositions\n";
440+
Format.fprintf fmt "type sprop sort. %% impredicative sort of propositions with definitional proof irrelevance\n";
441+
Format.fprintf fmt "type typ univ -> sort. %% predicative sort of data (carries a universe level)\n";
442+
);
443+
pp = (fun fmt -> function
444+
| Sorts.Type _ -> Format.fprintf fmt "Type"
445+
| Sorts.Set -> Format.fprintf fmt "Set"
446+
| Sorts.Prop -> Format.fprintf fmt "Prop"
447+
| Sorts.SProp -> Format.fprintf fmt "SProp"
448+
| Sorts.QSort _ -> Format.fprintf fmt "QSort");
449+
embed = (fun ~depth { options } _ state s ->
450+
match s with
451+
| Sorts.Prop -> state, E.mkConst propc, []
452+
| Sorts.SProp -> state, E.mkConst spropc, []
453+
| Sorts.Set ->
454+
let state, u, gls = univ.embed ~depth state Univ.Universe.type0 in
455+
state, E.mkApp typc u [], gls
456+
| Sorts.Type u ->
457+
let state, u, gls = univ.embed ~depth state u in
458+
state, E.mkApp typc u [], gls
459+
| Sorts.QSort _ -> nYI "sort polymorphism");
460+
readback = (fun ~depth { options } _ state t ->
461+
match E.look ~depth t with
462+
| E.Const c when c == propc -> state, Sorts.prop, []
463+
| E.Const c when c == spropc -> state, Sorts.sprop, []
464+
| E.App(c,u,[]) when c == typc ->
465+
let state, u, gls = univ.readback ~depth state u in
466+
state, Sorts.sort_of_univ u ,gls
467+
| E.UnifVar(k,_) -> begin
468+
let m = S.get um state in
469+
try
470+
let u = UM.host k m in
471+
state, Sorts.sort_of_univ u, []
472+
with Not_found ->
473+
let state, (_,u) = new_univ_level_variable state in
474+
let state = S.update um state (UM.add k u) in
475+
state, Sorts.sort_of_univ u, []
476+
end
477+
| _ -> raise API.Conversion.(TypeErr(TyName"sort",depth,t)));
478+
}
479+
425480
let in_coq_fresh ~id_only =
426481
let mk_fresh dbl =
427482
Id.of_string_soft
@@ -1074,14 +1129,18 @@ let in_elpi_flex_sort t = E.mkApp sortc (E.mkApp typc t []) []
10741129
let in_elpiast_flex_sort ~loc t =
10751130
A.mkAppGlobal ~loc sortc (A.mkAppGlobal ~loc typc t []) []
10761131

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) }
1132+
let sort = { sort with API.ContextualConversion.embed = (fun ~depth ctx csts state s ->
1133+
let state, s =
1134+
if ctx.options.algunivs = None || ctx.options.algunivs = Some false then
1135+
purge_algebraic_univs_sort state (EConstr.ESorts.make s)
1136+
else
1137+
state, s in
1138+
sort.API.ContextualConversion.embed ~depth ctx csts state s) }
10801139

1081-
let in_elpi_sort ~depth state s =
1082-
let state, s, gl = sort.API.Conversion.embed ~depth state s in
1140+
let in_elpi_sort ~depth ctx csts state s =
1141+
let state, s, gl = sort.API.ContextualConversion.embed ~depth ctx csts state s in
10831142
assert(gl=[]);
1084-
state, E.mkApp sortc s []
1143+
state, E.mkApp sortc s [], gl
10851144

10861145
let in_elpiast_sort ~loc state s =
10871146
A.mkAppGlobal ~loc sortc (ast_sort ~loc s) []
@@ -1301,10 +1360,10 @@ let get_options ~depth hyps state =
13011360
let no_tc = get_bool_option "coq:no_tc" in
13021361
let keepunivs = get_bool_option "coq:keepunivs" in
13031362
let redflags = get_redflags_option () in
1363+
let algunivs = get_bool_option "coq:keepalgunivs" in
13041364
make_options ~hoas_holes ~local ~warn ~depr ~primitive ~failsafe ~ppwidth
13051365
~pp ~pplevel ~using ~inline ~uinstance ~universe_decl ~reversible ~keepunivs
1306-
~redflags ~no_tc
1307-
1366+
~redflags ~no_tc ~algunivs
13081367
let mk_coq_context ~options state =
13091368
let env = get_global_env state in
13101369
let section = section_ids env in
@@ -1452,7 +1511,10 @@ let rec constr2lp coq_ctx ~calldepth ~depth state t =
14521511
let args = CList.firstn argno args in
14531512
let state, args = CList.fold_left_map (aux ~depth env) state args in
14541513
state, E.mkUnifVar elpi_uvk ~args:(List.rev args) state
1455-
| C.Sort s -> in_elpi_sort ~depth state (EC.ESorts.kind sigma s)
1514+
| C.Sort s ->
1515+
let state, s, gl = in_elpi_sort ~depth coq_ctx API.RawData.no_constraints state (EC.ESorts.kind sigma s) in
1516+
gls := gl @ !gls;
1517+
state, s
14561518
| C.Cast (t,_,ty0) ->
14571519
let state, t = aux ~depth env state t in
14581520
let state, ty = aux ~depth env state ty0 in
@@ -1962,7 +2024,7 @@ and lp2constr ~calldepth syntactic_constraints coq_ctx ~depth state ?(on_ty=fals
19622024
debug Pp.(fun () -> str"lp2term@" ++ int depth ++ str":" ++ str(pp2string (P.term depth) t));
19632025
match E.look ~depth t with
19642026
| E.App(s,p,[]) when sortc == s ->
1965-
let state, u, gsl = sort.API.Conversion.readback ~depth state p in
2027+
let state, u, gsl = sort.API.ContextualConversion.readback ~depth coq_ctx syntactic_constraints state p in
19662028
state, EC.mkSort (EC.ESorts.make u), gsl
19672029
(* constants *)
19682030
| 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)