Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@
- derive: support for `is_true` in `param1_trivial` (based on pre-existing
special support for `is_eq` and `is_bool`)

### API
- New `coq.univ.alg-super` that relates a univ `U` to its algebraic successor
`V`, that is `U+1` and not any `V` s.t. `U < V`

### HOAS
- New `@keep-alg-univs!` option for all APIs taking terms. By default algebraic
universes are replaced by named universes. See the `coq.univ.alg-super` API.

# [2.5.0] 18/2/2025

Requires Elpi 2.0.7 and Coq 8.20 or Rocq 9.0.
Expand Down
9 changes: 7 additions & 2 deletions builtin-doc/coq-builtin.elpi
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,8 @@ typeabbrev opaque? bool. macro @opaque! :- tt. macro @transparent! :- ff.

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

macro @keep-alg-univs! :- get-option "coq:keepalgunivs" tt.

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
Expand Down Expand Up @@ -978,8 +980,7 @@ kind univ type.
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)
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.
Expand All @@ -1000,6 +1001,10 @@ external pred coq.univ.print .
% [coq.univ.new U] A fresh universe.
external pred coq.univ.new o:univ.

% [coq.univ.alg-super U V] relates a univ U to its algebraic successor V,
% that is U+1 and not any V s.t. U < V
external pred coq.univ.alg-super i:univ, o:univ.

% [coq.univ Name U] Finds a named unvierse. Can fail.
external pred coq.univ o:id, o:univ.

Expand Down
2 changes: 2 additions & 0 deletions elpi/coq-HOAS.elpi
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,8 @@ typeabbrev opaque? bool. macro @opaque! :- tt. macro @transparent! :- ff.

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

macro @keep-alg-univs! :- get-option "coq:keepalgunivs" tt.

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
Expand Down
142 changes: 82 additions & 60 deletions src/rocq_elpi_HOAS.ml
Original file line number Diff line number Diff line change
Expand Up @@ -174,53 +174,6 @@ let isuniv, univout, univino, (univ : Univ.Universe.t API.Conversion.t) =
end
}

let propc = E.Constants.declare_global_symbol "prop"
let spropc = E.Constants.declare_global_symbol "sprop"
let typc = E.Constants.declare_global_symbol "typ"

let sort =
let open API.AlgebraicData in declare {
ty = API.Conversion.TyName "sort";
doc = "Sorts (kinds of types)";
pp = (fun fmt -> function
| Sorts.Type _ -> Format.fprintf fmt "Type"
| Sorts.Set -> Format.fprintf fmt "Set"
| Sorts.Prop -> Format.fprintf fmt "Prop"
| Sorts.SProp -> Format.fprintf fmt "SProp"
| Sorts.QSort _ -> Format.fprintf fmt "Type");
constructors = [
K("prop","impredicative sort of propositions",N,
B Sorts.prop,
M (fun ~ok ~ko -> function Sorts.Prop -> ok | _ -> ko ()));
K("sprop","impredicative sort of propositions with definitional proof irrelevance",N,
B Sorts.sprop,
M (fun ~ok ~ko -> function Sorts.SProp -> ok | _ -> ko ()));
K("typ","predicative sort of data (carries a universe level)",A(univ,N),
B (fun x -> Sorts.sort_of_univ x),
M (fun ~ok ~ko -> function
| Sorts.Type x -> ok x
| Sorts.Set -> ok Univ.Universe.type0
| _ -> ko ()));
K("uvar","",A(F.uvar,N),
BS (fun (k,_) state ->
let m = S.get um state in
try
let u = UM.host k m in
state, Sorts.sort_of_univ u
with Not_found ->
let state, (_,u) = new_univ_level_variable state in
let state = S.update um state (UM.add k u) in
state, Sorts.sort_of_univ u),
M (fun ~ok ~ko _ -> ko ()));
]
} |> API.ContextualConversion.(!<)

let ast_sort ~loc = function
| Sorts.Prop -> A.mkGlobal ~loc propc
| Sorts.SProp -> A.mkGlobal ~loc spropc
| Sorts.Set -> A.mkAppGlobal ~loc typc (A.mkOpaque ~loc @@ univino Univ.Universe.type0) []
| Sorts.Type u -> A.mkAppGlobal ~loc typc (A.mkOpaque ~loc @@ univino u) []
| _ -> assert false

let universe_level_variable =
let { CD.cin = levelin }, universe_level_variable_to_patch = CD.declare {
Expand Down Expand Up @@ -364,6 +317,7 @@ type options = {
keepunivs : bool option;
redflags : RedFlags.reds option;
no_tc: bool option;
algunivs : bool option;
}
let default_options () = {
hoas_holes = Some Verbatim;
Expand All @@ -382,14 +336,15 @@ let default_options () = {
keepunivs = None;
redflags = None;
no_tc = None;
algunivs = None;
}
let make_options ~hoas_holes ~local ~warn ~depr ~primitive ~failsafe ~ppwidth
~pp ~pplevel ~using ~inline ~uinstance ~universe_decl ~reversible ~keepunivs
~redflags ~no_tc =
~redflags ~no_tc ~algunivs =
let user_warns = Some UserWarn.{ depr; warn } in
{ hoas_holes; local; user_warns; primitive; failsafe; ppwidth; pp;
pplevel; using; inline; uinstance; universe_decl; reversible; keepunivs;
redflags; no_tc; }
redflags; no_tc; algunivs; }
let make_warn = UserWarn.make_warn

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

let propc = E.Constants.declare_global_symbol "prop"
let spropc = E.Constants.declare_global_symbol "sprop"
let typc = E.Constants.declare_global_symbol "typ"


let sort : (Sorts.t, _ coq_context, API.Data.constraints) API.ContextualConversion.t =
let open API.ContextualConversion in
{
ty = API.Conversion.TyName "sort";
pp_doc = (fun fmt () ->
Format.fprintf fmt "%% Sorts (kinds of types)\n";
Format.fprintf fmt "kind sort type.\n";
Format.fprintf fmt "type prop sort. %% impredicative sort of propositions\n";
Format.fprintf fmt "type sprop sort. %% impredicative sort of propositions with definitional proof irrelevance\n";
Format.fprintf fmt "type typ univ -> sort. %% predicative sort of data (carries a universe level)\n";
);
pp = (fun fmt -> function
| Sorts.Type _ -> Format.fprintf fmt "Type"
| Sorts.Set -> Format.fprintf fmt "Set"
| Sorts.Prop -> Format.fprintf fmt "Prop"
| Sorts.SProp -> Format.fprintf fmt "SProp"
| Sorts.QSort _ -> Format.fprintf fmt "QSort");
embed = (fun ~depth { options } _ state s ->
match s with
| Sorts.Prop -> state, E.mkConst propc, []
| Sorts.SProp -> state, E.mkConst spropc, []
| Sorts.Set ->
let state, u, gls = univ.embed ~depth state Univ.Universe.type0 in
state, E.mkApp typc u [], gls
| Sorts.Type u ->
let state, u, gls = univ.embed ~depth state u in
state, E.mkApp typc u [], gls
| Sorts.QSort _ -> nYI "sort polymorphism");
readback = (fun ~depth { options } _ state t ->
match E.look ~depth t with
| E.Const c when c == propc -> state, Sorts.prop, []
| E.Const c when c == spropc -> state, Sorts.sprop, []
| E.App(c,u,[]) when c == typc ->
let state, u, gls = univ.readback ~depth state u in
state, Sorts.sort_of_univ u ,gls
| E.UnifVar(k,_) -> begin
let m = S.get um state in
try
let u = UM.host k m in
state, Sorts.sort_of_univ u, []
with Not_found ->
let state, (_,u) = new_univ_level_variable state in
let state = S.update um state (UM.add k u) in
state, Sorts.sort_of_univ u, []
end
| _ -> raise API.Conversion.(TypeErr(TyName"sort",depth,t)));
}

let ast_sort ~loc = function
| Sorts.Prop -> A.mkGlobal ~loc propc
| Sorts.SProp -> A.mkGlobal ~loc spropc
| Sorts.Set -> A.mkAppGlobal ~loc typc (A.mkOpaque ~loc @@ univino Univ.Universe.type0) []
| Sorts.Type u -> A.mkAppGlobal ~loc typc (A.mkOpaque ~loc @@ univino u) []
| _ -> assert false


let in_coq_fresh ~id_only =
let mk_fresh dbl =
Id.of_string_soft
Expand Down Expand Up @@ -1052,7 +1068,6 @@ let section_ids env =
~init:[] named_ctx

let sortc = E.Constants.declare_global_symbol "sort"
let typc = E.Constants.declare_global_symbol "typ"

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

let sort = { sort with API.Conversion.embed = (fun ~depth state s ->
let state, s = purge_algebraic_univs_sort state (EConstr.ESorts.make s) in
sort.API.Conversion.embed ~depth state s) }
let sort = { sort with API.ContextualConversion.embed = (fun ~depth ctx csts state s ->
let state, s =
if ctx.options.algunivs = None || ctx.options.algunivs = Some false then
purge_algebraic_univs_sort state (EConstr.ESorts.make s)
else
state, s in
sort.API.ContextualConversion.embed ~depth ctx csts state s) }

let in_elpi_sort ~depth state s =
let state, s, gl = sort.API.Conversion.embed ~depth state s in
let in_elpi_sort ~depth ctx csts state s =
let state, s, gl = sort.API.ContextualConversion.embed ~depth ctx csts state s in
assert(gl=[]);
state, E.mkApp sortc s []
state, E.mkApp sortc s [], gl

let in_elpiast_sort ~loc state s =
A.mkAppGlobal ~loc sortc (ast_sort ~loc s) []
Expand Down Expand Up @@ -1301,10 +1320,10 @@ let get_options ~depth hyps state =
let no_tc = get_bool_option "coq:no_tc" in
let keepunivs = get_bool_option "coq:keepunivs" in
let redflags = get_redflags_option () in
let algunivs = get_bool_option "coq:keepalgunivs" in
make_options ~hoas_holes ~local ~warn ~depr ~primitive ~failsafe ~ppwidth
~pp ~pplevel ~using ~inline ~uinstance ~universe_decl ~reversible ~keepunivs
~redflags ~no_tc

~redflags ~no_tc ~algunivs
let mk_coq_context ~options state =
let env = get_global_env state in
let section = section_ids env in
Expand Down Expand Up @@ -1452,7 +1471,10 @@ let rec constr2lp coq_ctx ~calldepth ~depth state t =
let args = CList.firstn argno args in
let state, args = CList.fold_left_map (aux ~depth env) state args in
state, E.mkUnifVar elpi_uvk ~args:(List.rev args) state
| C.Sort s -> in_elpi_sort ~depth state (EC.ESorts.kind sigma s)
| C.Sort s ->
let state, s, gl = in_elpi_sort ~depth coq_ctx API.RawData.no_constraints state (EC.ESorts.kind sigma s) in
gls := gl @ !gls;
state, s
| C.Cast (t,_,ty0) ->
let state, t = aux ~depth env state t in
let state, ty = aux ~depth env state ty0 in
Expand Down Expand Up @@ -1962,7 +1984,7 @@ and lp2constr ~calldepth syntactic_constraints coq_ctx ~depth state ?(on_ty=fals
debug Pp.(fun () -> str"lp2term@" ++ int depth ++ str":" ++ str(pp2string (P.term depth) t));
match E.look ~depth t with
| E.App(s,p,[]) when sortc == s ->
let state, u, gsl = sort.API.Conversion.readback ~depth state p in
let state, u, gsl = sort.API.ContextualConversion.readback ~depth coq_ctx syntactic_constraints state p in
state, EC.mkSort (EC.ESorts.make u), gsl
(* constants *)
| E.App(c,d,[]) when globalc == c ->
Expand Down
5 changes: 3 additions & 2 deletions src/rocq_elpi_HOAS.mli
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ type options = {
keepunivs : bool option;
redflags : RedFlags.reds option;
no_tc: bool option;
algunivs : bool option;
}

type 'a coq_context = {
Expand Down Expand Up @@ -154,7 +155,7 @@ val in_elpi_gr : depth:int -> State.t -> Names.GlobRef.t -> term
val in_elpi_poly_gr : depth:int -> State.t -> Names.GlobRef.t -> term -> term
val in_elpi_poly_gr_instance : depth:int -> State.t -> Names.GlobRef.t -> UVars.Instance.t -> term
val in_elpi_flex_sort : term -> term
val in_elpi_sort : depth:int -> state -> Sorts.t -> state * term
val in_elpi_sort : depth:int -> 'a coq_context -> constraints -> state -> Sorts.t -> state * term * Conversion.extra_goals
val in_elpi_prod : Name.t -> term -> term -> term
val in_elpi_lam : Name.t -> term -> term -> term
val in_elpi_let : Name.t -> term -> term -> term -> term
Expand Down Expand Up @@ -197,7 +198,7 @@ val gref : Names.GlobRef.t Conversion.t
val inductive : inductive Conversion.t
val constructor : constructor Conversion.t
val constant : global_constant Conversion.t
val sort : Sorts.t Conversion.t
val sort : (Sorts.t,'a coq_context,constraints) ContextualConversion.t
val global_constant_of_globref : Names.GlobRef.t -> global_constant
val abbreviation : Globnames.abbreviation Conversion.t
val implicit_kind : Glob_term.binding_kind Conversion.t
Expand Down
Loading
Loading