1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
|
(* coq-prog-args: ("-top" "bug_5096") *)
Require Import Coq.FSets.FMapPositive Coq.PArith.BinPos Coq.Lists.List.
Set Asymmetric Patterns.
Notation eta x := (fst x, snd x).
Inductive expr {var : Type} : Type :=
| Const : expr
| LetIn : expr -> (var -> expr) -> expr.
Definition Expr := forall var, @expr var.
Fixpoint count_binders (e : @expr unit) : nat :=
match e with
| LetIn _ eC => 1 + @count_binders (eC tt)
| _ => 0
end.
Definition CountBinders (e : Expr) : nat := count_binders (e _).
Class Context (Name : Type) (var : Type) :=
{ ContextT : Type;
extendb : ContextT -> Name -> var -> ContextT;
empty : ContextT }.
Coercion ContextT : Context >-> Sortclass.
Arguments ContextT {_ _ _}, {_ _} _.
Arguments extendb {_ _ _} _ _ _.
Arguments empty {_ _ _}.
Module Export Named.
Inductive expr Name : Type :=
| Const : expr Name
| LetIn : Name -> expr Name -> expr Name -> expr Name.
End Named.
Global Arguments Const {_}.
Global Arguments LetIn {_} _ _ _.
Definition split_onames {Name : Type} (ls : list (option Name))
: option (Name) * list (option Name)
:= match ls with
| cons n ls'
=> (n, ls')
| nil => (None, nil)
end.
Section internal.
Context (InName OutName : Type)
{InContext : Context InName (OutName)}
{ReverseContext : Context OutName (InName)}
(InName_beq : InName -> InName -> bool).
Fixpoint register_reassign (ctxi : InContext) (ctxr : ReverseContext)
(e : expr InName) (new_names : list (option OutName))
: option (expr OutName)
:= match e in Named.expr _ return option (expr _) with
| Const => Some Const
| LetIn n ex eC
=> let '(n', new_names') := eta (split_onames new_names) in
match n', @register_reassign ctxi ctxr ex nil with
| Some n', Some x
=> let ctxi := @extendb _ _ _ ctxi n n' in
let ctxr := @extendb _ _ _ ctxr n' n in
option_map (LetIn n' x) (@register_reassign ctxi ctxr eC new_names')
| None, Some x
=> let ctxi := ctxi in
@register_reassign ctxi ctxr eC new_names'
| _, None => None
end
end.
End internal.
Global Instance pos_context (var : Type) : Context positive var
:= { ContextT := PositiveMap.t var;
extendb ctx key v := PositiveMap.add key v ctx;
empty := PositiveMap.empty _ }.
Global Arguments register_reassign {_ _ _ _} ctxi ctxr e _.
Section language5.
Context (Name : Type).
Local Notation expr := (@bug_5096.expr Name).
Local Notation nexpr := (@Named.expr Name).
Fixpoint ocompile (e : expr) (ls : list (option Name)) {struct e}
: option (nexpr)
:= match e in @bug_5096.expr _ return option (nexpr) with
| bug_5096.Const => Some Named.Const
| bug_5096.LetIn ex eC
=> match @ocompile ex nil, split_onames ls with
| Some x, (Some n, ls')%core
=> option_map (fun C => Named.LetIn n x C) (@ocompile (eC n) ls')
| _, _ => None
end
end.
Definition compile (e : expr) (ls : list Name) := @ocompile e (List.map (@Some _) ls).
End language5.
Global Arguments compile {_} e ls.
Fixpoint merge_liveness (ls1 ls2 : list unit) :=
match ls1, ls2 with
| cons x xs, cons y ys => cons tt (@merge_liveness xs ys)
| nil, ls | ls, nil => ls
end.
Section internal1.
Context (Name : Type)
(OutName : Type)
{Context : Context Name (list unit)}.
Definition compute_livenessf_step
(compute_livenessf : forall (ctx : Context) (e : expr Name) (prefix : list unit), list unit)
(ctx : Context)
(e : expr Name) (prefix : list unit)
: list unit
:= match e with
| Const => prefix
| LetIn n ex eC
=> let lx := @compute_livenessf ctx ex prefix in
let lx := merge_liveness lx (prefix ++ repeat tt 1) in
let ctx := @extendb _ _ _ ctx n (lx) in
@compute_livenessf ctx eC (prefix ++ repeat tt 1)
end.
Fixpoint compute_liveness ctx e prefix
:= @compute_livenessf_step (@compute_liveness) ctx e prefix.
Fixpoint insert_dead_names_gen def (ls : list unit) (lsn : list OutName)
: list (option OutName)
:= match ls with
| nil => nil
| cons live xs
=> match lsn with
| cons n lsn' => Some n :: @insert_dead_names_gen def xs lsn'
| nil => def :: @insert_dead_names_gen def xs nil
end
end.
Definition insert_dead_names def (e : expr Name)
:= insert_dead_names_gen def (compute_liveness empty e nil).
End internal1.
Global Arguments insert_dead_names {_ _ _} def e lsn.
Definition Let_In {A P} (x : A) (f : forall a : A, P a) : P x := let y := x in f y.
Section language7.
Context {Context : Context unit (positive)}.
Local Notation nexpr := (@Named.expr unit).
Definition CompileAndEliminateDeadCode (e : Expr) (ls : list unit)
: option (nexpr)
:= let e := compile (Name:=positive) (e _) (List.map Pos.of_nat (seq 1 (CountBinders e))) in
match e with
| Some e => Let_In (insert_dead_names None e ls) (* help vm_compute by factoring this out *)
(fun names => register_reassign empty empty e names)
| None => None
end.
End language7.
Global Arguments CompileAndEliminateDeadCode {_} e ls.
Definition ContextOn {Name1 Name2} f {var} (Ctx : Context Name1 var) : Context Name2 var
:= {| ContextT := Ctx;
extendb ctx n v := extendb ctx (f n) v;
empty := empty |}.
Definition Register := Datatypes.unit.
Global Instance RegisterContext {var : Type} : Context Register var
:= ContextOn (fun _ => 1%positive) (pos_context var).
Definition syntax := Named.expr Register.
Definition AssembleSyntax e ls (res := CompileAndEliminateDeadCode e ls)
:= match res return match res with None => _ | _ => _ end with
| Some v => v
| None => I
end.
Definition dummy_registers (n : nat) : list Register
:= List.map (fun _ => tt) (seq 0 n).
Definition DefaultRegisters (e : Expr) : list Register
:= dummy_registers (CountBinders e).
Definition DefaultAssembleSyntax e := @AssembleSyntax e (DefaultRegisters e).
Notation "'slet' x := A 'in' b" := (bug_5096.LetIn A (fun x => b)) (at level 200, b at level 200).
Notation "#[ var ]#" := (@bug_5096.Const var).
Definition compiled_syntax : Expr := fun (var : Type) =>
(
slet x1 := #[ var ]# in
slet x1 := #[ var ]# in
slet x1 := #[ var ]# in
slet x1 := #[ var ]# in
slet x1 := #[ var ]# in
slet x1 := #[ var ]# in
slet x1 := #[ var ]# in
slet x1 := #[ var ]# in
slet x1 := #[ var ]# in
slet x1 := #[ var ]# in
slet x1 := #[ var ]# in
slet x1 := #[ var ]# in
slet x1 := #[ var ]# in
slet x1 := #[ var ]# in
slet x1 := #[ var ]# in
slet x1 := #[ var ]# in
slet x1 := #[ var ]# in
@bug_5096.Const var).
Definition v :=
Eval cbv [compiled_syntax] in (DefaultAssembleSyntax (compiled_syntax)).
Timeout 2 Eval vm_compute in v.
|