Skip to content

Commit 2a10928

Browse files
authored
Merge pull request #334 from math-comp/instance-before-structure
saturate instances on structure declaration
2 parents 7d4f095 + 81cdb25 commit 2a10928

23 files changed

+716
-42
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## Unreleased
44

55
- **Removed** the `#[primitive_class]` attribute, making it the default.
6+
- **New** `HB.saturate` to saturate instances w.r.t. the current hierarchy
67

78
## [1.6.0] - 2023-09-20
89

HB/common/database.elpi

Lines changed: 98 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,38 @@ factories-provide FLwP MLwP :- std.do! [
133133
w-params.map UnsortedMLwP (p\t\ toposort-mixins) MLwP,
134134
].
135135

136+
pred undup-grefs i:list gref, o:list gref.
137+
undup-grefs L UL :- std.do! [
138+
coq.gref.list->set L S,
139+
coq.gref.set.elements S UL,
140+
].
141+
142+
pred undup-sorts i:list sort, o:list sort.
143+
undup-sorts L R :- std.do! [
144+
145+
if (std.mem L prop) (R1 = [prop]) (R1 = []),
146+
if (std.mem L sprop) (R2 = [sprop]) (R2 = []),
147+
if (std.mem L (typ _)) (R3 = [typ _]) (R3 = []),
148+
149+
std.flatten [R1, R2, R3] R,
150+
].
151+
152+
% also prunes cs-default
153+
pred undup-cs-patterns i:list cs-pattern, o:list cs-pattern.
154+
undup-cs-patterns L R :- std.do! [
155+
std.map-filter L (x\r\ x = cs-gref r) LGR,
156+
undup-grefs LGR ULGR,
157+
std.map ULGR (x\r\ r = cs-gref x) R1,
158+
159+
std.map-filter L (x\r\ x = cs-sort r) LS,
160+
undup-sorts LS ULS,
161+
std.map ULS (x\r\ r = cs-sort x) R2,
162+
163+
if (std.mem L cs-prod) (R3 = [cs-prod]) (R3 = []),
164+
165+
std.flatten [R1, R2, R3] R,
166+
].
167+
136168
% Mixins can be topologically sorted according to their dependencies
137169
pred toposort-mixins i:list (w-args mixinname), o:list (w-args mixinname).
138170
toposort-mixins In Out :- std.do! [
@@ -192,6 +224,13 @@ findall-builders LFIL :-
192224
std.map {std.findall (builder-decl B_)} extract-builder LFILunsorted,
193225
std.bubblesort LFILunsorted leq-builder LFIL.
194226

227+
pred findall-has-mixin-instance o:list prop.
228+
findall-has-mixin-instance CL :-
229+
std.findall (has-mixin-instance _ _ _) CL.
230+
231+
pred has-mixin-instance_key i:prop, o:cs-pattern.
232+
has-mixin-instance_key (has-mixin-instance P _ _) P.
233+
195234
pred findall-mixin-src i:term, o:list mixinname.
196235
findall-mixin-src T ML :-
197236
std.map {std.findall (mixin-src T M_ V_)} mixin-src_mixin ML.
@@ -299,7 +338,7 @@ get-constructor (indt R) (indc K) :- !,
299338
if (coq.env.indt R _ _ _ _ [K] _) true (coq.error "Not a record" R).
300339
get-constructor I _ :- coq.error "get-constructor: not an inductive" I.
301340

302-
%% finding for locally defined structures
341+
% finding for locally defined structures
303342
pred get-cs-structure i:cs-instance, o:structure.
304343
get-cs-structure (cs-instance _ _ (const Inst)) Struct :- std.do! [
305344
coq.env.typeof (const Inst) InstTy,
@@ -313,17 +352,64 @@ get-cs-instance (cs-instance _ _ (const Inst)) Inst.
313352
pred has-cs-instance i:gref, i:cs-instance.
314353
has-cs-instance GTy (cs-instance _ (cs-gref GTy) _).
315354

316-
pred term->cs-pattern i:term, o:cs-pattern.
317-
term->cs-pattern (prod _ _ _) cs-prod.
318-
term->cs-pattern (sort U) (cs-sort U).
319-
term->cs-pattern T (cs-gref GR) :- term->gref T GR.
320-
term->cs-pattern T _ :- coq.error T "HB database: is not a valid canonical key".
321-
322-
pred cs-pattern->name i:cs-pattern, o:string.
323-
cs-pattern->name cs-prod "prod".
324-
cs-pattern->name (cs-sort _) "sort".
325-
cs-pattern->name cs-default "default".
326-
cs-pattern->name (cs-gref GR) Name :- gref->modname-label GR 1 "_" Name.
355+
356+
pred mixin-src->has-mixin-instance i:prop, o:prop.
357+
mixin-src->has-mixin-instance (mixin-src (global GR) M I) (has-mixin-instance (cs-gref GR) M IHd) :-
358+
term->gref I IHd.
359+
360+
mixin-src->has-mixin-instance (mixin-src (app [global GR|_] ) M I) (has-mixin-instance (cs-gref GR) M IHd) :-
361+
term->gref I IHd.
362+
363+
mixin-src->has-mixin-instance (mixin-src (prod _ _ _ ) M I) (has-mixin-instance cs-prod M IHd):-
364+
term->gref I IHd.
365+
366+
mixin-src->has-mixin-instance (mixin-src (sort U) M I) (has-mixin-instance (cs-sort U) M IHd):-
367+
term->gref I IHd.
368+
369+
% this auxiliary function iterates over the list of arguments of an application,
370+
% and create the necessary unify condition for each arguments
371+
% and at the end returns the mixin-src clause with all the conditions
372+
pred mixin-instance-type->mixin-src.aux
373+
i:list term, % list of arguments
374+
i:term, % head of the original application
375+
i:mixinname, % name of mixin
376+
i:term, % instance body
377+
i:list prop, % Cond list
378+
o:prop.
379+
mixin-instance-type->mixin-src.aux [] T M I Cond (mixin-src T M I :- Cond).
380+
mixin-instance-type->mixin-src.aux [A|Args] T M I Cond (pi a \ C a) :-
381+
pi a \
382+
sigma Ta\
383+
coq.mk-app T [a] Ta,
384+
mixin-instance-type->mixin-src.aux Args Ta M I [coq.unify-eq A a ok|Cond] (C a).
385+
386+
387+
% transforms the type of a mixin instance into a
388+
% mixin-src clause with eventual conditions regarding its parameters
389+
pred mixin-instance-type->mixin-src
390+
i:term, % type of the instance Ty
391+
i:mixinname, % name of mixin
392+
i:term, % instance body I of type Ty
393+
i:list prop, % Cond list
394+
o:prop.
395+
396+
mixin-instance-type->mixin-src (app _ as F) M I Cond C :-
397+
factory? F (triple _ _ Subject),
398+
safe-dest-app Subject Hd Args,
399+
mixin-instance-type->mixin-src.aux Args Hd M I Cond C.
400+
401+
mixin-instance-type->mixin-src (prod N_ _ F) M I Cond (pi a \ C a) :-
402+
pi a\
403+
sigma Ia \
404+
coq.mk-app I [a] Ia,
405+
mixin-instance-type->mixin-src (F a) M Ia Cond (C a).
406+
407+
pred has-mixin-instance->mixin-src i:prop, o:prop.
408+
has-mixin-instance->mixin-src (has-mixin-instance _ M IHd) C :- std.do![
409+
T = global IHd,
410+
coq.env.typeof IHd Ty,
411+
mixin-instance-type->mixin-src Ty M T [] C,
412+
].
327413

328414
pred get-canonical-structures i:term, o:list structure.
329415
get-canonical-structures TyTrm StructL :- std.do! [

HB/common/stdpp.elpi

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,12 @@ pred coq.env.current-library o:string.
123123
coq.env.current-library L :- loc.fields {get-option "elpi.loc"} L _ _ _ _.
124124
coq.env.current-library "dummy.v".
125125

126+
pred coq.term-is-gref? i:term, o:gref.
127+
coq.term-is-gref? (global GR) GR :- !.
128+
coq.term-is-gref? (pglobal GR _) GR :- !.
129+
coq.term-is-gref? (app [Hd|_]) GR :- !, coq.term-is-gref? Hd GR.
130+
coq.term-is-gref? (let _ _ T x\x) GR :- !, coq.term-is-gref? T GR.
131+
126132
pred coq.prod-tgt->gref i:term, o:gref.
127133
coq.prod-tgt->gref T GR :- whd1 T T1, !, coq.prod-tgt->gref T1 GR.
128134
coq.prod-tgt->gref (prod N Src Tgt) GR :- !, @pi-decl N Src x\ coq.prod-tgt->gref (Tgt x) GR.
@@ -245,3 +251,86 @@ coq.fold-map (primitive _ as C) A C A :- !.
245251
coq.fold-map (uvar M L as X) A W A1 :- var X, !, std.fold-map L A coq.fold-map L1 A1, coq.mk-app-uvar M L1 W.
246252
% when used in CHR rules
247253
coq.fold-map (uvar X L) A (uvar X L1) A1 :- std.fold-map L A coq.fold-map L1 A1.
254+
255+
pred cs-pattern->term i:cs-pattern, o:term.
256+
cs-pattern->term (cs-gref GR) T :- coq.env.global GR T.
257+
cs-pattern->term (cs-sort prop) (sort prop).
258+
cs-pattern->term (cs-sort sprop) (sort sprop).
259+
cs-pattern->term (cs-sort _) T :- coq.elaborate-skeleton {{ Type }} _ T ok.
260+
cs-pattern->term cs-prod T :- coq.elaborate-skeleton (prod `x` Ty_ x\ Bo_ x) _ T ok.
261+
262+
pred term->cs-pattern i:term, o:cs-pattern.
263+
term->cs-pattern (prod _ _ _) cs-prod.
264+
term->cs-pattern (sort U) (cs-sort U).
265+
term->cs-pattern T (cs-gref GR) :- coq.term->gref T GR.
266+
term->cs-pattern T _ :- coq.error T "HB database: is not a valid canonical key".
267+
268+
pred cs-pattern->name i:cs-pattern, o:string.
269+
cs-pattern->name cs-prod "prod".
270+
cs-pattern->name (cs-sort _) "sort".
271+
cs-pattern->name cs-default "default".
272+
cs-pattern->name (cs-gref GR) Name :- gref->modname-label GR 1 "_" Name.
273+
274+
% ---------------------------------------------------------------------
275+
% kit for closing a term by abstracting evars with lambdas
276+
% we use constraints to attach to holes a number
277+
% and replace them by a special node, to later be bound
278+
% via a lambda
279+
280+
namespace abstract-holes {
281+
282+
% we add a new constructor to terms to represent terms to be abstracted
283+
type abs int -> term.
284+
285+
% bind back abstracted subterms
286+
pred bind i:int, i:int, i:term, o:term.
287+
bind I M T T1 :- M > I, !,
288+
T1 = {{ fun x => lp:(B x) }},
289+
N is I + 1,
290+
pi x\ % we allocate the fresh symbol for (abs M)
291+
(copy (abs N) x :- !) => % we schedule the replacement (abs M) -> x
292+
bind N M T (B x).
293+
bind M M T T1 :- copy T T1. % we perform all the replacements
294+
295+
% for a term with M holes, returns a term with M variables to fill these holes
296+
% the clause see is only generated for a term if it hasn't been seen before
297+
% the term might need to be typechecked first or main generates extra holes for the
298+
% type of the parameters
299+
pred main i:term, o:term.
300+
main T1 T3 :- std.do! [
301+
% we put (abs N) in place of each occurrence of the same hole
302+
(pi T Ty N N' M \ fold-map T N (abs M) M :- var T, not (seen? T _), !, coq.typecheck T Ty ok, fold-map Ty N _ N', M is N' + 1, seen! T M) =>
303+
(pi T N M \ fold-map T N (abs M) N :- var T, seen? T M, !) =>
304+
fold-map T1 0 T2 M,
305+
% we abstract M holes (M abs nodes)
306+
bind 0 M T2 T3,
307+
% cleanup constraint store
308+
purge-seen!,
309+
].
310+
311+
% all constraints are also on _ so that they share
312+
% a variable with the constraint to purge the store
313+
314+
% we query if the hole was seen before, and if so
315+
% we fetch its number
316+
pred seen? i:term, o:int.
317+
seen? X Y :- declare_constraint (seen? X Y) [X,_].
318+
319+
% we declare it is now seen and label it with a number
320+
pred seen! i:term, i:int.
321+
seen! X Y :- declare_constraint (seen! X Y) [X,_].
322+
323+
% to empty the store
324+
pred purge-seen!.
325+
purge-seen! :- declare_constraint purge-seen! [_].
326+
327+
constraint seen? seen! purge-seen! {
328+
% a succesful query, give the label back via M
329+
rule (seen! X N) \ (seen? X M) <=> (M = N).
330+
% an unsuccesful query
331+
rule \ (seen? X _) <=> false.
332+
333+
rule purge-seen! \ (seen! _ _).
334+
rule \ purge-seen!.
335+
}
336+
}

HB/common/utils.elpi

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,4 +374,11 @@ prod-last X X :- !.
374374

375375
pred prod-last-gref i:term, o:gref.
376376
prod-last-gref (prod N S X) GR :- !, @pi-decl N S x\ prod-last-gref (X x) GR.
377-
prod-last-gref X GR :- coq.term->gref X GR.
377+
prod-last-gref X GR :- coq.term->gref X GR.
378+
379+
% saturate a type constructor with holes
380+
pred saturate-type-constructor i:term, o:term .
381+
saturate-type-constructor T ET :-
382+
coq.typecheck T TH ok,
383+
coq.count-prods TH N,
384+
coq.mk-app T {coq.mk-n-holes N} ET.

HB/factory.elpi

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ argument->w-mixins (ctx-decl Decl) (pr MLwP ArgwP) :- !, std.do! [
5353
pred argument-name i:argument, o:string.
5454
argument-name (const-decl Id _ _) Id :- !.
5555
argument-name (indt-decl (parameter _ _ _ R)) Id :- !,
56-
argument-name (indt-decl (R (sort prop))) Id.
56+
argument-name (indt-decl (R (sort prop))) Id.
5757
argument-name (indt-decl (record Id _ _ _)) Id :- !.
5858
argument-name (indt-decl (inductive Id _ _ _)) Id :- !.
5959
argument-name (ctx-decl _) "_" :- !.
@@ -231,7 +231,6 @@ declare-mixin-or-factory MixinSrcClauses SectionCanonicalInstance
231231

232232
abstract-over-section TheParams TheType MixinSrcClauses SectionCanonicalInstance coq.abstract-indt-decl RDecl RDeclClosed _,
233233

234-
% coq.say RDecl RDeclClosed,
235234

236235
if (get-option "primitive" tt)
237236
(@primitive! => log.coq.env.add-indt RDeclClosed R)

0 commit comments

Comments
 (0)