Skip to content

Commit 9b2e996

Browse files
authored
Merge pull request #305 from proux01/paths
Add command HB.howto
2 parents a42b2e0 + 39a63e0 commit 9b2e996

16 files changed

+484
-452
lines changed

HB/about.elpi

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ main-located S (loc-gref GR) :- class-def (class Class GR MLwP), !,
1515
private.main-structure S Class GR MLwP.
1616

1717
main-located _ (loc-gref Class) :- class-def (class Class GR MLwP), !,
18-
gref->modname GR 2 "." M,
18+
gref->modname_short GR "." M,
1919
coq.gref->id GR St,
2020
S is M ^ "." ^ St,
2121
private.main-structure S Class GR MLwP.
@@ -45,7 +45,7 @@ main-located S (loc-gref GR) :- from Factory Mixin GR, !,
4545
private.main-builder S Factory Mixin.
4646

4747
main-located S (loc-gref GR) :-
48-
std.filter {coq.CS.db-for _ (cs-gref GR)} (private.not1 private.unif-hint?) LV,
48+
std.filter {coq.CS.db-for _ (cs-gref GR)} (not1 unif-hint?) LV,
4949
coq.CS.db-for GR _ LP,
5050
std.filter {coq.coercion.db} (c\c = coercion GR _ _ _) LC,
5151
if (LV = [], LP = [], LC = [])
@@ -57,6 +57,29 @@ main-located S (loc-gref GR) :-
5757

5858
main-located S (loc-abbreviation _) :- coq.error "HB: unknown abbreviation" S.
5959

60+
/* things also used in paths.elpi ------------------------------------------ */
61+
62+
shorten coq.pp.{ v , h, hv, hov , spc , str , box , glue , brk , empty }.
63+
64+
pred bulletize1 i:(A -> coq.pp -> prop), i:A, o:coq.pp.
65+
bulletize1 F X (glue [str "- ", M]) :- F X M.
66+
67+
pred bulletize i:list A, i:(A -> coq.pp -> prop), o:coq.pp.
68+
bulletize [] _ empty.
69+
bulletize L F (glue [brk 0 0 | PLB]) :-
70+
std.map L (bulletize1 F) PL,
71+
std.intersperse (brk 0 0) PL PLB.
72+
73+
% Print shortest qualified identifier of the module containing a gref
74+
pred pp-module i:gref, o:coq.pp.
75+
pp-module GR (str ID) :- gref->modname_short GR "." ID.
76+
77+
pred unif-hint? i:cs-instance.
78+
unif-hint? (cs-instance _ (cs-gref GR) _) :- coq.CS.db-for GR _ [_|_].
79+
80+
pred not1 i:(A -> prop), i:A.
81+
not1 P X :- not (P X).
82+
6083

6184
/* ------------------------------------------------------------------------- */
6285
/* ----------------------------- private code ------------------------------ */
@@ -76,7 +99,7 @@ main-canonical-value S CanonicalValues :-
7699
group-by-loc CanonicalValues CanonicalValuesL,
77100
%format
78101
PpCanonicalValues = box (v 4) [
79-
str "HB: ", str S, str " is canonically equipped with mixins:",
102+
str "HB: ", str S, str " is canonically equipped with structures:",
80103
{bulletize CanonicalValuesL pp-canonical-solution-list}],
81104
% print
82105
coq.say {coq.pp->string PpCanonicalValues},
@@ -101,7 +124,7 @@ pred pp-canonical-solution i:cs-instance, o:coq.pp.
101124
pp-canonical-solution (cs-instance _Proj _Pat GR) Pp :-
102125
coq.env.typeof GR T,
103126
coq.prod-tgt->gref T F,
104-
if (class-def (class _ F _)) (gref->modname F 2 "." ID) (coq.gref->string F ID),
127+
if (class-def (class _ F _)) (gref->modname_short F "." ID) (coq.gref->string F ID),
105128
Pp = box (hov 0) [ str ID ].
106129

107130
pred main-canonical-projection i:string, i:gref, i:list cs-instance.
@@ -127,11 +150,11 @@ pred main-coercion i:string, i:list coercion.
127150
main-coercion S [coercion GR _ Src Tgt|_] :-
128151
% format
129152
if (class-def (class _ Src _) ; class-def (class Src _ _))
130-
(Source = str {gref->modname Src 2 "."})
153+
(Source = str {gref->modname_short Src "."})
131154
(coq.term->pp (global Src) Source),
132155
if2 (Tgt = grefclass TGR)
133156
(if (class-def (class _ TGR _) ; class-def (class TGR _ _))
134-
(Target = str {gref->modname TGR 2 "."})
157+
(Target = str {gref->modname_short TGR "."})
135158
(coq.term->pp (global TGR) Target))
136159
(Tgt = sortclass)
137160
(Target = str "Sortclass")
@@ -306,7 +329,7 @@ main-factory-alias S _Const :-
306329
pred main-builder i:string, i:factoryname, i:mixinname.
307330
main-builder _S From To :-
308331
coq.say "HB: todo HB.about for builder from"
309-
{gref->modname From 2 "."} "to" {gref->modname To 2 "."}.
332+
{gref->modname_short From "."} "to" {gref->modname_short To "."}.
310333

311334
pred compute-field-info.aux i:list id, i:list implicit_kind, o:list coq.pp.
312335
compute-field-info.aux [] _ [].
@@ -323,9 +346,6 @@ compute-field-info Names Impls O :-
323346
compute-field-info.aux {std.rev Names} {std.rev Impls} Pp,
324347
std.intersperse spc {std.rev Pp} O.
325348

326-
pred pp-module i:gref, o:coq.pp.
327-
pp-module M (str ID) :- gref->modname M 2 "." ID.
328-
329349
pred pp-const i:constant, o:coq.pp.
330350
pp-const F (str ID) :- coq.gref->id (const F) ID.
331351

@@ -336,15 +356,6 @@ pred pp-if-verbose o:coq.pp, i:(coq.pp -> prop).
336356
pp-if-verbose V P :- get-option "verbose" tt, !, P V.
337357
pp-if-verbose empty _.
338358

339-
pred bulletize1 i:(A -> coq.pp -> prop), i:A, o:coq.pp.
340-
bulletize1 F X (glue [str "- ", M]) :- F X M.
341-
342-
pred bulletize i:list A, i:(A -> coq.pp -> prop), o:coq.pp.
343-
bulletize [] _ empty.
344-
bulletize L F (glue [brk 0 0 | PLB]) :-
345-
std.map L (bulletize1 F) PL,
346-
std.intersperse (brk 0 0) PL PLB.
347-
348359
pred pp-loc-of i:gref, o:coq.pp.
349360
pp-loc-of GR PP :- decl-location GR Loc, !, pp-loc Loc PP.
350361
pp-loc-of _ coq.pp.empty.
@@ -377,10 +388,4 @@ print-docstring GR :-
377388
(coq.say {coq.pp->string (box (hov 5) [str"Doc: ",Doc])})
378389
true.
379390

380-
pred unif-hint? i:cs-instance.
381-
unif-hint? (cs-instance _ (cs-gref GR) _) :- coq.CS.db-for GR _ [_|_].
382-
383-
pred not1 i:(A -> prop), i:A.
384-
not1 P X :- not (P X).
385-
386391
}}

HB/common/stdpp.elpi

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,25 @@ under.do! Then LP :- Then (_\ std.do! LP) _.
4848
pred map-triple i:(A -> A1 -> prop), i:(B -> B1 -> prop), i:(C -> C1 -> prop), i:triple A B C, o:triple A1 B1 C1.
4949
map-triple F G H (triple X Y Z) (triple X1 Y1 Z1) :- F X X1, G Y Y1, H Z Z1.
5050

51+
pred sort.split i:list A, o:list A, o:list A.
52+
sort.split [] [] [] :- !.
53+
sort.split [X] [X] [] :- !.
54+
sort.split [X,Y|TL] [X|L1] [Y|L2] :- sort.split TL L1 L2.
55+
56+
pred sort.merge i:(A -> A -> prop), i:list A, i:list A, o:list A.
57+
sort.merge _ [] L L :- !.
58+
sort.merge _ L [] L :- !.
59+
sort.merge Rel [X1|L1] [X2|L2] [X1|M] :- Rel X1 X2, !,
60+
sort.merge Rel L1 [X2|L2] M.
61+
sort.merge Rel [X1|L1] [X2|L2] [X2|M] :-
62+
sort.merge Rel [X1|L1] L2 M.
63+
64+
pred sort i:list A, i:(A -> A -> prop), o:list A.
65+
sort [] _ [] :- !.
66+
sort [X] _ [X] :- !.
67+
sort L Rel M :-
68+
sort.split L L1 L2, sort L1 Rel S1, sort L2 Rel S2, sort.merge Rel S1 S2 M.
69+
5170
pred bubblesort i:list A, i:(A -> A -> prop), o:list A.
5271
bubblesort [] _ [] :- !.
5372
bubblesort [X] _ [X] :- !.

HB/common/utils.elpi

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,27 @@ gref->modname-label GR NComp Sep ModName :-
137137
std.take N PathRev L,
138138
std.string.concat Sep {std.rev [{coq.gref->id GR}|L]} ModName.
139139

140+
pred string->modpath i:string, o:modpath.
141+
string->modpath S MP :-
142+
std.filter {coq.locate-all S} (l\l = loc-modpath _) L,
143+
L = [loc-modpath MP].
144+
145+
pred gref->modname_short1 i:modpath, i:string, i:list string, o:string.
146+
gref->modname_short1 _ S [] S.
147+
gref->modname_short1 MP "" [X|L] L' :- gref->modname_short1 MP X L L'.
148+
gref->modname_short1 MP S _ S :- string->modpath S MP.
149+
gref->modname_short1 MP S [X|L] S' :-
150+
gref->modname_short1 MP {std.string.concat "." [X,S]} L S'.
151+
152+
% Print shortest qualified identifier of the module containing a gref
153+
% Sep is used as separator
154+
pred gref->modname_short i:gref, i:string, o:string.
155+
gref->modname_short GR Sep IDS :-
156+
coq.gref->path GR Path,
157+
string->modpath {std.string.concat "." Path} MP,
158+
gref->modname_short1 MP "" {std.rev Path} ID,
159+
rex.replace "[.]" Sep ID IDS.
160+
140161
pred avoid-name-collision i:string, o:string.
141162
avoid-name-collision S S1 :-
142163
coq.locate-all S L,

HB/graph.elpi

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,11 @@ to-file File :- !, std.do! [
1818

1919
namespace private {
2020

21-
pred gref->modname i:gref, i:int, i:string, o:string.
22-
gref->modname GR NComp Sep ModName :-
23-
coq.gref->path GR Path,
24-
std.rev Path Mods,
25-
std.length Path Len,
26-
if (Len >= NComp) true (coq.error "Not enough enclosing modules for" {coq.gref->string GR}),
27-
std.take NComp Mods L,
28-
std.string.concat Sep {std.rev L} ModName.
29-
3021
pred pp-coercion-dot i:out_stream, i:coercion.
3122
pp-coercion-dot OC (coercion _ _ Src (grefclass Tgt)) :- class-def (class Src _ _), class-def (class Tgt _ _), !, std.do! [
32-
output OC {gref->modname Tgt 2 "_"},
23+
output OC {gref->modname_short Tgt "_"},
3324
output OC " -> ",
34-
output OC {gref->modname Src 2 "_"},
25+
output OC {gref->modname_short Src "_"},
3526
output OC ";\n",
3627
].
3728
pp-coercion-dot _ _.

HB/howto.elpi

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
/* Hierarchy Builder: algebraic hierarchies made easy
2+
This software is released under the terms of the MIT license */
3+
4+
namespace howto {
5+
6+
pred main-trm i:term, i:string, i:option int.
7+
main-trm T STgt Depth :- coq.term->gref T GR, main-gref GR STgt Depth.
8+
9+
pred main-str i:string, i:string, i:option int.
10+
main-str S STgt Depth :- coq.locate S GR, main-gref GR STgt Depth.
11+
12+
pred main-gref i:gref, i:string, i:option int.
13+
main-gref GR STgt Depth :- class-def (class _ GR _), !,
14+
private.mixins-in-structures [GR] MLSrc,
15+
main-from MLSrc STgt Depth.
16+
main-gref GR STgt Depth :-
17+
private.structures-on-gref GR SL,
18+
private.mixins-in-structures SL MLSrc,
19+
main-from MLSrc STgt Depth.
20+
21+
pred main-from i:list mixinname, i:string, i:option int.
22+
main-from MLSrc STgt Depth :-
23+
private.mixins-in-structures [{coq.locate STgt}] MLTgt,
24+
private.list-diff MLTgt MLSrc ML,
25+
if (ML = []) (coq.say "HB: nothing to do.") (main-from.aux MLSrc ML Depth).
26+
main-from.aux MLSrc ML (some Depth) :- main-increase-depth MLSrc ML Depth false.
27+
main-from.aux MLSrc ML none :- main-increase-depth MLSrc ML 3 true.
28+
29+
pred main-increase-depth i:list mixinname, i:list mixinname, i:int, i:prop.
30+
main-increase-depth MLSrc ML Depth AutoIncrease :-
31+
private.paths-from-for-step MLSrc ML Depth R,
32+
if (not (R = [])) (private.pp-solutions R)
33+
(if AutoIncrease
34+
(Depth' is Depth + 1,
35+
coq.say "HB: no solution found at depth" Depth "looking at depth" Depth',
36+
main-increase-depth MLSrc ML Depth' true)
37+
(coq.error "HB: no solution found, try to increase search depth.")).
38+
39+
40+
/* ------------------------------------------------------------------------- */
41+
/* ----------------------------- private code ------------------------------ */
42+
/* ------------------------------------------------------------------------- */
43+
44+
namespace private {
45+
46+
shorten coq.pp.{ v , hov , spc , str , box , glue }.
47+
48+
% L1 \subseteq L2
49+
pred incl i:list A, i:list A.
50+
incl L1 L2 :- std.forall L1 (std.mem L2).
51+
52+
% R = L1 \ L2
53+
pred list-diff i:list A, i:list A, o:list A.
54+
list-diff L1 L2 R :- std.filter L1 (about.not1 (std.mem L2)) R.
55+
56+
% R = L1 U L2
57+
pred union i:list A, i:list A, o:list A.
58+
union L1 L2 R :-
59+
std.fold L2 L1 (x\l\l'\if (std.mem l x) (l' = l) (l' = [x|l])) R.
60+
61+
pred insert-sorted i:(A -> A -> prop), i:A, i:list A, o:list A.
62+
insert-sorted _ X [] [X] :- !.
63+
insert-sorted Rel X [Y|T] [X,Y|T] :- Rel X Y, !.
64+
insert-sorted Rel X [Y|T] [Y|T'] :- insert-sorted Rel X T T', !.
65+
66+
pred lt-gref i:gref, i:gref.
67+
lt-gref X Y :-
68+
gref->modname_short X "." SX, gref->modname_short Y "." SY, !, SX s< SY.
69+
70+
pred size-order i:(list A -> list A -> prop), i:list A, i:list A.
71+
size-order Rel L1 L2 :-
72+
std.length L1 S1, std.length L2 S2, !, (S1 i< S2; (S1 = S2, !, Rel L1 L2)).
73+
74+
pred lexi-order i:list gref, i:list gref.
75+
lexi-order [] [].
76+
lexi-order [X1|_] [X2|_] :- lt-gref X1 X2.
77+
lexi-order [X|T1] [X|T2] :- lexi-order T1 T2.
78+
79+
% [structures-on-gref GR ML] list structures [GR] is equipped with
80+
pred structures-on-gref i:gref, o:list structure.
81+
structures-on-gref GR SL :-
82+
std.filter {coq.CS.db-for _ (cs-gref GR)} (about.not1 about.unif-hint?) LV,
83+
std.map LV structures-on-gref.aux SL.
84+
structures-on-gref.aux (cs-instance _ _ GR) F :-
85+
coq.prod-tgt->gref {coq.env.typeof GR} F, class-def (class _ F _).
86+
87+
% [mixins-in-structures SL ML] list mixins in structures [SL]
88+
pred mixins-in-structures i:list structure, o:list mixinname.
89+
mixins-in-structures SL ML :- std.fold SL [] mixins-in-structures.aux ML.
90+
mixins-in-structures.aux F L L' :-
91+
class-def (class _ F MLWP), union L {list-w-params_list MLWP} L'.
92+
93+
% a type to store a factory along with the mixins it depends on
94+
% and the mixins it provides
95+
kind factory_deps_prov type.
96+
type fdp factoryname -> list mixinname -> list mixinname -> factory_deps_prov.
97+
98+
% get all available factories in the above type
99+
pred list_factories o:list factory_deps_prov.
100+
list_factories FL :-
101+
std.map-filter {std.findall (factory-constructor _ _)} list_factories.aux FL.
102+
list_factories.aux (factory-constructor F _) (fdp F DML PML) :-
103+
list-w-params_list {gref-deps F} DML,
104+
list-w-params_list {factory-provides F} PML.
105+
106+
% [paths-from-for-step MLSrc ML K R] returns in [R] a list of sequences
107+
% of at most [K] factories that could, starting from mixins [MLSrc],
108+
% build exactly the mixins [ML]
109+
pred paths-from-for-step i:list mixinname, i:list mixinname, i:int,
110+
o:list (list factoryname).
111+
paths-from-for-step MLSrc ML K R :-
112+
std.filter {list_factories} (fd\sigma pml\fd = fdp _ _ pml, incl pml ML) FL,
113+
paths-from-for-step-using MLSrc ML K [] [] FL _ R.
114+
115+
% [paths-from-for-step-using MLSrc ML K Pre KnownPre FL KnownPre' R]
116+
% same as [paths-from-for-step MLSrc ML K R] using only factories in [FL]
117+
% [Pre] is a (sorted) prefix that is looked into the list of known (sorted)
118+
% prefixes [KnownPre] to avoid generating identical solutions up to permutations
119+
pred paths-from-for-step-using i:list mixinname, i:list mixinname, i:int,
120+
i:list factoryname, i:list (list factoryname), i:list factory_deps_prov,
121+
o:list (list factoryname), o:list (list factoryname).
122+
paths-from-for-step-using _ _ K _ KnownPre _ KnownPre [] :- K i< 0.
123+
paths-from-for-step-using _ _ _ Pre KnownPre _ KnownPre [] :-
124+
std.mem KnownPre Pre, !.
125+
paths-from-for-step-using _ [] _ Pre KnownPre _ [Pre|KnownPre] [[]] :- !.
126+
paths-from-for-step-using MLSrc ML K Pre KnownPre FL [Pre|KnownPre'] R :-
127+
K' is K - 1,
128+
std.filter FL (p\sigma dml\p = fdp _ dml _, incl dml MLSrc) FLdep,
129+
std.fold FLdep (pr KnownPre [])
130+
(paths-from-for-step-using.aux MLSrc ML FL K' Pre)
131+
(pr KnownPre' R).
132+
paths-from-for-step-using.aux MLSrc ML FL' K' Pre (fdp F _ MLF) (pr KnPre L)
133+
(pr KnPre' R) :-
134+
std.append MLSrc MLF MLSrc',
135+
list-diff ML MLF ML',
136+
insert-sorted lt-gref F Pre Pre',
137+
std.filter FL' (p\sigma pml\p = fdp _ _ pml, incl pml ML') FML',
138+
paths-from-for-step-using MLSrc' ML' K' Pre' KnPre FML' KnPre' R',
139+
std.map R' (l\r\r = [F|l]) R'',
140+
std.append L R'' R.
141+
142+
pred pp-solutions i:list (list factoryname).
143+
pp-solutions LLF :-
144+
std.sort LLF (size-order lexi-order) SLLF,
145+
% format
146+
PpSolutions = box (v 4) [
147+
str "HB: solutions (use 'HB.about F.Build' to see the arguments of each factory F):",
148+
{about.bulletize SLLF pp-solution}],
149+
% print
150+
coq.say {coq.pp->string PpSolutions},
151+
coq.say.
152+
153+
pred pp-solution i:list factoryname o:coq.pp.
154+
pp-solution L (box (hov 0) PLS) :-
155+
std.map L about.pp-module PL,
156+
std.intersperse (glue [str ";", spc]) PL PLS.
157+
158+
}}

Makefile.test-suite.coq.local

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ DIFF=\
1919
post-all::
2020
$(call DIFF, tests/compress_coe.v)
2121
$(call DIFF, tests/about.v)
22+
$(call DIFF, tests/howto.v)
2223
$(call DIFF, tests/missing_join_error.v)
2324
$(call DIFF, tests/not_same_key.v)
2425
$(call DIFF, tests/hnf.v)

0 commit comments

Comments
 (0)