diff options
author | Jason Gross <jgross@mit.edu> | 2018-04-30 14:29:16 -0400 |
---|---|---|
committer | Jason Gross <jasongross9@gmail.com> | 2018-05-05 18:01:31 -0400 |
commit | a8bc8196c119df719867690faca0cd1f99b18eff (patch) | |
tree | 3cb8540455abca75998acc2e63e387ec1ec2101d /src/Experiments | |
parent | 9471c11b708e5f1c564ef4b5da8cc8a0a5df0c67 (diff) |
WIP with andres, not working pattern language
Diffstat (limited to 'src/Experiments')
-rw-r--r-- | src/Experiments/PartialEvaluationWithLetIn.v | 354 |
1 files changed, 280 insertions, 74 deletions
diff --git a/src/Experiments/PartialEvaluationWithLetIn.v b/src/Experiments/PartialEvaluationWithLetIn.v index 7b854af21..5bcfb2d27 100644 --- a/src/Experiments/PartialEvaluationWithLetIn.v +++ b/src/Experiments/PartialEvaluationWithLetIn.v @@ -1,3 +1,4 @@ +Require Import Coq.Lists.List. Require Import Crypto.Util.Option. Require Import Crypto.Util.Notations. @@ -41,13 +42,82 @@ Bind Scope etype_scope with type.type. Infix "->" := type.arrow : etype_scope. Module base. Module type. - Inductive type := nat | prod (A B : type). + Inductive type := nat | prod (A B : type) | list (A : type). End type. Notation type := type.type. End base. Bind Scope etype_scope with base.type. Infix "*" := base.type.prod : etype_scope. +Fixpoint upperboundT (t : base.type) : Type + := match t with + | base.type.nat => option nat + | base.type.prod A B => upperboundT A * upperboundT B + | base.type.list A => option (list (upperboundT A)) + end. + +Module expr. + Section with_var. + Context {base_type : Type}. + Local Notation type := (type base_type). + Context {ident : type -> Type} + {var : type -> Type}. + + Inductive expr : type -> Type := + | Ident {t} (idc : ident t) : expr t + | Var {t} (v : var t) : expr t + | Abs {s d} (f : var s -> expr d) : expr (s -> d) + | App {s d} (f : expr (s -> d)) (x : expr s) : expr d + | LetIn {A B} (x : expr A) (f : var A -> expr B) : expr B + . + End with_var. + + Module Export Notations. + Delimit Scope expr_scope with expr. + Bind Scope expr_scope with expr. + Infix "@" := App : expr_scope. + Reserved Notation "\ x .. y , t" (at level 200, x binder, y binder, right associativity, format "\ x .. y , '//' t"). + Notation "\ x .. y , f" := (Abs (fun x => .. (Abs (fun y => f%expr)) .. )) : expr_scope. + Notation "'λ' x .. y , f" := (Abs (fun x => .. (Abs (fun y => f%expr)) .. )) : expr_scope. + Notation "'expr_let' x := A 'in' b" := (LetIn A (fun x => b%expr)) : expr_scope. + Notation "'$' x" := (Var x) (at level 9, format "'$' x") : expr_scope. + Notation "### x" := (Ident x) (at level 9, x at level 10, format "### x") : expr_scope. + End Notations. +End expr. +Import expr.Notations. +Notation expr := expr.expr. + +Module UnderLets. + Section with_var. + Context {base_type : Type}. + Local Notation type := (type base_type). + Context {ident : type -> Type} + {var : type -> Type}. + Local Notation expr := (@expr base_type ident var). + + Inductive UnderLets {T : Type} := + | Base (v : T) + | UnderLet {A} (x : expr A) (f : var A -> UnderLets). + + Fixpoint splice {A B} (x : @UnderLets A) (e : A -> @UnderLets B) : @UnderLets B + := match x with + | Base v => e v + | UnderLet A x f => UnderLet x (fun v => @splice _ _ (f v) e) + end. + + Fixpoint to_expr {t} (x : @UnderLets (expr t)) : expr t + := match x with + | Base v => v + | UnderLet A x f + => expr.LetIn x (fun v => @to_expr _ (f v)) + end. + End with_var. + Global Arguments UnderLets : clear implicits. +End UnderLets. +Delimit Scope under_lets_scope with under_lets. +Bind Scope under_lets_scope with UnderLets.UnderLets. +Notation "x <-- y ; f" := (UnderLets.splice y (fun x => f%under_lets)) : under_lets_scope. + Module parametric. Local Notation einterp := type.interp. Module type. @@ -79,14 +149,16 @@ Module parametric. Local Notation btype := base.type.type. Local Notation bnat := base.type.nat. Local Notation bprod := base.type.prod. + Local Notation blist := base.type.list. Module base. Module type. - Inductive type := nat | prod (A B : type) | var_with_subst (subst : btype). + Inductive type := nat | prod (A B : type) | list (A : type) | var_with_subst (subst : btype). Fixpoint subst (t : type) : btype := match t with | nat => bnat | prod A B => bprod (subst A) (subst B) + | list A => blist (subst A) | var_with_subst s => s end. @@ -97,6 +169,7 @@ Module parametric. := match t with | nat => Datatypes.nat | prod A B => interp A * interp B + | list A => Datatypes.list (interp A) | var_with_subst s => base_interp s end%type. End interp. @@ -117,43 +190,6 @@ Bind Scope ptype_scope with parametric.base.type. Infix "*" := parametric.base.type.prod : ptype_scope. Notation "# x" := (parametric.base.type.var_with_subst x) (at level 9, x at level 10, format "# x") : ptype_scope. -Fixpoint upperboundT (t : base.type) : Type - := match t with - | base.type.nat => option nat - | base.type.prod A B => upperboundT A * upperboundT B - end. - -Module expr. - Section with_var. - Context {base_type : Type}. - Local Notation type := (type base_type). - Context {ident : type -> Type} - {var : type -> Type}. - - Inductive expr : type -> Type := - | Ident {t} (idc : ident t) : expr t - | Var {t} (v : var t) : expr t - | Abs {s d} (f : var s -> expr d) : expr (s -> d) - | App {s d} (f : expr (s -> d)) (x : expr s) : expr d - | LetIn {A B} (x : expr A) (f : var A -> expr B) : expr B - . - End with_var. - - Module Export Notations. - Delimit Scope expr_scope with expr. - Bind Scope expr_scope with expr. - Infix "@" := App : expr_scope. - Reserved Notation "\ x .. y , t" (at level 200, x binder, y binder, right associativity, format "\ x .. y , '//' t"). - Notation "\ x .. y , f" := (Abs (fun x => .. (Abs (fun y => f%expr)) .. )) : expr_scope. - Notation "'λ' x .. y , f" := (Abs (fun x => .. (Abs (fun y => f%expr)) .. )) : expr_scope. - Notation "'expr_let' x := A 'in' b" := (LetIn A (fun x => b%expr)) : expr_scope. - Notation "'$' x" := (Var x) (at level 9, format "'$' x") : expr_scope. - Notation "### x" := (Ident x) (at level 9, x at level 10, format "### x") : expr_scope. - End Notations. -End expr. -Import expr.Notations. -Notation expr := expr.expr. - Module ident. Local Notation type := (type base.type). Section with_base. @@ -168,6 +204,12 @@ Module ident. | Pair {A B : base.type} : pident (#A -> #B -> #A * #B)%ptype | Fst {A B} : pident (#A * #B -> #A)%ptype | Snd {A B} : pident (#A * #B -> #B)%ptype + | Nil {A} : pident (parametric.base.type.list #A)%ptype + | Cons {A} : pident (#A -> parametric.base.type.list #A -> parametric.base.type.list #A)%ptype + | List_map {A B} : pident ((#A -> #B) -> parametric.base.type.list #A -> parametric.base.type.list #B)%ptype + | List_app {A} : pident (parametric.base.type.list #A -> parametric.base.type.list #A -> parametric.base.type.list #A)%ptype + | List_flat_map {A B} : pident ((#A -> parametric.base.type.list #B) -> parametric.base.type.list #A -> parametric.base.type.list #B)%ptype + | List_rect {A P} : pident (#P -> (#A -> parametric.base.type.list #A -> #P -> #P) -> parametric.base.type.list #A -> #P)%ptype | Cast {T} (upper_bound : upperboundT T) : pident (#T -> #T)%ptype . @@ -189,6 +231,12 @@ Module ident. Notation "# x" := (expr.Ident (wrap x)) (at level 9, x at level 10, format "# x") : expr_scope. Notation "( x , y , .. , z )" := (expr.App (expr.App (#Pair) .. (expr.App (expr.App (#Pair) x%expr) y%expr) .. ) z%expr) : expr_scope. Notation "x + y" := (#Plus @ x @ y)%expr : expr_scope. + (*Notation "x :: y" := (#Cons @ x @ y)%expr : expr_scope.*) + (* Unification fails if we don't fill in [wident pident] explicitly *) + Notation "x :: y" := (@expr.App base.type.type (wident pident) _ _ _ (#Cons @ x) y)%expr : expr_scope. + Notation "[ ]" := (#Nil)%expr : expr_scope. + Notation "[ x ]" := (#Cons @ x @ (#Nil))%expr : expr_scope. + Notation "[ x ; y ; .. ; z ]" := (@expr.App base.type.type (wident pident) _ _ _ (#Cons @ x) (#Cons @ y @ .. (#Cons @ z @ #Nil) ..))%expr : expr_scope. End Notations. End ident. Import ident.Notations. @@ -196,37 +244,6 @@ Notation ident := ident.ident. Notation pident := ident.pident. Notation wident := ident.wident. -Module UnderLets. - Section with_var. - Context {base_type : Type}. - Local Notation type := (type base_type). - Context {ident : type -> Type} - {var : type -> Type}. - Local Notation expr := (@expr base_type ident var). - - Inductive UnderLets {T : Type} := - | Base (v : T) - | UnderLet {A} (x : expr A) (f : var A -> UnderLets). - - Fixpoint splice {A B} (x : @UnderLets A) (e : A -> @UnderLets B) : @UnderLets B - := match x with - | Base v => e v - | UnderLet A x f => UnderLet x (fun v => @splice _ _ (f v) e) - end. - - Fixpoint to_expr {t} (x : @UnderLets (expr t)) : expr t - := match x with - | Base v => v - | UnderLet A x f - => expr.LetIn x (fun v => @to_expr _ (f v)) - end. - End with_var. - Global Arguments UnderLets : clear implicits. -End UnderLets. -Delimit Scope under_lets_scope with under_lets. -Bind Scope under_lets_scope with UnderLets.UnderLets. -Notation "x <-- y ; f" := (UnderLets.splice y (fun x => f%under_lets)) : under_lets_scope. - Module partial. Import UnderLets. Section with_var. @@ -351,6 +368,10 @@ Module partial. Context {var : type -> Type} (pident : ptype -> Type). Local Notation ident := (wident pident). + Context (ident_transport : forall t (P : ident t -> Type) (idc idc' : ident t), + P idc -> option (P idc')). + Definition type_transport (P : type -> Type) t t' : P t -> option (P t'). + Admitted. Local Notation expr := (@expr base.type ident). Local Notation UnderLets := (@UnderLets base.type ident var). Context (abstract_domain' : base.type -> Type). @@ -372,8 +393,118 @@ Module partial. barrier in both directions a decent amount *) (ident_Literal : nat -> pident parametric.base.type.nat) (ident_Pair : forall A B, pident (#A -> #B -> #A * #B)%ptype) + (ident_Nil : forall A, pident (parametric.base.type.list #A)%ptype) + (ident_Cons : forall A, pident (#A -> parametric.base.type.list #A -> parametric.base.type.list #A)%ptype) (ident_Fst : forall A B, pident (#A * #B -> #A)%ptype) - (ident_Snd : forall A B, pident (#A * #B -> #B)%ptype). + (ident_Snd : forall A B, pident (#A * #B -> #B)%ptype) + (hd_tl_list_state : forall A, abstract_domain' (base.type.list A) -> abstract_domain' A * abstract_domain' (base.type.list A)). + + + + Inductive base_value : type -> Type := + | Ident {t} (idc : ident t) : base_value t + | App {s d} (f : base_value (s -> d)) (x : base_value s) : base_value d + | Abs {s d} (f : @expr var (s -> d)) : base_value (s -> d). + + (*(intersect_state : forall A, abstract_domain' A -> abstract_domain' A -> abstract_domain' A)*) + + + Local Notation value := (@value base.type ident var base_value abstract_domain'). + + Definition abstraction_function : forall t : base.type, base_value t -> abstract_domain' t + := fun _ _ => bottom' _. + + Fixpoint base_reify {t} (e : base_value t) : @expr var t + := match e in base_value t return expr t with + | Ident t idc => ###idc + | App s d f x => @base_reify _ f @ (@base_reify _ x) + | Abs s d f => f + end%expr. + + Local Notation reflect := (@reflect base.type ident var base_value abstract_domain' annotate bottom' (@abstraction_function) (@base_reify)). + Local Notation bottom := (@bottom base.type abstract_domain' bottom'). + + Fixpoint base_reflect {t} : base_value t -> value t + := match t return base_value t -> value t with + | type.base t => @inr _ _ + | type.arrow s d => fun v => reflect (base_reify v) bottom + end. + + Inductive pattern : type -> Type := + | PIdent {t} (idc : ident t) : pattern t + | PApp {s d} (f : pattern (s -> d)) (x : pattern s) : pattern d + | PVar {t} : pattern t. + + Fixpoint pattern_bound {t} (p : pattern t) : Type + := match p with + | PIdent t idc => unit + | PApp s d f x => @pattern_bound _ f * @pattern_bound _ x + | PVar t => value t + end. + + Fixpoint pattern_matches {t} (p : pattern t) (v : base_value t) : option (pattern_bound p). + refine match p, v return option (pattern_bound p) with + | PIdent t idc, Ident t' idc' + => (idc'' <- type_transport ident _ _ idc'; + ident_transport _ (fun _ => unit) idc idc'' tt) + | PApp s d f x, App s' d' f' x' + => (f'' <- type_transport base_value _ _ f'; + x'' <- type_transport base_value _ _ x'; + sb <- @pattern_matches _ f f''; + db <- @pattern_matches _ x x''; + Some (sb, db)) + | PVar t, e + => (e' <- type_transport base_value _ t e; + _) + | PIdent _ _, _ => None + | PApp _ _ _ _, _ => None + end%option. + refine match p in pattern t return base_value t -> option (pattern_bound p) with + | PIdent t idc + => fun v + => match v in base_value t return ident t -> option unit with + | Ident t idc' + => fun idc => ident_transport _ (fun _ => unit) idc idc' tt + | App _ _ _ _ + | Abs _ _ _ + => fun _ => None + end idc + | PApp s d f x + => fun v + => let v' := match v in base_value d return option (base_value with + | Ident t idc => _ + | App s d f x => _ + | Abs s d f => _ + end + (* + let f' := fun v' => @pattern_matches _ f v' in + let x' := fun v' => @pattern_matches _ x v' in + _*) + | PVar t => _ + end. + cbn. + + Focus 3. + cbn. + + Context (do_rewrite_rules + Context (half_interp : forall {t} (idc : pident t), parametric.half_interp UnderLets value t). + + + + + + + Definition interp_ident : forall t, ident t -> value t. + := match idc in ident.wident _ t return value t with + | ident.wrap T idc' as idc + => pinterp + (Base (reflect (###idc) (abstract_interp_ident _ idc')))%expr + (half_interp _ idc') + end. + + + (base_reify : forall t, base_value t -> @expr var t). Fixpoint base_value (t : base.type) := match t return Type with @@ -381,6 +512,8 @@ Module partial. => nat | base.type.prod A B as t => (abstract_domain' A * @expr var A + base_value A) * (abstract_domain' B * @expr var B + base_value B) + | base.type.list A as t + => list (abstract_domain' A * @expr var A + base_value A) (* cons cells *) * option (abstract_domain' (base.type.list A) * @expr var (base.type.list A)) end%type. Fixpoint abstraction_function {t} : base_value t -> abstract_domain' t @@ -399,6 +532,22 @@ Module partial. end in abstract_interp_ident _ (ident_Pair A B) sta stb + | base.type.list A + => fun '(cells, rest) + => let st_cells := List.map + (fun a => match a with + | inl (st, _) => st + | inr a' => @abstraction_function A a' + end) + cells in + let st_rest := match rest with + | None => abstract_interp_ident _ (ident_Nil A) + | Some (st, _) => st + end in + List.fold_right + (abstract_interp_ident _ (ident_Cons A)) + st_rest + st_cells end. Fixpoint base_reify {t} : base_value t -> @expr var t @@ -424,12 +573,38 @@ Module partial. | inr v => @base_reify _ v end in (#(ident_Pair A B) @ ea @ eb)%expr + | base.type.list A + => fun '(cons_cells, rest) + => let cells' := List.map + (fun a => match a with + | inl (st, e) + => match annotate _ st with + | None => e + | Some cst => ###cst @ e + end%expr + | inr v => @base_reify _ v + end) + cons_cells in + let rest' := match rest with + | Some (st, e) + => match annotate _ st with + | None => e + | Some cst => ###cst @ e + end%expr + | None => (#(ident_Nil A))%expr + end in + List.fold_right + (fun x xs => (#(ident_Cons A) @ x @ xs)%expr) + rest' + cells' end. Local Notation value := (@value base.type ident var base_value abstract_domain'). Context (half_interp : forall {t} (idc : pident t), parametric.half_interp UnderLets value t). + Print List.fold_left. + Fixpoint intersect_state_base_value {t} : abstract_domain' t -> base_value t -> base_value t := match t return abstract_domain' t -> base_value t -> base_value t with | base.type.nat => update_literal_with_state @@ -446,6 +621,25 @@ Module partial. | inr v => inr (@intersect_state_base_value _ stb v) end in (a', b') + | base.type.list _ + => fun st '(cons_cells, rest) + => let '(cells', st_rest) + := List.fold_left + (fun '(rest_cells, st) cell + => let '(st0, st') := hd_tl_list_state _ st in + (match cell with + | inl (st0', e) => inl (intersect_state _ st0 st0', e) + | inr v => inr (@intersect_state_base_value _ st0 v) + end :: rest_cells, + st')) + cons_cells + (nil, st) in + (cells', + match rest with + | None => None + | Some (st_rest', e) + => Some (intersect_state _ st_rest st_rest', e) + end) end. @@ -470,12 +664,14 @@ Module partial. => fun v => inr v | parametric.base.type.prod A B => fun '(a, b) => inr (@pinterp_base A a, @pinterp_base B b) + | parametric.base.type.list A + => fun ls => inr (List.map (@pinterp_base A) ls, None) | parametric.base.type.var_with_subst subst => fun v => v end. - Fixpoint puninterp_base {t : parametric.base.type} : value (parametric.subst (type.base t)) -> option (parametric.half_interp UnderLets value (type.base t)) - := match t return value (parametric.subst (type.base t)) -> option (parametric.half_interp UnderLets value (type.base t)) with + Fixpoint puninterp_base {t : parametric.base.type} : value (parametric.subst (type.base t)) -> option (parametric.half_interp UnderLets value (type.base t)). + refine match t return value (parametric.subst (type.base t)) -> option (parametric.half_interp UnderLets value (type.base t)) with | parametric.base.type.nat => fun v => match v with @@ -491,9 +687,19 @@ Module partial. b' <- @puninterp_base B b; Some (a', b')) end + | parametric.base.type.list A + => fun ls + => match ls with + | inl _ => None + | inr (cons_cells, rest) + => _ + end | parametric.base.type.var_with_subst subst => @Some _ - end%option. + end%option. + fold parametric.base.type.subst in *. + fold base_value in *. + cbn in *. (* FIXME: naming; these are basically just fancy identity functions *) Fixpoint vinterp_arrow {t : type} : value t -> @type.interpM base.type UnderLets value t |