diff options
Diffstat (limited to 'src/Experiments/PartialEvaluationWithLetIn.v')
-rw-r--r-- | src/Experiments/PartialEvaluationWithLetIn.v | 876 |
1 files changed, 0 insertions, 876 deletions
diff --git a/src/Experiments/PartialEvaluationWithLetIn.v b/src/Experiments/PartialEvaluationWithLetIn.v deleted file mode 100644 index 82a34c528..000000000 --- a/src/Experiments/PartialEvaluationWithLetIn.v +++ /dev/null @@ -1,876 +0,0 @@ -Require Import Coq.Lists.List. -Require Import Crypto.Util.Option. -Require Import Crypto.Util.Notations. - -(** Notes: - -1. pattern out identifiers and types. - - type := arrow (_:type) (_:type) | type_base (_:base_type) -- the latter is a parameter - - literal is an identifier - - expr cases: var, abs, app, letin, ident -- ident is a parameter -2. add prenex polymorphism for identifiers (type variables) - - - - ident is indexed by typecodes, perhaps cases: arrow | base | typevar -*) - -Module type. - Inductive type {base_type : Type} := base (t : base_type) | arrow (s d : type). - Global Arguments type : clear implicits. - - Fixpoint for_each_lhs_of_arrow {base_type} (f : type base_type -> Type) (t : type base_type) : Type - := match t with - | base t => unit - | arrow s d => f s * @for_each_lhs_of_arrow _ f d - end. - - Fixpoint interp {base_type} (base_interp : base_type -> Type) (t : type base_type) : Type - := match t with - | base t => base_interp t - | arrow s d => @interp _ base_interp s -> @interp _ base_interp d - end. - - Fixpoint interpM {base_type} (M : Type -> Type) (base_interp : base_type -> Type) (t : type base_type) : Type - := match t with - | base t => base_interp t - | arrow s d => @interpM _ M base_interp s -> M (@interpM _ M base_interp d) - end. -End type. -Notation type := type.type. -Delimit Scope etype_scope with etype. -Bind Scope etype_scope with type.type. -Infix "->" := type.arrow : etype_scope. -Module base. - Module 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. - -Module parametric. - Local Notation einterp := type.interp. - Module type. - Section subst. - Context {base_type_with_var base_type} - (base_subst : base_type_with_var -> base_type) - (base_interp : base_type_with_var -> Type) - (base_subst_interp : base_type -> Type) - (M : Type -> Type) - (ret : forall T, T -> M T). - - Fixpoint subst (t : type base_type_with_var) : type base_type - := match t with - | type.base t => type.base (base_subst t) - | type.arrow s d => type.arrow (subst s) (subst d) - end. - - (* half_interp *) - Fixpoint interp (t : type base_type_with_var) : Type - := match t with - | type.base t => base_interp t - | type.arrow s d - => match s with - | type.arrow s' d' => type.interpM M base_subst_interp (subst s) - | type.base t => base_interp t - end -> interp d - end. - - Fixpoint interpM_final (t : type base_type_with_var) : Type - := match t with - | type.base t => M (base_interp t) - | type.arrow s d - => match s with - | type.arrow s' d' => type.interpM M base_subst_interp (subst s) - | type.base t => base_interp t - end -> interpM_final d - end. - - Fixpoint interpM_final_of_interp {t} : interp t -> interpM_final t - := match t with - | type.base t => ret _ - | type.arrow s d - => fun f x => @interpM_final_of_interp d (f x) - end. - End subst. - End type. - 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) | 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. - - Section interp. - Context (base_interp : btype -> Type). - - Fixpoint interp (t : type) : Type - := 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. - End type. - Notation type := type.type. - End base. - - Definition subst (t : type base.type) : type btype - := type.subst base.type.subst t. - - Definition half_interp (M : Type -> Type) (half_interp : base.type.type -> Type) (interp : btype -> Type) (t : type base.type) : Type - := type.interp base.type.subst half_interp interp M t. - Definition half_interp2 (M : Type -> Type) (half_interp : base.type.type -> Type) (interp : btype -> Type) (t : type base.type) : Type - := type.interpM_final base.type.subst half_interp interp M t. - Definition half_interp2_of_interp {M half_interpf interp t} ret - : half_interp M half_interpf interp t -> half_interp2 M half_interpf interp t - := type.interpM_final_of_interp _ _ _ _ ret. -End parametric. -Notation ptype := (type.type parametric.base.type). -Delimit Scope ptype_scope with ptype. -Notation "s -> d" := (type.arrow s%ptype d%ptype) : ptype_scope. -Bind Scope ptype_scope with parametric.base.type. -Infix "*" := parametric.base.type.prod : ptype_scope. -Notation "# x" := (parametric.base.type.var_with_subst 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 - | 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. - 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 10, format "'$' x") : expr_scope. - Notation "### x" := (Ident 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. - Let type_base (x : base.type) : type := type.base x. - Local Coercion type_base : base.type >-> type. - Let ptype_base (x : parametric.base.type) : ptype := type.base x. - Local Coercion ptype_base : parametric.base.type >-> ptype. - - Inductive pident : ptype -> Type := - | Literal (v : nat) : pident parametric.base.type.nat - | Plus : pident (parametric.base.type.nat -> parametric.base.type.nat -> parametric.base.type.nat) - | 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 -> #(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 - . - - Inductive wident {pident : ptype -> Type} : type -> Type := - | wrap {T} (idc : pident T) : wident (parametric.subst T). - Global Arguments wident : clear implicits. - Definition ident := wident pident. - Definition pwrap {T} (idc : pident T) : ident _ := @wrap pident T idc. - End with_base. - Global Arguments wrap {pident T} idc. - Global Coercion pwrap : pident >-> ident. - - Module Export Notations. - Delimit Scope ident_scope with ident. - Bind Scope ident_scope with ident. - Bind Scope ident_scope with pident. - Global Arguments expr.Ident {base_type%type ident%function var%function t%etype} idc%ident. - Notation "## x" := (Literal x) : ident_scope. - Notation "## x" := (expr.Ident (wrap (Literal x))) : expr_scope. - Notation "# x" := (expr.Ident (wrap 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. -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 splice_list {A B} (ls : list (@UnderLets A)) (e : list A -> @UnderLets B) : @UnderLets B - := match ls with - | nil => e nil - | cons x xs - => splice x (fun x => @splice_list A B xs (fun xs => e (cons x xs))) - 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. -Notation "x <--- y ; f" := (UnderLets.splice_list y (fun x => f%under_lets)) : under_lets_scope. - -Module partial. - Import UnderLets. - Section with_var. - Context {base_type : Type}. - Local Notation type := (type base_type). - Let type_base (x : base_type) : type := type.base x. - Local Coercion type_base : base_type >-> type. - Context {ident : type -> Type} - {var : type -> Type}. - Local Notation expr := (@expr base_type ident). - Local Notation UnderLets := (@UnderLets base_type ident var). - Context (base_value : base_type -> Type) - (abstract_domain' : base_type -> Type) - (annotate : forall t, abstract_domain' t -> option (ident (t -> t))) - (intersect_state : forall A, abstract_domain' A -> abstract_domain' A -> abstract_domain' A) - (bottom' : forall A, abstract_domain' A) - (abstraction_function : forall t, base_value t -> abstract_domain' t) - (base_reify : forall t, base_value t -> @expr var t). - - Definition value (t : type) - := type.interpM - UnderLets - (fun t => abstract_domain' t * @expr var t + base_value t)%type - t. - Definition value_with_lets (t : type) - := UnderLets (value t). - - Context (interp_ident : forall t, ident t -> value_with_lets t). - - Definition abstract_domain (t : type) - := type.interp abstract_domain' t. - - Fixpoint bottom {t} : abstract_domain t - := match t with - | type.base t => bottom' t - | type.arrow s d => fun _ => @bottom d - end. - - Fixpoint bottom_for_each_lhs_of_arrow {t} : type.for_each_lhs_of_arrow abstract_domain t - := match t return type.for_each_lhs_of_arrow abstract_domain t with - | type.base t => tt - | type.arrow s d => (bottom, @bottom_for_each_lhs_of_arrow d) - end. - - Fixpoint state_of_value {t} : value t -> abstract_domain t - := match t return value t -> abstract_domain t with - | type.base t - => fun v - => match v with - | inl (st, _) => st - | inr n => abstraction_function _ n - end - | type.arrow s d => fun _ => bottom - end. - - Fixpoint reify {t} : value t -> type.for_each_lhs_of_arrow abstract_domain t -> @expr var t - := match t return value t -> type.for_each_lhs_of_arrow abstract_domain t -> @expr var t with - | type.base t - => fun v 'tt - => match v with - | inl (st, e) - => match annotate _ st with - | None => e - | Some cst => ###cst @ e - end%expr - | inr v => base_reify _ v - end - | type.arrow s d - => fun f '(sv, dv) - => λ x , (UnderLets.to_expr - (fx <-- f (@reflect _ (expr.Var x) sv); - Base (@reify _ fx dv))) - end%core%expr - with reflect {t} : @expr var t -> abstract_domain t -> value t - := match t return @expr var t -> abstract_domain t -> value t with - | type.base t - => fun e st => inl (st, e) - | type.arrow s d - => fun e absf v - => let stv := state_of_value v in - Base (@reflect d (e @ (@reify s v bottom_for_each_lhs_of_arrow)) (absf stv))%expr - end. - - Fixpoint interp {t} (e : @expr value_with_lets t) : value_with_lets t - := match e in expr.expr t return value_with_lets t with - | expr.Ident t idc => interp_ident t idc - | expr.Var t v => v - | expr.Abs s d f => Base (fun x => @interp d (f (Base x))) - | expr.App s d f x - => (x' <-- @interp s x; - f' <-- @interp (s -> d)%etype f; - f' x') - | expr.LetIn (type.arrow _ _) B x f - => (x' <-- @interp _ x; - @interp _ (f (Base x'))) - | expr.LetIn (type.base A) B x f - => (x' <-- @interp _ x; - UnderLet - (reify x' tt) - (fun x'v - => @interp _ (f (Base (reflect (expr.Var x'v) (state_of_value x')))))) - end%under_lets. - - Definition eval_with_bound {t} (e : @expr value_with_lets t) - (st : type.for_each_lhs_of_arrow abstract_domain t) - : expr t - := UnderLets.to_expr (e' <-- interp e; Base (reify e' st)). - - Definition eval {t} (e : @expr value_with_lets t) : expr t - := eval_with_bound e bottom_for_each_lhs_of_arrow. - End with_var. - - Module wident. - Section with_var. - Local Notation type := (type base.type). - Let type_base (x : base.type) : type := type.base x. - Local Coercion type_base : base.type >-> type. - Let type_pbase (x : parametric.base.type) : ptype := type.base x. - Local Coercion type_pbase : parametric.base.type >-> type. - Context {var : type -> Type} - (pident : ptype -> Type). - Local Notation ident := (wident pident). - Local Notation expr := (@expr base.type ident). - Local Notation UnderLets := (@UnderLets base.type ident var). - Context (abstract_domain' : base.type -> Type). - Local Notation abstract_domain := (@abstract_domain base.type abstract_domain'). - Context (annotate : forall t, abstract_domain' t -> option (ident (t -> t))) - (abstract_interp_ident : forall t, pident t -> type.interp abstract_domain' (parametric.subst t)) - (intersect_state : forall A, abstract_domain' A -> abstract_domain' A -> abstract_domain' A) - (update_literal_with_state : abstract_domain' base.type.nat -> nat -> nat) - (state_of_upperbound : forall T, upperboundT T -> abstract_domain' T) - (bottom' : forall A, abstract_domain' A) - (** we need constructors for reify and destructors for - intersect_state, which is needed to talk about how to do - cast on values; there's a leaky abstraction barrier - here: we assume that we can take apart the abstract - state via type structure and then put it back together - again, in order to cast values. But we don't require - that the abstract state is actually a pair on product - types, so we pay the cost of crossing that abstraction - 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_List_app : forall A, pident (parametric.base.type.list #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) - (hd_tl_list_state : forall A, abstract_domain' (base.type.list A) -> abstract_domain' A * abstract_domain' (base.type.list A)). - - Local Notation expr_with_abs A - := (prod (abstract_domain' A) (@expr var A)). - Local Notation expr_or base_value A - := (sum (expr_with_abs A) (base_value A%etype)). - Fixpoint base_value (t : base.type) - := match t return Type with - | base.type.nat as t - => nat - | base.type.prod A B as t - => (expr_or base_value A) * (expr_or base_value B) - | base.type.list A as t - => list (expr_or base_value A) (* cons cells *) - end%type. - Local Notation value := (@value base.type ident var base_value abstract_domain'). - Local Notation value_with_lets := (@value_with_lets base.type ident var base_value abstract_domain'). - Fixpoint pbase_value (t : parametric.base.type) - := match t return Type with - | parametric.base.type.nat as t - => nat - | parametric.base.type.prod A B as t - => pbase_value A * pbase_value B - | parametric.base.type.list A as t - => list (pbase_value A) - | parametric.base.type.var_with_subst A as t - => value A - end%type. - - Fixpoint abstraction_function {t} : base_value t -> abstract_domain' t - := match t return base_value t -> abstract_domain' t with - | base.type.nat - => fun v => abstract_interp_ident _ (ident_Literal v) - | base.type.prod A B - => fun '(a, b) - => let sta := match a with - | inl (st, _) => st - | inr a' => @abstraction_function A a' - end in - let stb := match b with - | inl (st, _) => st - | inr b' => @abstraction_function B b' - end in - abstract_interp_ident - _ (ident_Pair A B) sta stb - | base.type.list A - => fun cells - => let st_cells - := List.map - (fun a => match a with - | inl (st, _) => st - | inr a' => @abstraction_function A a' - end) - cells in - List.fold_right - (abstract_interp_ident _ (ident_Cons A)) - (abstract_interp_ident _ (ident_Nil A)) - st_cells - end. - - Fixpoint base_reify {t} : base_value t -> @expr var t - := match t return base_value t -> expr t with - | base.type.nat - => fun v => expr.Ident (ident.wrap (ident_Literal v)) - | base.type.prod A B - => fun '(a, b) - => let ea := match a with - | inl (st, e) - => match annotate _ st with - | None => e - | Some cst => ###cst @ e - end%expr - | inr v => @base_reify _ v - end in - let eb := match b with - | inl (st, e) - => match annotate _ st with - | None => e - | Some cst => ###cst @ e - end%expr - | inr v => @base_reify _ v - end in - (#(ident_Pair A B) @ ea @ eb)%expr - | base.type.list A - => fun cells - => 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) - cells in - List.fold_right - (fun x xs => (#(ident_Cons A) @ x @ xs)%expr) - (#(ident_Nil A))%expr - cells' - end. - - Context (half_interp : forall {t} (idc : pident t), - parametric.half_interp UnderLets pbase_value value t - + parametric.half_interp2 UnderLets pbase_value value t). - - 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 - | base.type.prod _ _ - => fun st '(a, b) - => let sta := abstract_interp_ident _ (ident_Fst _ _) st in - let stb := abstract_interp_ident _ (ident_Snd _ _) st in - let a' := match a with - | inl (sta', e) => inl (intersect_state _ sta sta', e) - | inr v => inr (@intersect_state_base_value _ sta v) - end in - let b' := match b with - | inl (stb', e) => inl (intersect_state _ stb stb', e) - | inr v => inr (@intersect_state_base_value _ stb v) - end in - (a', b') - | base.type.list _ - => fun st cells - => let '(cells', st) - := 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')) - cells - (nil, st) in - cells' - end. - - - Definition intersect_state_value {t} : abstract_domain t -> value t -> value t - := match t with - | type.base t - => fun st e - => match e with - | inl (st', e) => inl (intersect_state _ st st', e) - | inr v => inr (intersect_state_base_value st v) - end - | type.arrow s d => fun _ e => e - end. - - Local Notation reify := (@reify base.type ident var base_value abstract_domain' annotate bottom' (@abstraction_function) (@base_reify)). - Local Notation reflect := (@reflect base.type ident var base_value abstract_domain' annotate bottom' (@abstraction_function) (@base_reify)). - - Fixpoint pinterp_base {t : parametric.base.type} : parametric.half_interp UnderLets pbase_value value (type.base t) -> value (parametric.subst (type.base t)) - := match t return parametric.half_interp UnderLets pbase_value value (type.base t) -> value (parametric.subst (type.base t)) with - | parametric.base.type.nat - => 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) - | 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 pbase_value value (type.base t)) - := match t return value (parametric.subst (type.base t)) -> option (parametric.half_interp UnderLets pbase_value value (type.base t)) with - | parametric.base.type.nat - => fun v - => match v with - | inl _ => None - | inr v' => Some v' - end - | parametric.base.type.prod A B - => fun ab - => match ab with - | inl _ => None - | inr (a, b) - => (a' <- @puninterp_base A a; - b' <- @puninterp_base B b; - Some (a', b')) - end - | parametric.base.type.list A - => fun ls - => match ls with - | inl rest => None - | inr ls - => List.fold_right - (fun x xs - => (x' <- x; xs' <- xs; Some (x' :: xs'))%option) - (Some nil) - (List.map (@puninterp_base A) ls) - end - | parametric.base.type.var_with_subst subst - => @Some _ - end%option. - - Fixpoint pinterp {t} : UnderLets (value (parametric.subst t)) -> parametric.half_interp2 UnderLets pbase_value value t -> value_with_lets (parametric.subst t) - := match t return UnderLets (value (parametric.subst t)) -> parametric.half_interp2 UnderLets pbase_value value t -> value_with_lets (parametric.subst t) with - | type.base t - => fun default partial => (partial' <-- partial; - Base (pinterp_base partial')) - | type.arrow (type.base s) d - => fun fdefault fpartial - => Base - (fun (v : value (parametric.subst (type.base s))) - => let default := (fdefault' <-- fdefault; fdefault' v) in - match puninterp_base v return UnderLets (value (parametric.subst d)) with - | Some v' => @pinterp d default (fpartial v') - | None => default - end) - | type.arrow s d - => fun fdefault fpartial - => Base - (fun (v : value (parametric.subst s)) - => @pinterp - d (fdefault' <-- fdefault; fdefault' v) - (fpartial v)) - end%under_lets. - - Local Notation bottom := (@bottom base.type abstract_domain' bottom'). - - Definition interp {t} (idc : ident t) : value_with_lets t - := match idc in ident.wident _ t return value_with_lets t with - | ident.wrap T idc' as idc - => pinterp - (Base (reflect (###idc) (abstract_interp_ident _ idc')))%expr - match half_interp _ idc' with - | inl interp_idc => parametric.half_interp2_of_interp (fun T => @Base _ ident var T) interp_idc - | inr interp2_idc => interp2_idc - end - end. - - Definition eval_with_bound {t} (e : @expr value_with_lets t) - (st : type.for_each_lhs_of_arrow abstract_domain t) - : expr t - := @eval_with_bound base.type ident var base_value abstract_domain' annotate bottom' (@abstraction_function) (@base_reify) (@interp) t e st. - - Definition eval {t} (e : @expr value_with_lets t) : @expr var t - := @eval base.type ident var base_value abstract_domain' annotate bottom' (@abstraction_function) (@base_reify) (@interp) t e. - End with_var. - End wident. - - Module ident. - Section with_var. - Local Notation type := (type base.type). - Let type_base (x : base.type) : type := type.base x. - Local Coercion type_base : base.type >-> type. - Context {var : type -> Type}. - Local Notation expr := (@expr base.type ident). - Local Notation UnderLets := (@UnderLets base.type ident var). - Context (abstract_domain' : base.type -> Type). - Local Notation abstract_domain := (@abstract_domain base.type abstract_domain'). - Context (annotate : forall t, abstract_domain' t -> option (ident (t -> t))) - (abstract_interp_ident : forall t, pident t -> type.interp abstract_domain' (parametric.subst t)) - (intersect_state : forall A, abstract_domain' A -> abstract_domain' A -> abstract_domain' A) - (update_literal_with_state : abstract_domain' base.type.nat -> nat -> nat) - (state_of_upperbound : forall T, upperboundT T -> abstract_domain' T) - (bottom' : forall A, abstract_domain' A) - (hd_tl_list_state : forall A, abstract_domain' (base.type.list A) -> abstract_domain' A * abstract_domain' (base.type.list A)). - - Local Notation base_value := (@wident.base_value var pident abstract_domain'). - Local Notation pbase_value := (@wident.pbase_value var pident abstract_domain'). - Local Notation value := (@value base.type ident var base_value abstract_domain'). - Local Notation intersect_state_value := (@wident.intersect_state_value var pident abstract_domain' abstract_interp_ident intersect_state update_literal_with_state (@ident.Fst) (@ident.Snd) (@hd_tl_list_state)). - Local Notation abstraction_function := (@wident.abstraction_function var pident abstract_domain' abstract_interp_ident (@ident.Literal) (@ident.Pair) (@ident.Nil) (@ident.Cons)). - Local Notation base_reify := (@wident.base_reify var pident abstract_domain' annotate (@ident.Literal) (@ident.Pair) (@ident.Nil) (@ident.Cons)). - Local Notation reify := (@reify base.type ident var base_value abstract_domain' annotate bottom' (@abstraction_function) (@base_reify)). - Local Notation state_of_value := (@state_of_value base.type ident var base_value abstract_domain' bottom' (@abstraction_function)). - - Definition half_interp {t} (idc : pident t) - : parametric.half_interp UnderLets pbase_value value t - + parametric.half_interp2 UnderLets pbase_value value t - := match idc in ident.pident t return parametric.half_interp UnderLets pbase_value value t + parametric.half_interp2 UnderLets pbase_value value t with - | ident.Literal v => inl v - | ident.Plus => inl Nat.add - | ident.Pair A B => inl (@pair _ _) - | ident.Fst A B => inl (@fst _ _) - | ident.Snd A B => inl (@snd _ _) - | ident.Nil _ => inl (@nil _) - | ident.Cons _ => inl (@cons _) - | ident.List_app _ => inl (@List.app _) - | ident.List_map _ _ - => inr (fun f ls => fls <--- List.map f ls; Base fls) - | ident.List_flat_map A B - => inr (fun f ls - => fls <--- List.map f ls; - Base - (List.fold_right - (fun ls1 ls2 : value (base.type.list B) - => match ls1, ls2 with - | inr ls1, inr ls2 => inr (ls1 ++ ls2) - | _, _ - => let rls1 := reify ls1 tt in - let rls2 := reify ls2 tt in - let st1 := state_of_value ls1 in - let st2 := state_of_value ls2 in - inl (abstract_interp_ident _ (ident.List_app) st1 st2, - (#ident.List_app @ rls1 @ rls2)%expr) - end) - (inr nil) - fls)) - | ident.List_rect A P - => inr - (fun N_case C_case ls - => list_rect - _ - (Base N_case) - (fun x xs rest - => (rest' <-- rest; - C_case <-- C_case x; - C_case <-- C_case (inr xs); - C_case rest')) - ls) - | ident.Cast T upper_bound as idc - => inl (intersect_state_value (t:=T) (state_of_upperbound _ upper_bound)) - end%under_lets. - - Local Notation value_with_lets := (@value_with_lets base.type ident var base_value abstract_domain'). - - Definition eval_with_bound {t} (e : @expr value_with_lets t) - (st : type.for_each_lhs_of_arrow abstract_domain t) - : expr t - := @wident.eval_with_bound var pident abstract_domain' annotate abstract_interp_ident bottom' (@ident.Literal) (@ident.Pair) (@ident.Nil) (@ident.Cons) (@half_interp) t e st. - - Definition eval {t} (e : @expr value_with_lets t) : @expr var t - := @wident.eval var pident abstract_domain' annotate abstract_interp_ident bottom' (@ident.Literal) (@ident.Pair) (@ident.Nil) (@ident.Cons) (@half_interp) t e. - End with_var. - End ident. -End partial. - -Section specialized. - Local Notation abstract_domain' := upperboundT. - Local Notation abstract_domain := (@partial.abstract_domain base.type abstract_domain'). - Notation expr := (@expr base.type ident). - Local Notation type := (type base.type). - Let type_base (x : base.type) : type := type.base x. - Local Coercion type_base : base.type >-> type. - Definition annotate t (st : abstract_domain' t) : option (ident (t -> t)) - := Some (ident.wrap (ident.Cast st)). - Fixpoint bottom' T : abstract_domain' T - := match T return abstract_domain' T with - | base.type.nat => None - | base.type.prod A B => (bottom' _, bottom' _) - | base.type.list _ => None - end. - Fixpoint intersect_state A : abstract_domain' A -> abstract_domain' A -> abstract_domain' A - := match A return abstract_domain' A -> abstract_domain' A -> abstract_domain' A with - | base.type.nat - => fun x y - => match x, y with - | Some x', Some y' => Some (Nat.min x' y') - | Some x', None | None, Some x' => Some x' - | None, None => None - end - | base.type.prod A B - => fun '(x, y) '(x', y') => (@intersect_state _ x x', @intersect_state _ y y') - | base.type.list A - => fun ls1 ls2 - => match ls1, ls2 with - | None, v => v - | v, None => v - | Some ls1, Some ls2 - => Some (List.map (fun '(x, x') => @intersect_state A x x') - (List.combine ls1 ls2)) - end - end. - Axiom evil : nat -> nat. - Definition update_literal_with_state : abstract_domain' base.type.nat -> nat -> nat - := fun upperbound n - => match upperbound with - | Some upperbound' - => if Nat.leb n upperbound' then n else evil n - | None => n - end. - Definition state_of_upperbound : forall T, upperboundT T -> abstract_domain' T - := fun _ x => x. - Definition abstract_interp_ident t (idc : pident t) : type.interp abstract_domain' (parametric.subst t) - := match idc in ident.pident t return type.interp abstract_domain' (parametric.subst t) with - | ident.Literal v => Some v - | ident.Plus - => fun x y - => match x, y with - | Some x', Some y' => Some (x' + y') - | _, _ => None - end - | ident.Pair A B => @pair _ _ - | ident.Fst A B => @fst _ _ - | ident.Snd A B => @snd _ _ - | ident.Nil A => Some nil - | ident.Cons A - => fun x xs => (xs' <- xs; Some (cons x xs')) - | ident.List_map A B - => fun f ls => option_map (List.map f) ls - | ident.List_app A - => fun ls1 ls2 => (ls1' <- ls1; ls2' <- ls2; Some (ls1' ++ ls2')) - | ident.List_flat_map A B - => fun f ls - => (ls' <- ls; - List.fold_right - (fun ls1 ls2 => (ls1' <- ls1; ls2' <- ls2; Some (ls1' ++ ls2'))) - (Some nil) - (List.map f ls')) - | ident.List_rect A P - => fun N C ls - => match ls with - | Some ls' - => list_rect - _ - N - (fun x xs rec => C x (Some xs) rec) - ls' - | None => bottom' _ - end - | ident.Cast T upper_bound - => intersect_state _ (state_of_upperbound _ upper_bound) - end%option. - - Definition hd_tl_list_state A (st : abstract_domain' (base.type.list A)) - : abstract_domain' A * abstract_domain' (base.type.list A) - := match st with - | None => (bottom' _, None) - | Some nil => (bottom' _, Some nil) - | Some (cons x xs) => (x, Some xs) - end. - - Definition eval {var} {t} (e : @expr _ t) : expr t - := (@partial.ident.eval) - var abstract_domain' annotate abstract_interp_ident intersect_state update_literal_with_state state_of_upperbound bottom' hd_tl_list_state t e. - Definition eval_with_bound {var} {t} (e : @expr _ t) (bound : type.for_each_lhs_of_arrow abstract_domain t) : expr t - := (@partial.ident.eval_with_bound) - var abstract_domain annotate abstract_interp_ident intersect_state update_literal_with_state state_of_upperbound bottom' hd_tl_list_state t e bound. - - Import expr. - Import ident. - - Eval compute in eval (#Fst @ (expr_let x := ##10 in ($x, $x)))%expr. - - Eval compute in eval ((\ x , expr_let y := ##5 in #Fst @ $x + (#Fst @ $x + ($y + $y))) - @ (##1, ##1))%expr. - - Eval compute in eval ((\ x , expr_let y := ##5 in $y + ($y + (#Fst @ $x + #Snd @ $x))) - @ (##1, ##7))%expr. - - - Eval cbv in eval_with_bound - (\z , ((\ x , expr_let y := ##5 in $y + ($z + (#Fst @ $x + #Snd @ $x))) - @ (##1, ##7)))%expr - (Some 100, tt). -End specialized. |