Skip to content

Commit 33dfcef

Browse files
committed
HB.tag
1 parent e11c79b commit 33dfcef

File tree

7 files changed

+140
-21
lines changed

7 files changed

+140
-21
lines changed

HB/common/database.elpi

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -352,11 +352,14 @@ structure-nparams Structure NParams :-
352352
class-def (class Class Structure _),
353353
factory-nparams Class NParams.
354354

355+
pred factory?-split i:term, o:factoryname, o:list term, o:term, o:list term.
356+
factory?-split (app[global GR|Args]) F [global GR|Params] T Rest :-
357+
factory-alias->gref GR F, factory-nparams F NP, !,
358+
std.split-at NP Args Params [T|Rest].
359+
355360
pred factory? i:term, o:w-args factoryname.
356361
factory? S (triple F Params T) :-
357-
not (var S), !,
358-
safe-dest-app S (global GR) Args, factory-alias->gref GR F, factory-nparams F NP, !,
359-
std.split-at NP Args Params [T|_].
362+
factory?-split S F [_|Params] T _.
360363

361364
% [find-max-classes Mixins Classes] states that Classes is a list of classes
362365
% which contain all the mixins in Mixins.
@@ -376,3 +379,8 @@ find-max-classes [M|Mixins] [C|Classes] :-
376379
].
377380
find-max-classes [M|_] _ :- coq.error "HB: cannot find a class containing mixin" M.
378381

382+
pred is-structure-op-w-wrapper i:term, o:int, o:classname.
383+
is-structure-op-w-wrapper (global (const C)) N Class :- exported-op M _ C, wrapper-mixin _ (const C) _, factory-nparams M N, mixin-first-class M Class.
384+
is-structure-op-w-wrapper (app[global (const C)|_]) N Class :- exported-op M _ C, wrapper-mixin _ (const C) _, factory-nparams M N, mixin-first-class M Class.
385+
is-structure-op-w-wrapper (global GR) N Class :- tag GR Class N, wrapper-mixin _ GR _.
386+
is-structure-op-w-wrapper (app[global GR|_]) N Class :- tag GR Class N, wrapper-mixin _ GR _.

HB/common/utils.elpi

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -371,13 +371,19 @@ re-enable-id-phant T T1 :-
371371

372372
pred failsafe-structure-inference i:term, o:term.
373373
failsafe-structure-inference T T1 :-
374-
(pi OP Args Args1 M Class NP S\
375-
copy (app [global (const OP)|Args]) (app [global (const OP)| Args1]) :-
376-
exported-op M _ OP, mixin-first-class M Class, factory-nparams Class NP,
377-
std.nth NP Args S,
378-
var S,
374+
(pi T T2 F_Params F_Params1 Args Args1 Subject Subject1 NP ArgsOp ArgsOp1 OP S\
375+
copy T T2 :-
376+
factory?-split T _ F_Params Subject Args,
377+
std.map F_Params copy F_Params1,
378+
std.map Args copy Args1,
379+
is-structure-op-w-wrapper Subject NP Class,
380+
coq.safe-dest-app Subject OP ArgsOp,
381+
std.nth NP ArgsOp S,
382+
(var S ; name S),
379383
!,
380-
eta-structure-record NP Class Args Args1) =>
384+
eta-structure-record NP Class ArgsOp ArgsOp1,
385+
coq.mk-app OP ArgsOp1 Subject1,
386+
coq.mk-app (app F_Params1) [Subject1|Args1] T2) =>
381387
copy T T1.
382388

383389
pred eta-structure-record i:int, i:classname, i:list term, o:list term.

HB/instance.elpi

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ declare-const Name BodySkel TyWPSkel CSL :- std.do! [
8888
% derived instance %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8989
(private.declare-regular-inst TheType ML TheMixins TyWP SectionName CSL)
9090
% regular instance %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
91-
(if (get-option "wrapper" ff ; not(private.is-structure-op-w-wrapper TheType))
91+
(if (get-option "wrapper" ff ; not(is-structure-op-w-wrapper TheType _ _))
9292
% regular subject %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9393
(private.declare-regular-inst TheType ML TheMixins TyWP SectionName CSL)
9494
% wrapper %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -400,10 +400,6 @@ declare-wrapper-inst TheType ML TheMixins TyWP SectionName CSL :- std.do![
400400
private.declare-structure-instance-from-mixins TheNewType WML TheWrappedMixins CSL,
401401
].
402402

403-
pred is-structure-op-w-wrapper i:term.
404-
is-structure-op-w-wrapper (global (const C)) :- exported-op _ _ C, wrapper-mixin _ (const C) _.
405-
is-structure-op-w-wrapper (app[global (const C)|_]) :- exported-op _ _ C, wrapper-mixin _ (const C) _.
406-
407403
pred derive-wrapper-instances i:term, i:mixinname, o:term, o:constant.
408404
derive-wrapper-instances Instance WrapperMixin WrapperSubject C :- std.do! [
409405

HB/structure.elpi

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ declare Module BSkel Sort :- std.do! [
1212
failsafe-structure-inference BSkelNoId BSkelNoIdX,
1313
std.assert-ok! (coq.elaborate-skeleton BSkelNoIdX _ BNoId) "illtyped structure definition",
1414
re-enable-id-phant BNoId B,
15-
1615
private.sigT->list-w-params B GRFSwP_or_ThingtoBeWrapped ClosureCheck,
1716

1817
% do some work to go back to factories on a single subject
@@ -217,7 +216,6 @@ clean-op-ty [exported-op _ Po C|Ops] S T1 T2 :-
217216
gref-deps (const Po) MLwP,
218217
w-params.nparams MLwP NParams,
219218
std.length {list-w-params_list MLwP} NMixins,
220-
221219
(pi L L1 L2 Params Rest PoArgs\
222220
copy (app [global (const Po)| L]) (app [global (const C) | L2]) :-
223221
std.split-at NParams L Params [_|Rest],
@@ -658,19 +656,25 @@ if-coverage-not-good-error.one _ _. % new class is the first covering M
658656
% hom belongs to Quiver, hence hom_isMon takes a "T of Quiver T"
659657

660658
% checks if the term is forall A B C, Factory ... (Op A B C) ...
661-
pred factory-on-some-structure-op? i:term, i:list term, o:gref, o:constant.
659+
pred factory-on-some-structure-op? i:term, i:list term, o:gref, o:gref.
662660
factory-on-some-structure-op? (prod N Ty Bo) VS F OP :-
663661
@pi-decl N Ty x\
664662
factory-on-some-structure-op? (Bo x) [x|VS] F OP.
665-
factory-on-some-structure-op? T VS F OP :-
663+
factory-on-some-structure-op? T VS F (const OP) :-
666664
factory? T (triple F _ Subject),
667665
coq.safe-dest-app Subject (global (const OP)) Args,
668666
exported-op _ _ OP,
669667
std.appendR _ {std.rev VS} Args.
668+
factory-on-some-structure-op? T VS F GR :- std.do! [
669+
factory? T (triple F _ Subject),
670+
coq.safe-dest-app Subject (global GR) Args,
671+
tag GR _ _,
672+
std.appendR _ {std.rev VS} Args,
673+
].
670674

671675
kind factory-on-subject type.
672676
type factory-on-the-type w-args factoryname -> factory-on-subject.
673-
type factory-on-structure-op term -> factoryname -> constant -> factory-on-subject.
677+
type factory-on-structure-op term -> factoryname -> gref -> factory-on-subject.
674678

675679
pred product->triples i:term, i:term, o:list factory-on-subject, o:bool.
676680
product->triples {{ lib:hb.prod lp:A lp:B }} T L ClosureCheck :- !,
@@ -708,7 +712,7 @@ lift-to-the-subject.aux [] _ [].
708712
lift-to-the-subject.aux [factory-on-the-type F|Rest] T [F|Rest1] :-
709713
lift-to-the-subject.aux Rest T Rest1.
710714
lift-to-the-subject.aux [factory-on-structure-op Expr F OP|Rest] T [WF|Rest1] :-
711-
wrapper-mixin Wrapper (const OP) F, !,
715+
wrapper-mixin Wrapper OP F, !,
712716
factory-nparams Wrapper NParams,
713717
coq.mk-app {coq.env.global Wrapper} {std.append {coq.mk-n-holes NParams} [T]} W,
714718
factory? W WF,

_CoqProject.test-suite

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ examples/Coq2020_material/CoqWS_abstract.v
5252
examples/Coq2020_material/CoqWS_expansion/withHB.v
5353
examples/Coq2020_material/CoqWS_expansion/withoutHB.v
5454

55-
examples/cat/cat.v
5655
tests/enriched_cat_case6.v
5756

5857
tests/type_of_exported_ops.v
@@ -84,6 +83,7 @@ tests/fun_instance.v
8483
tests/issue284.v
8584
tests/issue287.v
8685
tests/monoid_enriched_cat.v
86+
tests/tag_wrap.v
8787

8888
-R tests HB.tests
8989
-R examples HB.examples

structures.v

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,11 @@ pred mixin-mem i:term, o:gref.
167167
% wrapper-mixin (indt "hom_isMon") (const "hom") (indt "isMon").
168168
pred wrapper-mixin o:mixinname, o:gref, o:mixinname.
169169

170+
% designated identity function for wrapping (sometimes you don't have a
171+
% structure op for it).
172+
% [tag GR Class NParams]
173+
pred tag o:gref, o:classname, o:int.
174+
170175
%%%%%% Memory of exported mixins (HB.structure) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
171176
% Operations (named mixin fields) need to be exported exactly once,
172177
% but the same mixin can be used in many structure, hence this memory
@@ -1002,6 +1007,68 @@ check-or-not Skel :-
10021007
Elpi Typecheck.
10031008
Elpi Export HB.check.
10041009

1010+
(* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% *)
1011+
(* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% *)
1012+
(* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% *)
1013+
1014+
(** [HB.tag] declares a tag for mixin subjects
1015+
1016+
[[
1017+
HB.tag Definition N Params x := x
1018+
]]
1019+
1020+
*)
1021+
1022+
#[arguments(raw)] Elpi Command HB.tag.
1023+
Elpi Accumulate Db hb.db.
1024+
Elpi Accumulate File "HB/common/stdpp.elpi".
1025+
Elpi Accumulate File "HB/common/database.elpi".
1026+
#[skip="8.1[56].*"] Elpi Accumulate File "HB/common/compat_acc_clauses_all.elpi".
1027+
#[only="8.1[56].*"] Elpi Accumulate File "HB/common/compat_acc_clauses_816.elpi".
1028+
Elpi Accumulate File "HB/common/utils.elpi".
1029+
Elpi Accumulate File "HB/common/log.elpi".
1030+
Elpi Accumulate File "HB/common/synthesis.elpi".
1031+
Elpi Accumulate File "HB/context.elpi".
1032+
Elpi Accumulate File "HB/instance.elpi".
1033+
Elpi Accumulate lp:{{
1034+
1035+
main [const-decl Name (some BodySkel) AritySkel] :- !, std.do! [
1036+
std.assert-ok! (coq.elaborate-arity-skeleton AritySkel _ Arity) "HB: type illtyped",
1037+
coq.arity->nparams Arity N,
1038+
coq.arity->term Arity Ty,
1039+
std.assert-ok! (coq.elaborate-skeleton BodySkel Ty Body) "HB: body illtyped",
1040+
with-attributes (with-logging (std.do! [
1041+
log.coq.env.add-const-noimplicits Name Body Ty @transparent! C,
1042+
coq.arity->implicits Arity CImpls,
1043+
if (coq.any-implicit? CImpls)
1044+
(@global! => coq.arguments.set-implicit (const C) [CImpls])
1045+
true,
1046+
])),
1047+
M is N - 1,
1048+
class-of-nth-arg M Ty Class,
1049+
acc-clause current (tag (const C) Class M),
1050+
].
1051+
main [str G, str"|", int M] :- !,
1052+
coq.locate G GR,
1053+
coq.env.typeof GR Ty,
1054+
class-of-nth-arg M Ty Class,
1055+
acc-clause current (tag GR Class M).
1056+
1057+
main _ :- coq.error "Usage: HB.tag Definition <Name> := <Builder> T ...\nUsage: HB.tag <gref> | <nparams>".
1058+
1059+
pred class-of-nth-arg i:int, i:term, o:classname.
1060+
class-of-nth-arg 0 (prod _ (global S) _\_) Class :- class-def (class Class S _).
1061+
class-of-nth-arg 0 (prod _ (app [global S|_]) _\_) Class :- class-def (class Class S _).
1062+
class-of-nth-arg N (prod Name Ty Bo) Class :- N > 0, !, M is N - 1,
1063+
@pi-decl Name Ty x\ class-of-nth-arg M (Bo x) Class.
1064+
class-of-nth-arg 0 T _ :- !,
1065+
coq.error "HB: the last parameter of a tag must be of a structure type:" {coq.term->string T}.
1066+
class-of-nth-arg _ T _ :- !,
1067+
coq.error "HB: not enough argsuments:" {coq.term->string T}.
1068+
1069+
}}.
1070+
Elpi Typecheck.
1071+
Elpi Export HB.tag.
10051072

10061073
(* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% *)
10071074
(* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% *)

tests/tag_wrap.v

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
From HB Require Import structures.
2+
3+
HB.mixin Record isSomething T := { clearly : True }.
4+
HB.structure Definition Something := { T of isSomething T }.
5+
6+
HB.mixin Record isTerminal (T : Type) := { p : True }.
7+
8+
HB.tag Definition this_one (T : Something.type) : Type := T.
9+
10+
#[wrapper]
11+
HB.mixin Record this_one_isTerminal T of Something T := {
12+
private : isTerminal (this_one T)
13+
}.
14+
15+
HB.tag Definition this_other_one (T : Something.type) : Type := T.
16+
17+
#[wrapper]
18+
HB.mixin Record this_other_one_isTerminal T of Something T := {
19+
private : isTerminal (this_other_one T)
20+
}.
21+
(* This is a bug, maybe even in master. If I declare an instance on a mixin
22+
which leads to no new structure instance, then the mixin is not use later
23+
on *)
24+
HB.structure Definition magic1 := { T of
25+
isSomething T &
26+
isTerminal (this_one T)
27+
}.
28+
29+
HB.structure Definition magic := { T of
30+
isSomething T &
31+
isTerminal (this_one T) &
32+
isTerminal (this_other_one T)
33+
}.
34+
35+
HB.instance Definition _ : isSomething nat := isSomething.Build nat I.
36+
HB.instance Definition _ : isTerminal (this_one nat) := isTerminal.Build nat I.
37+
HB.instance Definition _ : isTerminal (this_other_one nat) := isTerminal.Build nat I.
38+
Check nat : magic.type.

0 commit comments

Comments
 (0)