Skip to content

Commit 0d04e8f

Browse files
committed
HB.tag
1 parent 79a12f2 commit 0d04e8f

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
@@ -438,11 +438,14 @@ structure-nparams Structure NParams :-
438438
class-def (class Class Structure _),
439439
factory-nparams Class NParams.
440440

441+
pred factory?-split i:term, o:factoryname, o:list term, o:term, o:list term.
442+
factory?-split (app[global GR|Args]) F [global GR|Params] T Rest :-
443+
factory-alias->gref GR F, factory-nparams F NP, !,
444+
std.split-at NP Args Params [T|Rest].
445+
441446
pred factory? i:term, o:w-args factoryname.
442447
factory? S (triple F Params T) :-
443-
not (var S), !,
444-
safe-dest-app S (global GR) Args, factory-alias->gref GR F, factory-nparams F NP, !,
445-
std.split-at NP Args Params [T|_].
448+
factory?-split S F [_|Params] T _.
446449

447450
% [find-max-classes Mixins Classes] states that Classes is a list of classes
448451
% which contain all the mixins in Mixins.
@@ -462,3 +465,8 @@ find-max-classes [M|Mixins] [C|Classes] :-
462465
].
463466
find-max-classes [M|_] _ :- coq.error "HB: cannot find a class containing mixin" M.
464467

468+
pred is-structure-op-w-wrapper i:term, o:int, o:classname.
469+
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.
470+
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.
471+
is-structure-op-w-wrapper (global GR) N Class :- tag GR Class N, wrapper-mixin _ GR _.
472+
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 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -462,10 +462,6 @@ declare-wrapper-inst TheType ML TheMixins TyWP SectionName CSL :- std.do![
462462
private.declare-structure-instance-from-mixins TheNewType WML TheWrappedMixins CSL,
463463
].
464464

465-
pred is-structure-op-w-wrapper i:term.
466-
is-structure-op-w-wrapper (global (const C)) :- exported-op _ _ C, wrapper-mixin _ (const C) _.
467-
is-structure-op-w-wrapper (app[global (const C)|_]) :- exported-op _ _ C, wrapper-mixin _ (const C) _.
468-
469465
pred derive-wrapper-instances i:term, i:mixinname, o:term, o:constant.
470466
derive-wrapper-instances Instance WrapperMixin WrapperSubject C :- std.do! [
471467

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
@@ -220,7 +219,6 @@ clean-op-ty [exported-op _ Po C|Ops] S T1 T2 :-
220219
gref-deps (const Po) MLwP,
221220
w-params.nparams MLwP NParams,
222221
std.length {list-w-params_list MLwP} NMixins,
223-
224222
(pi L L1 L2 Params Rest PoArgs\
225223
copy (app [global (const Po)| L]) (app [global (const C) | L2]) :-
226224
std.split-at NParams L Params [_|Rest],
@@ -662,19 +660,25 @@ if-coverage-not-good-error.one _ _. % new class is the first covering M
662660
% hom belongs to Quiver, hence hom_isMon takes a "T of Quiver T"
663661

664662
% checks if the term is forall A B C, Factory ... (Op A B C) ...
665-
pred factory-on-some-structure-op? i:term, i:list term, o:gref, o:constant.
663+
pred factory-on-some-structure-op? i:term, i:list term, o:gref, o:gref.
666664
factory-on-some-structure-op? (prod N Ty Bo) VS F OP :-
667665
@pi-decl N Ty x\
668666
factory-on-some-structure-op? (Bo x) [x|VS] F OP.
669-
factory-on-some-structure-op? T VS F OP :-
667+
factory-on-some-structure-op? T VS F (const OP) :-
670668
factory? T (triple F _ Subject),
671669
coq.safe-dest-app Subject (global (const OP)) Args,
672670
exported-op _ _ OP,
673671
std.appendR _ {std.rev VS} Args.
672+
factory-on-some-structure-op? T VS F GR :- std.do! [
673+
factory? T (triple F _ Subject),
674+
coq.safe-dest-app Subject (global GR) Args,
675+
tag GR _ _,
676+
std.appendR _ {std.rev VS} Args,
677+
].
674678

675679
kind factory-on-subject type.
676680
type factory-on-the-type w-args factoryname -> factory-on-subject.
677-
type factory-on-structure-op term -> factoryname -> constant -> factory-on-subject.
681+
type factory-on-structure-op term -> factoryname -> gref -> factory-on-subject.
678682

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

_CoqProject.test-suite

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

56-
examples/cat/cat.v
5756
tests/enriched_cat_case6.v
5857

5958
tests/type_of_exported_ops.v
@@ -96,6 +95,7 @@ tests/unit/mk_src_map.v
9695
tests/unit/close_hole_term.v
9796
tests/unit/struct.v
9897
tests/monoid_enriched_cat.v
98+
tests/tag_wrap.v
9999

100100
-R tests HB.tests
101101
-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
@@ -1043,6 +1048,68 @@ check-or-not Skel :-
10431048
Elpi Typecheck.
10441049
Elpi Export HB.check.
10451050

1051+
(* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% *)
1052+
(* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% *)
1053+
(* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% *)
1054+
1055+
(** [HB.tag] declares a tag for mixin subjects
1056+
1057+
[[
1058+
HB.tag Definition N Params x := x
1059+
]]
1060+
1061+
*)
1062+
1063+
#[arguments(raw)] Elpi Command HB.tag.
1064+
Elpi Accumulate Db hb.db.
1065+
Elpi Accumulate File "HB/common/stdpp.elpi".
1066+
Elpi Accumulate File "HB/common/database.elpi".
1067+
#[skip="8.1[56].*"] Elpi Accumulate File "HB/common/compat_acc_clauses_all.elpi".
1068+
#[only="8.1[56].*"] Elpi Accumulate File "HB/common/compat_acc_clauses_816.elpi".
1069+
Elpi Accumulate File "HB/common/utils.elpi".
1070+
Elpi Accumulate File "HB/common/log.elpi".
1071+
Elpi Accumulate File "HB/common/synthesis.elpi".
1072+
Elpi Accumulate File "HB/context.elpi".
1073+
Elpi Accumulate File "HB/instance.elpi".
1074+
Elpi Accumulate lp:{{
1075+
1076+
main [const-decl Name (some BodySkel) AritySkel] :- !, std.do! [
1077+
std.assert-ok! (coq.elaborate-arity-skeleton AritySkel _ Arity) "HB: type illtyped",
1078+
coq.arity->nparams Arity N,
1079+
coq.arity->term Arity Ty,
1080+
std.assert-ok! (coq.elaborate-skeleton BodySkel Ty Body) "HB: body illtyped",
1081+
with-attributes (with-logging (std.do! [
1082+
log.coq.env.add-const-noimplicits Name Body Ty @transparent! C,
1083+
coq.arity->implicits Arity CImpls,
1084+
if (coq.any-implicit? CImpls)
1085+
(@global! => coq.arguments.set-implicit (const C) [CImpls])
1086+
true,
1087+
])),
1088+
M is N - 1,
1089+
class-of-nth-arg M Ty Class,
1090+
acc-clause current (tag (const C) Class M),
1091+
].
1092+
main [str G, str"|", int M] :- !,
1093+
coq.locate G GR,
1094+
coq.env.typeof GR Ty,
1095+
class-of-nth-arg M Ty Class,
1096+
acc-clause current (tag GR Class M).
1097+
1098+
main _ :- coq.error "Usage: HB.tag Definition <Name> := <Builder> T ...\nUsage: HB.tag <gref> | <nparams>".
1099+
1100+
pred class-of-nth-arg i:int, i:term, o:classname.
1101+
class-of-nth-arg 0 (prod _ (global S) _\_) Class :- class-def (class Class S _).
1102+
class-of-nth-arg 0 (prod _ (app [global S|_]) _\_) Class :- class-def (class Class S _).
1103+
class-of-nth-arg N (prod Name Ty Bo) Class :- N > 0, !, M is N - 1,
1104+
@pi-decl Name Ty x\ class-of-nth-arg M (Bo x) Class.
1105+
class-of-nth-arg 0 T _ :- !,
1106+
coq.error "HB: the last parameter of a tag must be of a structure type:" {coq.term->string T}.
1107+
class-of-nth-arg _ T _ :- !,
1108+
coq.error "HB: not enough argsuments:" {coq.term->string T}.
1109+
1110+
}}.
1111+
Elpi Typecheck.
1112+
Elpi Export HB.tag.
10461113

10471114
(* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% *)
10481115
(* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% *)

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)