Skip to content

Commit b24b884

Browse files
authored
Merge pull request #1238 from mattam82/9.0-unsafe-ind-map
New unsafe pass to extract inductives to arbitrary constants
2 parents 1f2c5a0 + 40dcb51 commit b24b884

File tree

8 files changed

+262
-9
lines changed

8 files changed

+262
-9
lines changed

erasure-plugin/_PluginProject.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ src/eCoInductiveToInductive.mli
126126
src/eCoInductiveToInductive.ml
127127
src/eReorderCstrs.mli
128128
src/eReorderCstrs.ml
129+
src/eRemapInductives.mli
130+
src/eRemapInductives.ml
129131
src/eUnboxing.mli
130132
src/eUnboxing.ml
131133
src/eTransform.mli

erasure-plugin/src/g_metarocq_erasure.mlg

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ let make_erasure_config config =
5858
{ enable_unsafe = if config.unsafe then all_unsafe_passes else no_unsafe_passes ;
5959
enable_typed_erasure = config.typed;
6060
dearging_config = default_dearging_config;
61-
inlined_constants = Kernames.KernameSet.empty }
61+
inlined_constants = Kernames.KernameSet.empty;
62+
extracted_inductives = [] }
6263

6364
let time_opt config str fn arg =
6465
if config.time then

erasure-plugin/src/metarocq_erasure_plugin.mlpack

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ EInlineProjections
6868
EConstructorsAsBlocks
6969
ECoInductiveToInductive
7070
EReorderCstrs
71+
ERemapInductives
7172
EUnboxing
7273
EProgram
7374
OptimizePropDiscr

erasure-plugin/theories/ETransform.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1159,4 +1159,4 @@ Instance optional_self_transformation_ext {env term eval} activate tr extends :
11591159
TransformExt.t (@optional_self_transform env term eval activate tr) extends extends.
11601160
Proof.
11611161
red; intros. destruct activate; cbn in * => //. now apply H.
1162-
Qed.
1162+
Qed.

erasure-plugin/theories/Erasure.v

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ From MetaRocq.Template Require Import EtaExpand TemplateProgram.
66
From MetaRocq.PCUIC Require PCUICAst PCUICAstUtils PCUICProgram.
77
From MetaRocq.SafeChecker Require Import PCUICErrors PCUICWfEnvImpl.
88
From MetaRocq.Erasure Require EAstUtils ErasureFunction ErasureCorrectness EPretty Extract.
9-
From MetaRocq.Erasure Require Import EProgram EInlining EBeta.
9+
From MetaRocq.Erasure Require Import EProgram EInlining EBeta ERemapInductives.
1010
From MetaRocq.ErasurePlugin Require Import ETransform.
1111

1212
Import PCUICProgram.
@@ -36,13 +36,15 @@ Record unsafe_passes :=
3636
{ cofix_to_lazy : bool;
3737
inlining : bool;
3838
unboxing : bool;
39+
inductives_extraction : bool;
3940
betared : bool }.
4041

4142
Record erasure_configuration := {
4243
enable_unsafe : unsafe_passes;
4344
enable_typed_erasure : bool;
4445
dearging_config : dearging_config;
45-
inlined_constants : KernameSet.t
46+
inlined_constants : KernameSet.t;
47+
extracted_inductives : extract_inductives;
4648
}.
4749

4850
Definition default_dearging_config :=
@@ -54,7 +56,8 @@ Definition default_dearging_config :=
5456
Definition make_unsafe_passes b :=
5557
{| cofix_to_lazy := b;
5658
inlining := b;
57-
unboxing := b;
59+
unboxing := b;
60+
inductives_extraction := b;
5861
betared := b |}.
5962

6063
Definition no_unsafe_passes := make_unsafe_passes false.
@@ -66,21 +69,25 @@ Definition all_unsafe_passes := make_unsafe_passes true.
6669
Definition default_unsafe_passes :=
6770
{| cofix_to_lazy := true;
6871
inlining := true;
69-
unboxing := false;
72+
unboxing := false;
73+
inductives_extraction := true;
7074
betared := true |}.
7175

7276
Definition default_erasure_config :=
7377
{| enable_unsafe := default_unsafe_passes;
7478
dearging_config := default_dearging_config;
7579
enable_typed_erasure := true;
76-
inlined_constants := KernameSet.empty |}.
80+
inlined_constants := KernameSet.empty;
81+
extracted_inductives := [] |}.
7782

7883
(* This runs only the verified phases without the typed erasure and "fast" remove params *)
7984
Definition safe_erasure_config :=
8085
{| enable_unsafe := no_unsafe_passes;
8186
enable_typed_erasure := false;
8287
dearging_config := default_dearging_config;
83-
inlined_constants := KernameSet.empty |}.
88+
inlined_constants := KernameSet.empty;
89+
extracted_inductives := [];
90+
|}.
8491

8592
Axiom assume_welltyped_template_program_expansion :
8693
forall p (wtp : ∥ wt_template_program_env p ∥),
@@ -131,6 +138,9 @@ Program Definition optional_unsafe_transforms econf :=
131138
ETransform.optional_self_transform passes.(inlining)
132139
(inline_transformation efl final_wcbv_flags econf.(inlined_constants) ▷
133140
forget_inlining_info_transformation efl final_wcbv_flags) ▷
141+
ETransform.optional_self_transform passes.(inductives_extraction)
142+
(extract_inductive_transformation efl final_wcbv_flags econf.(extracted_inductives) ▷
143+
forget_inductive_extraction_info_transformation efl final_wcbv_flags) ▷
134144
(* Heuristically do it twice for more beta-normal terms *)
135145
ETransform.optional_self_transform passes.(betared)
136146
(betared_transformation efl final_wcbv_flags ▷
@@ -145,6 +155,9 @@ Qed.
145155
Next Obligation.
146156
destruct (enable_unsafe econf) as [[] [] [] []]; cbn in * => //; intuition auto.
147157
Qed.
158+
Next Obligation.
159+
destruct (enable_unsafe econf) as [[] [] [] [] []]; cbn in * => //; intuition auto.
160+
Qed.
148161

149162
Program Definition verified_lambdabox_pipeline {guard : abstract_guard_impl}
150163
(efl := EWellformed.all_env_flags)
@@ -1119,7 +1132,8 @@ Definition typed_erasure_config :=
11191132
{| enable_unsafe := no_unsafe_passes;
11201133
dearging_config := default_dearging_config;
11211134
enable_typed_erasure := true;
1122-
inlined_constants := KernameSet.empty |}.
1135+
inlined_constants := KernameSet.empty;
1136+
extracted_inductives := [] |}.
11231137

11241138
(* TODO: Parameterize by a configuration for dearging, allowing to, e.g., override masks. *)
11251139
Program Definition typed_erase_and_print_template_program (p : Ast.Env.program)

erasure/_RocqProject.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ theories/EWcbvEvalCstrsAsBlocksFixLambdaInd.v
4343
theories/ECoInductiveToInductive.v
4444
theories/EUnboxing.v
4545
theories/EReorderCstrs.v
46+
theories/ERemapInductives.v
4647
theories/EImplementBox.v
4748

4849
theories/Typed/Annotations.v

erasure/theories/EProgram.v

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ Import EGlobalEnv EWellformed.
2121
Definition inductive_mapping : Set := Kernames.inductive * (bytestring.string * list nat).
2222
Definition inductives_mapping := list inductive_mapping.
2323

24+
Record extract_inductive :=
25+
{ cstrs : list kername; (* One constant for each constructor *)
26+
elim : kername } (* The new eliminator *).
27+
28+
Definition extract_inductives := list (inductive * extract_inductive).
29+
2430
Definition eprogram := (EAst.global_context * EAst.term).
2531
Definition eprogram_env := (EEnvMap.GlobalContextMap.t * EAst.term).
2632

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
From Stdlib Require Import List String Arith Lia ssreflect ssrbool Morphisms.
2+
Import ListNotations.
3+
From Equations Require Import Equations.
4+
Set Equations Transparent.
5+
6+
From MetaRocq.PCUIC Require Import PCUICAstUtils.
7+
From MetaRocq.Utils Require Import MRList bytestring utils monad_utils.
8+
From MetaRocq.Erasure Require Import EProgram EPrimitive EAst ESpineView EEtaExpanded EInduction EGlobalEnv
9+
EAstUtils ELiftSubst EWellformed ECSubst EWcbvEval.
10+
11+
Import Kernames.
12+
Import MRMonadNotation.
13+
14+
Lemma lookup_declared_constructor {Σ id mdecl idecl cdecl} :
15+
lookup_constructor Σ id.1 id.2 = Some (mdecl, idecl, cdecl) ->
16+
declared_constructor Σ id mdecl idecl cdecl.
17+
Proof.
18+
rewrite /lookup_constructor /declared_constructor.
19+
rewrite /declared_inductive /lookup_inductive.
20+
rewrite /declared_minductive /lookup_minductive.
21+
destruct lookup_env => //=. destruct g => //=.
22+
destruct nth_error eqn:hn => //. destruct (nth_error _ id.2) eqn:hn' => //.
23+
intros [= <- <- <-]. intuition auto.
24+
Qed.
25+
26+
Fixpoint lookup_inductive_assoc {A} (Σ : list (inductive × A)) (kn : inductive) {struct Σ} : option A :=
27+
match Σ with
28+
| [] => None
29+
| d :: tl => if kn == d.1 then Some d.2 else lookup_inductive_assoc tl kn
30+
end.
31+
32+
Equations filter_map {A B} (f : A -> option B) (l : list A) : list B :=
33+
| f, [] := []
34+
| f, x :: xs with f x := {
35+
| None => filter_map f xs
36+
| Some x' => x' :: filter_map f xs }.
37+
38+
Section Remap.
39+
Context (Σ : global_declarations).
40+
Context (mapping : extract_inductives).
41+
42+
Definition lookup_constructor_mapping i c : option kername :=
43+
trs <- lookup_inductive_assoc mapping i ;;
44+
nth_error trs.(cstrs) c.
45+
46+
Definition lookup_constructor_remapping i c args :=
47+
match lookup_constructor_mapping i c with
48+
| None => tConstruct i c args
49+
| Some c' => mkApps (tConst c') args
50+
end.
51+
52+
Fixpoint it_mkLambda nas t :=
53+
match nas with
54+
| [] => t
55+
| na :: nas => tLambda na (it_mkLambda nas t)
56+
end.
57+
58+
Definition make_branch '(ctx, br) :=
59+
match #|ctx| with
60+
| 0 => tLambda BasicAst.nAnon (lift 1 0 br)
61+
| _ => it_mkLambda ctx br
62+
end.
63+
64+
Definition remap_case i c brs :=
65+
match lookup_inductive_assoc mapping (fst i) with
66+
| None => tCase i c brs
67+
| Some tr =>
68+
mkApps (tConst tr.(elim)) (map make_branch brs)
69+
end.
70+
71+
Equations remap (t : term) : term :=
72+
| tVar na => tVar na
73+
| tLambda nm bod => tLambda nm (remap bod)
74+
| tLetIn nm dfn bod => tLetIn nm (remap dfn) (remap bod)
75+
| tApp fn arg => tApp (remap fn) (remap arg)
76+
| tConst nm => tConst nm
77+
| tConstruct i m args => lookup_constructor_remapping i m (map remap args)
78+
| tCase i mch brs =>
79+
let brs := map (on_snd remap) brs in
80+
let mch := remap mch in
81+
remap_case i mch brs
82+
| tFix mfix idx => tFix (map (map_def remap) mfix) idx
83+
| tCoFix mfix idx => tCoFix (map (map_def remap) mfix) idx
84+
| tProj p bod =>
85+
tProj p (remap bod)
86+
| tPrim p => tPrim (map_prim remap p)
87+
| tLazy t => tLazy (remap t)
88+
| tForce t => tForce (remap t)
89+
| tRel n => tRel n
90+
| tBox => tBox
91+
| tEvar ev args => tEvar ev (map remap args).
92+
93+
Definition remap_constant_decl cb :=
94+
{| cst_body := option_map remap cb.(cst_body) |}.
95+
96+
Definition remaped_one_ind kn i (oib : one_inductive_body) : bool :=
97+
match lookup_inductive_assoc mapping {| inductive_mind := kn; inductive_ind := i |} with
98+
| None => false
99+
| Some trs => true
100+
end.
101+
102+
Definition remap_inductive_decl kn idecl :=
103+
let remapings := mapi (remaped_one_ind kn) idecl.(ind_bodies) in
104+
List.forallb (fun b => b) remapings.
105+
106+
Definition remap_decl d :=
107+
match d.2 with
108+
| ConstantDecl cb => Some (d.1, ConstantDecl (remap_constant_decl cb))
109+
| InductiveDecl idecl => if remap_inductive_decl d.1 idecl then None else Some d
110+
end.
111+
112+
Definition remap_env Σ :=
113+
filter_map (remap_decl) Σ.
114+
115+
End Remap.
116+
117+
Definition remap_program mapping (p : program) : program :=
118+
(remap_env mapping p.1, remap mapping p.2).
119+
120+
From MetaRocq.Erasure Require Import EProgram EWellformed EWcbvEval.
121+
From MetaRocq.Common Require Import Transform.
122+
123+
Definition inductives_extraction_program :=
124+
(global_context × extract_inductives) × term.
125+
126+
Definition inductives_extraction_program_inlinings (pr : inductives_extraction_program) : extract_inductives :=
127+
pr.1.2.
128+
129+
Coercion inductives_extraction_program_inlinings : inductives_extraction_program >-> extract_inductives.
130+
131+
Definition extract_inductive_program mapping (p : program) : inductives_extraction_program :=
132+
let Σ' := remap_env mapping p.1 in
133+
(Σ', mapping, remap mapping p.2).
134+
135+
Definition forget_inductive_extraction_info (pr : inductives_extraction_program) : eprogram :=
136+
let '((Σ', inls), p) := pr in
137+
(Σ', p).
138+
139+
Coercion forget_inductive_extraction_info : inductives_extraction_program >-> eprogram.
140+
141+
Definition eval_inductives_extraction_program wfl (pr : inductives_extraction_program) := eval_eprogram wfl pr.
142+
143+
Axiom trust_inductive_extraction_wf :
144+
forall efl : EEnvFlags,
145+
WcbvFlags ->
146+
forall inductive_extraction : extract_inductives,
147+
forall (input : Transform.program _ term),
148+
wf_eprogram efl input -> wf_eprogram efl (extract_inductive_program inductive_extraction input).
149+
Axiom trust_inductive_extraction_pres :
150+
forall (efl : EEnvFlags) (wfl : WcbvFlags) inductive_extraction (p : Transform.program _ term)
151+
(v : term),
152+
wf_eprogram efl p ->
153+
eval_eprogram wfl p v ->
154+
exists v' : term,
155+
let ip := extract_inductive_program inductive_extraction p in
156+
eval_eprogram wfl ip v' /\ v' = remap ip v.
157+
158+
Import Transform.
159+
160+
Program Definition extract_inductive_transformation (efl : EEnvFlags) (wfl : WcbvFlags) inductive_extraction :
161+
Transform.t _ _ EAst.term EAst.term _ _
162+
(eval_eprogram wfl) (eval_inductives_extraction_program wfl) :=
163+
{| name := "inductive_extraction ";
164+
transform p _ := extract_inductive_program inductive_extraction p ;
165+
pre p := wf_eprogram efl p ;
166+
post (p : inductives_extraction_program) := wf_eprogram efl p ;
167+
obseq p hp (p' : inductives_extraction_program) v v' := v' = remap p' v |}.
168+
169+
Next Obligation.
170+
now apply trust_inductive_extraction_wf.
171+
Qed.
172+
Next Obligation.
173+
now eapply trust_inductive_extraction_pres.
174+
Qed.
175+
176+
#[global]
177+
Axiom trust_inline_transformation_ext :
178+
forall (efl : EEnvFlags) (wfl : WcbvFlags) inductive_extraction,
179+
TransformExt.t (extract_inductive_transformation efl wfl inductive_extraction)
180+
(fun p p' => extends p.1 p'.1) (fun p p' => extends p.1.1 p'.1.1).
181+
182+
Definition extends_inductives_extraction_eprogram (p q : inductives_extraction_program) :=
183+
extends p.1.1 q.1.1 /\ p.2 = q.2.
184+
185+
#[global]
186+
Axiom trust_inline_transformation_ext' :
187+
forall (efl : EEnvFlags) (wfl : WcbvFlags) inductive_extraction,
188+
TransformExt.t (extract_inductive_transformation efl wfl inductive_extraction)
189+
extends_eprogram extends_inductives_extraction_eprogram.
190+
191+
192+
Program Definition forget_inductive_extraction_info_transformation (efl : EEnvFlags) (wfl : WcbvFlags) :
193+
Transform.t _ _ EAst.term EAst.term _ _
194+
(eval_inductives_extraction_program wfl) (eval_eprogram wfl) :=
195+
{| name := "forgetting about inductive_extraction info";
196+
transform p _ := (p.1.1, p.2) ;
197+
pre (p : inductives_extraction_program) := wf_eprogram efl p ;
198+
post (p : eprogram) := wf_eprogram efl p ;
199+
obseq p hp p' v v' := v' = v |}.
200+
201+
Next Obligation.
202+
destruct input as [[Σ inls] t].
203+
exact p.
204+
Qed.
205+
Next Obligation.
206+
exists v; split => //. subst p'.
207+
now destruct p as [[Σ inls] t].
208+
Qed.
209+
210+
#[global]
211+
Lemma forget_inductive_extraction_info_transformation_ext :
212+
forall (efl : EEnvFlags) (wfl : WcbvFlags),
213+
TransformExt.t (forget_inductive_extraction_info_transformation efl wfl)
214+
(fun p p' => extends p.1.1 p'.1.1) (fun p p' => extends p.1 p'.1).
215+
Proof.
216+
intros.
217+
red. now intros [[] ?] [[] ?]; cbn.
218+
Qed.
219+
220+
#[global]
221+
Lemma forget_inductive_extraction_info_transformation_ext' :
222+
forall (efl : EEnvFlags) (wfl : WcbvFlags),
223+
TransformExt.t (forget_inductive_extraction_info_transformation efl wfl)
224+
extends_inductives_extraction_eprogram extends_eprogram.
225+
Proof.
226+
intros ? ? [[] ?] [[] ?]; cbn.
227+
now rewrite /extends_inductives_extraction_eprogram /extends_eprogram /=.
228+
Qed.

0 commit comments

Comments
 (0)