From 9da5c2d62b1007f633886d10fa4959382b063597 Mon Sep 17 00:00:00 2001 From: Enrico Tassi Date: Fri, 4 Oct 2019 18:18:38 +0200 Subject: [PATCH] enable map and set from elpi 1.8 --- coq-builtin.elpi | 220 +++++++++++++++++++++++++++++++++++++ src/coq_elpi_vernacular.ml | 2 +- 2 files changed, 221 insertions(+), 1 deletion(-) diff --git a/coq-builtin.elpi b/coq-builtin.elpi index 3ba6d0f08..28b7bae18 100644 --- a/coq-builtin.elpi +++ b/coq-builtin.elpi @@ -1186,6 +1186,226 @@ external pred std.loc.set.elements i:std.loc.set, o:list @loc. % [std.loc.set.cardinal M N] N is the number of elements of M external pred std.loc.set.cardinal i:std.loc.set, o:int. +#line 0 "builtin_map.elpi" +kind std.map type -> type -> type. +type std.map std.map.private.map K V -> (K -> K -> cmp -> prop) -> std.map K V. + +namespace std.map { + +% [make Eq Ltn M] builds an empty map M where keys are compared using Eq and Ltn +pred make i:(K -> K -> cmp -> prop), o:std.map K V. +make Cmp (std.map private.empty Cmp). + +% [find K M V] looks in M for the value V associated to K +pred find i:K, i:std.map K V, o:V. +find K (std.map M Cmp) V :- private.find M Cmp K V. + +% [add K V M M1] M1 is M where K is bound to V +pred add i:K, i:V, i:std.map K V, o:std.map K V. +add K V (std.map M Cmp) (std.map M1 Cmp) :- private.add M Cmp K V M1. + +% [remove K M M1] M1 is M where K is unbound +pred remove i:K, i:std.map K V, o:std.map K V. +remove K (std.map M Cmp) (std.map M1 Cmp) :- private.remove M Cmp K M1. + +% [bindings M L] L is the key-value pairs in increasing order +pred bindings i:std.map K V, o:list (pair K V). +bindings (std.map M _) L :- private.bindings M [] L. + +namespace private { + +% Taken from OCaml's map.ml +kind map type -> type -> type. +type empty map K V. +type node map K V -> K -> V -> map K V -> int -> map K V. + +pred height i:map K V, o:int. +height empty 0. +height (node _ _ _ _ H) H. + +pred create i:map K V, i:K, i:V, i:map K V, o:map K V. +create L K V R (node L K V R H) :- H is {std.max {height L} {height R}} + 1. + +pred bal i:map K V, i:K, i:V, i:map K V, o:map K V. +bal L K V R T :- + height L HL, + height R HR, + HL2 is HL + 2, + HR2 is HR + 2, + bal.aux HL HR HL2 HR2 L K V R T. + +bal.aux HL _ _ HR2 (node LL LV LD LR _) X D R T :- + HL > HR2, {height LL} >= {height LR}, !, + create LL LV LD {create LR X D R} T. +bal.aux HL _ _ HR2 (node LL LV LD (node LRL LRV LRD LRR _) _) X D R T :- + HL > HR2, !, + create {create LL LV LD LRL} LRV LRD {create LRR X D R} T. +bal.aux _ HR HL2 _ L X D (node RL RV RD RR _) T :- + HR > HL2, {height RR} >= {height RL}, !, + create {create L X D RL} RV RD RR T. +bal.aux _ HR HL2 _ L X D (node (node RLL RLV RLD RLR _) RV RD RR _) T :- + HR > HL2, !, + create {create L X D RLL} RLV RLD {create RLR RV RD RR} T. +bal.aux _ _ _ _ L K V R T :- create L K V R T. + +pred add i:map K V, i:(K -> K -> cmp -> prop), i:K, i:V, o:map K V. +add empty _ K V T :- create empty K V empty T. +add (node _ X _ _ _ as M) Cmp X1 XD M1 :- Cmp X1 X E, add.aux E M Cmp X1 XD M1. +add.aux eq (node L _ _ R H) _ X XD T :- T = node L X XD R H. +add.aux lt (node L V D R _) Cmp X XD T :- bal {add L Cmp X XD} V D R T. +add.aux gt (node L V D R _) Cmp X XD T :- bal L V D {add R Cmp X XD} T. + +pred find i:map K V, i:(K -> K -> cmp -> prop), i:K, o:V. +find (node L K1 V1 R _) Cmp K V :- Cmp K K1 E, find.aux E Cmp L R V1 K V. +find.aux eq _ _ _ V _ V. +find.aux lt Cmp L _ _ K V :- find L Cmp K V. +find.aux gt Cmp _ R _ K V :- find R Cmp K V. + +pred remove-min-binding i:map K V, o:map K V. +remove-min-binding (node empty _ _ R _) R :- !. +remove-min-binding (node L V D R _) X :- bal {remove-min-binding L} V D R X. + +pred min-binding i:map K V, o:K, o:V. +min-binding (node empty V D _ _) V D :- !. +min-binding (node L _ _ _ _) V D :- min-binding L V D. + +pred merge i:map K V, i:map K V, o:map K V. +merge empty X X :- !. +merge X empty X :- !. +merge M1 M2 R :- + min-binding M2 X D, + bal M1 X D {remove-min-binding M2} R. + +pred remove i:map K V, i:(K -> K -> cmp -> prop), i:K, o:map K V. +remove empty _ _ empty :- !. +remove (node L V D R _) Cmp X M :- Cmp X V E, remove.aux E Cmp L R V D X M. +remove.aux eq _ L R _ _ _ M :- merge L R M. +remove.aux lt Cmp L R V D X M :- bal {remove L Cmp X} V D R M. +remove.aux gt Cmp L R V D X M :- bal L V D {remove R Cmp X} M. + +pred bindings i:map K V, i:list (pair K V), o:list (pair K V). +bindings empty X X. +bindings (node L V D R _) X X1 :- + bindings L [pr V D|{bindings R X}] X1. + + +} % std.map.private +} % std.map + + +#line 0 "builtin_set.elpi" +kind std.set type -> type. +type std.set std.set.private.set E -> (E -> E -> cmp -> prop) -> std.set E. + +namespace std.set { + +% [make Eq Ltn M] builds an empty set M where keys are compared using Eq and Ltn +pred make i:(E -> E -> cmp -> prop), o:std.set E. +make Cmp (std.set private.empty Cmp). + +% [mem E M] looks if E is in M +pred mem i:E, i:std.set E. +mem E (std.set M Cmp):- private.mem M Cmp E. + +% [add E M M1] M1 is M + {E} +pred add i:E, i:std.set E, o:std.set E. +add E (std.set M Cmp) (std.set M1 Cmp) :- private.add M Cmp E M1. + +% [remove E M M1] M1 is M - {E} +pred remove i:E, i:std.set E, o:std.set E. +remove E (std.set M Cmp) (std.set M1 Cmp) :- private.remove M Cmp E M1. + +% [cardinal S N] N is the number of elements of S +pred cardinal i:std.set E, o:int. +cardinal (std.set M _) N :- private.cardinal M N. + +pred elements i:std.set E, o:list E. +elements (std.set M _) L :- private.elements M [] L. + +namespace private { + +% Taken from OCaml's set.ml +kind set type -> type. +type empty set E. +type node set E -> E -> set E -> int -> set E. + +pred height i:set E, o:int. +height empty 0. +height (node _ _ _ H) H. + +pred create i:set E, i:E, i:set E, o:set E. +create L E R (node L E R H) :- H is {std.max {height L} {height R}} + 1. + +pred bal i:set E, i:E, i:set E, o:set E. +bal L E R T :- + height L HL, + height R HR, + HL2 is HL + 2, + HR2 is HR + 2, + bal.aux HL HR HL2 HR2 L E R T. + +bal.aux HL _ _ HR2 (node LL LV LR _) X R T :- + HL > HR2, {height LL} >= {height LR}, !, + create LL LV {create LR X R} T. +bal.aux HL _ _ HR2 (node LL LV (node LRL LRV LRR _) _) X R T :- + HL > HR2, !, + create {create LL LV LRL} LRV {create LRR X R} T. +bal.aux _ HR HL2 _ L X (node RL RV RR _) T :- + HR > HL2, {height RR} >= {height RL}, !, + create {create L X RL} RV RR T. +bal.aux _ HR HL2 _ L X (node (node RLL RLV RLR _) RV RR _) T :- + HR > HL2, !, + create {create L X RLL} RLV {create RLR RV RR} T. +bal.aux _ _ _ _ L E R T :- create L E R T. + +pred add i:set E, i:(E -> E -> cmp -> prop), i:E, o:set E. +add empty _ E T :- create empty E empty T. +add (node L X R H) Cmp X1 S :- Cmp X1 X E, add.aux E Cmp L R X X1 H S. +add.aux eq _ L R X _ H (node L X R H). +add.aux lt Cmp L R E X _ T :- bal {add L Cmp X} E R T. +add.aux gt Cmp L R E X _ T :- bal L E {add R Cmp X} T. + +pred mem i:set E, i:(E -> E -> cmp -> prop), i:E. +mem (node L K R _) Cmp E :- Cmp E K O, mem.aux O Cmp L R E. +mem.aux eq _ _ _ _. +mem.aux lt Cmp L _ E :- mem L Cmp E. +mem.aux gt Cmp _ R E :- mem R Cmp E. + +pred remove-min-binding i:set E, o:set E. +remove-min-binding (node empty _ R _) R :- !. +remove-min-binding (node L E R _) X :- bal {remove-min-binding L} E R X. + +pred min-binding i:set E, o:E. +min-binding (node empty E _ _) E :- !. +min-binding (node L _ _ _) E :- min-binding L E. + +pred merge i:set E, i:set E, o:set E. +merge empty X X :- !. +merge X empty X :- !. +merge M1 M2 R :- + min-binding M2 X, + bal M1 X {remove-min-binding M2} R. + +pred remove i:set E, i:(E -> E -> cmp -> prop), i:E, o:set E. +remove empty _ _ empty. +remove (node L E R _) Cmp X M :- Cmp X E O, remove.aux O Cmp L R E X M. +remove.aux eq _ L R _ _ M :- merge L R M. +remove.aux lt Cmp L R E X M :- bal {remove L Cmp X} E R M. +remove.aux gt Cmp L R E X M :- bal L E {remove R Cmp X} M. + +pred cardinal i:set E, o:int. +cardinal empty 0. +cardinal (node L _ R _) N :- N is {cardinal L} + 1 + {cardinal R}. + +pred elements i:set E, i:list E, o:list E. +elements empty X X. +elements (node L E R _) Acc X :- + elements L [E|{elements R Acc}] X. + +} % std.set.private +} % std.set + + % % ############################################################################# diff --git a/src/coq_elpi_vernacular.ml b/src/coq_elpi_vernacular.ml index 8e89c4271..d3b8f6a69 100644 --- a/src/coq_elpi_vernacular.ml +++ b/src/coq_elpi_vernacular.ml @@ -176,7 +176,7 @@ let builtin_declarations = LPDoc "#############################################################################"; ] @ core_builtins @ elpi_builtins @ elpi_nonlogical_builtins @ - elpi_stdlib @ + elpi_stdlib @ elpi_map @ elpi_set @ [LPDoc "#############################################################################"; LPDoc "Internal use only (Elpi Print/Typecheck). Please don't use."; LPDoc "#############################################################################"; ] @