Skip to content
Open
Show file tree
Hide file tree
Changes from 12 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
1 change: 1 addition & 0 deletions HB/common/utils-synterp.elpi
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ with-attributes P :-
att "primitive" bool,
att "non_forgetful_inheritance" bool,
att "hnf" bool,
att "interactive" bool,
] Opts, !,
Opts => (save-docstring, P).

Expand Down
3 changes: 3 additions & 0 deletions HB/common/utils.elpi
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ gref->modname_short GR Sep IDS :-

func avoid-name-collision string -> string.
avoid-name-collision S S1 :-
if (var S)
(S = "unnamed")
(true),
coq.locate-all S L,
if (std.mem L (loc-gref GR), coq.gref->path GR P, coq.env.current-path P)
(S1 is S ^ "__" ^ {std.any->string {new_int}})
Expand Down
21 changes: 16 additions & 5 deletions HB/instance.elpi
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ declare-const Name BodySkel TyWPSkel CFL CSL :- std.do! [
% A side effect of opening a section is loosing meta data associated
% with instances, in particular builder tags are lost
if-verbose (coq.say "HB: skipping section opening"),
SectionBody = Body
SectionBody = Body,
%FIXME : introduce a bug
%TODO re-allow local instances (test file local_instance.v)
std.assert! (coq.next-synterp-action (begin-section SectionName)) "synterp code did not open section",
log.coq.env.begin-section SectionName
) (
std.assert! (coq.next-synterp-action (begin-section SectionName)) "synterp code did not open section",
log.coq.env.begin-section SectionName,
Expand Down Expand Up @@ -78,10 +82,11 @@ declare-const Name BodySkel TyWPSkel CFL CSL :- std.do! [
true,

% handle parameters via a section -- end
if (TyWP = arity _) true (
% FIXME
% if (TyWP = arity _) true (
if-verbose (coq.say {header} "closing instance section"),
log.coq.env.end-section-name SectionName
),
log.coq.env.end-section-name SectionName,
% ),

% we accumulate clauses now that the section is over
acc-clauses current Clauses
Expand Down Expand Up @@ -295,10 +300,16 @@ declare-instance Factory T F Clauses CFL CSL :-
!,
declare-canonical-instances-from-factory-and-local-builders Factory
T F TheFactory FGR Clauses CFL CSL.
declare-instance Factory T F Clauses CFL CSL :-
declare-instance Factory T F Clauses CFL CSL :- !,
declare-canonical-instances-from-factory Factory T F Clauses1 CFL CSL,
clauses-for-export {std.append CFL CSL} Clauses2,
std.append Clauses1 Clauses2 Clauses.
% declare-instance Factory T F Clauses CFL CSL :- !,
% if (get-option "program" tt)
% (coq.say "HB: declare-instance: program option detected") true,
% declare-canonical-instances-from-factory Factory T F Clauses1 CFL CSL,
% clauses-for-export {std.append CFL CSL} Clauses2,
% std.append Clauses1 Clauses2 Clauses.

func clauses-for-export list (pair id constant) -> list prop.
clauses-for-export CL ECL :-
Expand Down
89 changes: 82 additions & 7 deletions HB/structures.v
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
Set Warnings "-elpi.flex-clause".

(* Support constants, to be kept in sync with shim/structures.v *)
From Corelib Require Import ssreflect ssrfun.

Expand Down Expand Up @@ -771,6 +773,7 @@ HB.instance Definition N Params := Factory.Build Params T …
- [#[verbose]] for a verbose output.
- [#[hnf] to compute the head normal form of CS instances before declaring
them
- [#[interactive]] to provide part of the instance in tactics mode.
*)

#[arguments(raw)] Elpi Command HB.instance.
Expand All @@ -792,23 +795,95 @@ main [const-decl Name (some BodySkel) TyWPSkel] :- !,
main [T0, F0] :- !,
coq.warning "HB" "HB.deprecated" "The syntax \"HB.instance Key FactoryInstance\" is deprecated, use \"HB.instance Definition\" instead",
with-attributes (with-logging (instance.declare-existing T0 F0)).

main-interp-proof [const-decl Name (some BodySkel) TyWPSkel] _ Body AllGoals (const-decl Name (some Body) TyWP) :-
std.assert-ok! (coq.elaborate-arity-skeleton TyWPSkel _ TyWP) "Definition type illtyped",
coq.arity->term TyWP Ty,
std.assert-ok! (coq.elaborate-skeleton BodySkel Ty Body) "Definition illtyped",
coq.ltac.collect-goals Body Goal Shelved,
std.append Shelved Goal AllGoals.
}}.

#[synterp] Elpi Accumulate lp:{{

shorten coq.env.{ begin-section, end-section }.

main [const-decl _ _ (arity _)] :- !.
main [const-decl _ _ (parameter _ _ _ _)] :- !,
SectionName is "hb_instance_" ^ {std.any->string {new_int} },
begin-section SectionName, end-section.
main [_, _] :- !.
pred interactive-in-attributes i:list attribute.
interactive-in-attributes [attribute "interactive" (leaf-str "") | _].
interactive-in-attributes [_ | Atts] :- interactive-in-attributes Atts.

main _ :- coq.error "Usage: HB.instance Definition <Name> := <Builder> T ...".
main _ :-
attributes A,
if (interactive-in-attributes A)
(true)
(SectionName is "hb_instance_" ^ {std.any->string {new_int} },
begin-section SectionName, end-section).
}}.

Elpi Typecheck.
#[proof(begin_if="interactive")]
Elpi Export HB.instance.



#[arguments(raw)] Elpi Command HB.endinstance.
Elpi Accumulate Db hb.db.
Elpi Accumulate File "HB/common/stdpp.elpi".
Elpi Accumulate File "HB/common/database.elpi".
Elpi Accumulate File "HB/common/compat_acc_clauses_all.elpi".
Elpi Accumulate File "HB/common/compat_add_secvar_all.elpi".
Elpi Accumulate File "HB/common/utils.elpi".
Elpi Accumulate File "HB/common/log.elpi".
Elpi Accumulate File "HB/common/synthesis.elpi".
Elpi Accumulate File "HB/context.elpi".
Elpi Accumulate File "HB/instance.elpi".
Elpi Accumulate lp:{{
func under term, list (pair term term) -> term.
under (fun N Ty F) Acc (fun N Ty F') :-
@pi-decl N Ty x\
under (F x) [(pr x Ty)|Acc] (F' x).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may make sense to have a triple here and also store N, and use that N in abstract in place of `x`

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, done ! the name of the parameter is used in the abstraction

under (app L) Acc (app L') :-
aux Acc L L'.

func aux list (pair term term), list term -> list term.
aux _ [] [].
aux Acc [T|TS] [T|TS'] :-
coq.typecheck T Ty ok,
coq.typecheck Ty TyTy ok,
%coq.typecheck-ty does not make coercions
(not (TyTy = {{Prop}}); T = global _), !,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if T is globla_ we don't really need to typecheck it. You could have a "fast path" for this case.
like a rule axu Acc [global _ as T|....

aux Acc TS TS'.
aux Acc [T|TS] [T'|TS'] :-
std.spy! (abstract Acc T TA),
log.coq.env.add-const _ TA _ @opaque! C,
T' = app [(global (const C))|{std.map Acc fst}],
aux Acc TS TS'.

func abstract list (pair term term), term -> term.
abstract [] T T' :-
copy T T'.
abstract [(pr V Ty) | A] T (fun `x` Ty F) :-
pi w\ (copy V w :- !) => abstract A T (F w).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this code should go to utils, maybe in a namespace abstract-props-as-lemmas.
You can then leave here just the call to abstract-props-as-lemmas.main (now called under).

Related design question for @CohenCyril is how configurable this should be, i.e. instead of using Prop as a marker one may want to flag the fields of mixins/factories as not-data. It may be possible to have a default (Prop) and a field-attribute as https://rocq-prover.org/doc/master/refman/language/extensions/canonical.html#rocq:attr.canonical (in rocq/Elpi) but it may require some little work.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I think it is better if configurable. But reasonable choices are essentially Prop, SProp and hProp. So possibly just registering them (as a open list) and unifying with them is enough.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An issue with moving that code to utils is that it uses "log.coq.env.add-const" which is in log and which in turns uses some code from utils (eg "avoid-name-collision)
I could always create a new file to store these functions...

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignore log, the log module is a relic. I guess the collision avoidance code can go to utils as well.

main-interp-qed _ _ P _GL (const-decl Name (some _Body) TyWP) :-
under P [] P',
with-attributes (with-logging (instance.declare-const Name P' TyWP _ _)).
}}.

#[synterp] Elpi Accumulate lp:{{

shorten coq.env.{ begin-section, end-section }.

main _ :-
SectionName is "hb_instance_" ^ {std.any->string {new_int} },
begin-section SectionName, end-section.
}}.

#[proof="end"]
Elpi Export HB.endinstance.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick HB.end_instance

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done :)





(* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% *)
(* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% *)
(* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% *)
Expand Down
Loading
Loading