Mercurial > cpdt > repo
view src/Intensional.v @ 183:02569049397b
Closure conversion defined
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Sun, 16 Nov 2008 14:01:33 -0500 |
parents | 24b99e025fe8 |
children | 699fd70c04a7 |
line wrap: on
line source
(* Copyright (c) 2008, Adam Chlipala * * This work is licensed under a * Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 * Unported License. * The license text is available at: * http://creativecommons.org/licenses/by-nc-nd/3.0/ *) (* begin hide *) Require Import Arith Bool String List. Require Import Axioms Tactics DepList. Set Implicit Arguments. (* end hide *) (** %\chapter{Intensional Transformations}% *) (** TODO: Prose for this chapter *) (** * Closure Conversion *) Module Source. Inductive type : Type := | TNat : type | Arrow : type -> type -> type. Notation "'Nat'" := TNat : source_scope. Infix "-->" := Arrow (right associativity, at level 60) : source_scope. Open Scope source_scope. Bind Scope source_scope with type. Delimit Scope source_scope with source. Section vars. Variable var : type -> Type. Inductive exp : type -> Type := | Var : forall t, var t -> exp t | Const : nat -> exp Nat | Plus : exp Nat -> exp Nat -> exp Nat | App : forall t1 t2, exp (t1 --> t2) -> exp t1 -> exp t2 | Abs : forall t1 t2, (var t1 -> exp t2) -> exp (t1 --> t2). End vars. Definition Exp t := forall var, exp var t. Implicit Arguments Var [var t]. Implicit Arguments Const [var]. Implicit Arguments Plus [var]. Implicit Arguments App [var t1 t2]. Implicit Arguments Abs [var t1 t2]. Notation "# v" := (Var v) (at level 70) : source_scope. Notation "^ n" := (Const n) (at level 70) : source_scope. Infix "+^" := Plus (left associativity, at level 79) : source_scope. Infix "@" := App (left associativity, at level 77) : source_scope. Notation "\ x , e" := (Abs (fun x => e)) (at level 78) : source_scope. Notation "\ ! , e" := (Abs (fun _ => e)) (at level 78) : source_scope. Bind Scope source_scope with exp. Definition zero : Exp Nat := fun _ => ^0. Definition one : Exp Nat := fun _ => ^1. Definition zpo : Exp Nat := fun _ => zero _ +^ one _. Definition ident : Exp (Nat --> Nat) := fun _ => \x, #x. Definition app_ident : Exp Nat := fun _ => ident _ @ zpo _. Definition app : Exp ((Nat --> Nat) --> Nat --> Nat) := fun _ => \f, \x, #f @ #x. Definition app_ident' : Exp Nat := fun _ => app _ @ ident _ @ zpo _. Fixpoint typeDenote (t : type) : Set := match t with | Nat => nat | t1 --> t2 => typeDenote t1 -> typeDenote t2 end. Fixpoint expDenote t (e : exp typeDenote t) {struct e} : typeDenote t := match e in (exp _ t) return (typeDenote t) with | Var _ v => v | Const n => n | Plus e1 e2 => expDenote e1 + expDenote e2 | App _ _ e1 e2 => (expDenote e1) (expDenote e2) | Abs _ _ e' => fun x => expDenote (e' x) end. Definition ExpDenote t (e : Exp t) := expDenote (e _). Section exp_equiv. Variables var1 var2 : type -> Type. Inductive exp_equiv : list { t : type & var1 t * var2 t }%type -> forall t, exp var1 t -> exp var2 t -> Prop := | EqVar : forall G t (v1 : var1 t) v2, In (existT _ t (v1, v2)) G -> exp_equiv G (#v1) (#v2) | EqConst : forall G n, exp_equiv G (^n) (^n) | EqPlus : forall G x1 y1 x2 y2, exp_equiv G x1 x2 -> exp_equiv G y1 y2 -> exp_equiv G (x1 +^ y1) (x2 +^ y2) | EqApp : forall G t1 t2 (f1 : exp _ (t1 --> t2)) (x1 : exp _ t1) f2 x2, exp_equiv G f1 f2 -> exp_equiv G x1 x2 -> exp_equiv G (f1 @ x1) (f2 @ x2) | EqAbs : forall G t1 t2 (f1 : var1 t1 -> exp var1 t2) f2, (forall v1 v2, exp_equiv (existT _ t1 (v1, v2) :: G) (f1 v1) (f2 v2)) -> exp_equiv G (Abs f1) (Abs f2). End exp_equiv. Axiom Exp_equiv : forall t (E : Exp t) var1 var2, exp_equiv nil (E var1) (E var2). End Source. Module Closed. Inductive type : Type := | TNat : type | Arrow : type -> type -> type | Code : type -> type -> type -> type | Prod : type -> type -> type | TUnit : type. Notation "'Nat'" := TNat : cc_scope. Notation "'Unit'" := TUnit : cc_scope. Infix "-->" := Arrow (right associativity, at level 60) : cc_scope. Infix "**" := Prod (right associativity, at level 59) : cc_scope. Notation "env @@ dom ---> ran" := (Code env dom ran) (no associativity, at level 62, dom at next level) : cc_scope. Bind Scope cc_scope with type. Delimit Scope cc_scope with cc. Open Local Scope cc_scope. Section vars. Variable var : type -> Set. Inductive exp : type -> Type := | Var : forall t, var t -> exp t | Const : nat -> exp Nat | Plus : exp Nat -> exp Nat -> exp Nat | App : forall dom ran, exp (dom --> ran) -> exp dom -> exp ran | Pack : forall env dom ran, exp (env @@ dom ---> ran) -> exp env -> exp (dom --> ran) | EUnit : exp Unit | Pair : forall t1 t2, exp t1 -> exp t2 -> exp (t1 ** t2) | Fst : forall t1 t2, exp (t1 ** t2) -> exp t1 | Snd : forall t1 t2, exp (t1 ** t2) -> exp t2 | Let : forall t1 t2, exp t1 -> (var t1 -> exp t2) -> exp t2. Section funcs. Variable T : Type. Inductive funcs : Type := | Main : T -> funcs | Abs : forall env dom ran, (var env -> var dom -> exp ran) -> (var (env @@ dom ---> ran) -> funcs) -> funcs. End funcs. Definition prog t := funcs (exp t). End vars. Implicit Arguments Var [var t]. Implicit Arguments Const [var]. Implicit Arguments EUnit [var]. Implicit Arguments Fst [var t1 t2]. Implicit Arguments Snd [var t1 t2]. Implicit Arguments Main [var T]. Implicit Arguments Abs [var T env dom ran]. Notation "# v" := (Var v) (at level 70) : cc_scope. Notation "^ n" := (Const n) (at level 70) : cc_scope. Infix "+^" := Plus (left associativity, at level 79) : cc_scope. Infix "@" := App (left associativity, at level 77) : cc_scope. Infix "##" := Pack (no associativity, at level 71) : cc_scope. Notation "()" := EUnit : cc_scope. Notation "[ x1 , x2 ]" := (Pair x1 x2) (at level 73) : cc_scope. Notation "#1 x" := (Fst x) (at level 72) : cc_scope. Notation "#2 x" := (Snd x) (at level 72) : cc_scope. Notation "f <== \\ x , y , e ; fs" := (Abs (fun x y => e) (fun f => fs)) (right associativity, at level 80, e at next level) : cc_scope. Notation "x <- e1 ; e2" := (Let e1 (fun x => e2)) (right associativity, at level 80, e1 at next level) : cc_scope. Bind Scope cc_scope with exp funcs prog. Fixpoint typeDenote (t : type) : Set := match t with | Nat => nat | Unit => unit | dom --> ran => typeDenote dom -> typeDenote ran | t1 ** t2 => typeDenote t1 * typeDenote t2 | env @@ dom ---> ran => typeDenote env -> typeDenote dom -> typeDenote ran end%type. Fixpoint expDenote t (e : exp typeDenote t) {struct e} : typeDenote t := match e in (exp _ t) return (typeDenote t) with | Var _ v => v | Const n => n | Plus e1 e2 => expDenote e1 + expDenote e2 | App _ _ f x => (expDenote f) (expDenote x) | Pack _ _ _ f env => (expDenote f) (expDenote env) | EUnit => tt | Pair _ _ e1 e2 => (expDenote e1, expDenote e2) | Fst _ _ e' => fst (expDenote e') | Snd _ _ e' => snd (expDenote e') | Let _ _ e1 e2 => expDenote (e2 (expDenote e1)) end. Fixpoint funcsDenote T (fs : funcs typeDenote T) : T := match fs with | Main v => v | Abs _ _ _ e fs => funcsDenote (fs (fun env arg => expDenote (e env arg))) end. Definition progDenote t (p : prog typeDenote t) : typeDenote t := expDenote (funcsDenote p). Definition Exp t := forall var, exp var t. Definition Prog t := forall var, prog var t. Definition ExpDenote t (E : Exp t) := expDenote (E _). Definition ProgDenote t (P : Prog t) := progDenote (P _). End Closed. Import Source Closed. Section splice. Open Local Scope cc_scope. Fixpoint spliceFuncs var T1 (fs : funcs var T1) T2 (f : T1 -> funcs var T2) {struct fs} : funcs var T2 := match fs with | Main v => f v | Abs _ _ _ e fs' => Abs e (fun x => spliceFuncs (fs' x) f) end. End splice. Notation "x <-- e1 ; e2" := (spliceFuncs e1 (fun x => e2)) (right associativity, at level 80, e1 at next level) : cc_scope. Definition natvar (_ : Source.type) := nat. Definition isfree := hlist (fun (_ : Source.type) => bool). Ltac maybe_destruct E := match goal with | [ x : _ |- _ ] => match E with | x => idtac end | _ => match E with | eq_nat_dec _ _ => idtac end end; destruct E. Ltac my_crush := crush; repeat (match goal with | [ x : (_ * _)%type |- _ ] => destruct x | [ |- context[if ?B then _ else _] ] => maybe_destruct B | [ _ : context[if ?B then _ else _] |- _ ] => maybe_destruct B end; crush). Section isfree. Import Source. Open Local Scope source_scope. Hint Extern 3 False => omega. Fixpoint lookup_type (envT : list Source.type) (n : nat) {struct envT} : isfree envT -> option Source.type := match envT return (isfree envT -> _) with | nil => fun _ => None | first :: rest => fun fvs => if eq_nat_dec n (length rest) then match fvs with | (true, _) => Some first | (false, _) => None end else lookup_type rest n (snd fvs) end. Implicit Arguments lookup_type [envT]. Notation ok := (fun (envT : list Source.type) (fvs : isfree envT) (n : nat) (t : Source.type) => lookup_type n fvs = Some t). Fixpoint wfExp (envT : list Source.type) (fvs : isfree envT) t (e : Source.exp natvar t) {struct e} : Prop := match e with | Var t v => ok envT fvs v t | Const _ => True | Plus e1 e2 => wfExp envT fvs e1 /\ wfExp envT fvs e2 | App _ _ e1 e2 => wfExp envT fvs e1 /\ wfExp envT fvs e2 | Abs dom _ e' => wfExp (dom :: envT) (true ::: fvs) (e' (length envT)) end. Implicit Arguments wfExp [envT t]. Theorem wfExp_weaken : forall t (e : exp natvar t) envT (fvs fvs' : isfree envT), wfExp fvs e -> (forall n t, ok _ fvs n t -> ok _ fvs' n t) -> wfExp fvs' e. Hint Extern 1 (lookup_type (envT := _ :: _) _ _ = Some _) => simpl in *; my_crush. induction e; my_crush; eauto. Defined. Fixpoint isfree_none (envT : list Source.type) : isfree envT := match envT return (isfree envT) with | nil => tt | _ :: _ => (false, isfree_none _) end. Implicit Arguments isfree_none [envT]. Fixpoint isfree_one (envT : list Source.type) (n : nat) {struct envT} : isfree envT := match envT return (isfree envT) with | nil => tt | _ :: rest => if eq_nat_dec n (length rest) then (true, isfree_none) else (false, isfree_one _ n) end. Implicit Arguments isfree_one [envT]. Fixpoint isfree_merge (envT : list Source.type) : isfree envT -> isfree envT -> isfree envT := match envT return (isfree envT -> isfree envT -> isfree envT) with | nil => fun _ _ => tt | _ :: _ => fun fv1 fv2 => (fst fv1 || fst fv2, isfree_merge _ (snd fv1) (snd fv2)) end. Implicit Arguments isfree_merge [envT]. Fixpoint fvsExp t (e : exp natvar t) (envT : list Source.type) {struct e} : isfree envT := match e with | Var _ n => isfree_one n | Const _ => isfree_none | Plus e1 e2 => isfree_merge (fvsExp e1 envT) (fvsExp e2 envT) | App _ _ e1 e2 => isfree_merge (fvsExp e1 envT) (fvsExp e2 envT) | Abs dom _ e' => snd (fvsExp (e' (length envT)) (dom :: envT)) end. Lemma isfree_one_correct : forall t (v : natvar t) envT fvs, ok envT fvs v t -> ok envT (isfree_one (envT:=envT) v) v t. induction envT; my_crush; eauto. Defined. Lemma isfree_merge_correct1 : forall t (v : natvar t) envT fvs1 fvs2, ok envT fvs1 v t -> ok envT (isfree_merge (envT:=envT) fvs1 fvs2) v t. induction envT; my_crush; eauto. Defined. Hint Rewrite orb_true_r : cpdt. Lemma isfree_merge_correct2 : forall t (v : natvar t) envT fvs1 fvs2, ok envT fvs2 v t -> ok envT (isfree_merge (envT:=envT) fvs1 fvs2) v t. induction envT; my_crush; eauto. Defined. Hint Resolve isfree_one_correct isfree_merge_correct1 isfree_merge_correct2. Lemma fvsExp_correct : forall t (e : exp natvar t) envT (fvs : isfree envT), wfExp fvs e -> forall (fvs' : isfree envT), (forall v t, ok envT (fvsExp e envT) v t -> ok envT fvs' v t) -> wfExp fvs' e. Hint Extern 1 (_ = _) => match goal with | [ H : lookup_type _ (fvsExp ?X ?Y) = _ |- _ ] => destruct (fvsExp X Y); my_crush end. induction e; my_crush; eauto. Defined. Lemma lookup_type_unique : forall v t1 t2 envT (fvs1 fvs2 : isfree envT), lookup_type v fvs1 = Some t1 -> lookup_type v fvs2 = Some t2 -> t1 = t2. induction envT; my_crush; eauto. Defined. Implicit Arguments lookup_type_unique [v t1 t2 envT fvs1 fvs2]. Hint Extern 2 (lookup_type _ _ = Some _) => match goal with | [ H1 : lookup_type ?v _ = Some _, H2 : lookup_type ?v _ = Some _ |- _ ] => (generalize (lookup_type_unique H1 H2); intro; subst) || rewrite <- (lookup_type_unique H1 H2) end. Lemma lookup_none : forall v t envT, lookup_type (envT:=envT) v (isfree_none (envT:=envT)) = Some t -> False. induction envT; my_crush. Defined. Hint Extern 2 (_ = _) => elimtype False; eapply lookup_none; eassumption. Lemma lookup_one : forall v' v t envT, lookup_type (envT:=envT) v' (isfree_one (envT:=envT) v) = Some t -> v' = v. induction envT; my_crush. Defined. Implicit Arguments lookup_one [v' v t envT]. Hint Extern 2 (lookup_type _ _ = Some _) => match goal with | [ H : lookup_type _ _ = Some _ |- _ ] => generalize (lookup_one H); intro; subst end. Lemma lookup_merge : forall v t envT (fvs1 fvs2 : isfree envT), lookup_type v (isfree_merge fvs1 fvs2) = Some t -> lookup_type v fvs1 = Some t \/ lookup_type v fvs2 = Some t. induction envT; my_crush. Defined. Implicit Arguments lookup_merge [v t envT fvs1 fvs2]. Lemma lookup_bound : forall v t envT (fvs : isfree envT), lookup_type v fvs = Some t -> v < length envT. Hint Resolve lt_S. induction envT; my_crush; eauto. Defined. Hint Resolve lookup_bound. Lemma lookup_bound_contra : forall t envT (fvs : isfree envT), lookup_type (length envT) fvs = Some t -> False. intros; assert (length envT < length envT); eauto. Defined. Hint Resolve lookup_bound_contra. Hint Extern 3 (_ = _) => elimtype False; omega. Lemma lookup_push_drop : forall v t t' envT fvs, v < length envT -> lookup_type (envT := t :: envT) v (true, fvs) = Some t' -> lookup_type (envT := envT) v fvs = Some t'. my_crush. Defined. Lemma lookup_push_add : forall v t t' envT fvs, lookup_type (envT := envT) v (snd fvs) = Some t' -> lookup_type (envT := t :: envT) v fvs = Some t'. my_crush; elimtype False; eauto. Defined. Hint Resolve lookup_bound lookup_push_drop lookup_push_add. Theorem fvsExp_minimal : forall t (e : exp natvar t) envT (fvs : isfree envT), wfExp fvs e -> (forall v t, ok envT (fvsExp e envT) v t -> ok envT fvs v t). Hint Extern 1 (_ = _) => match goal with | [ H : lookup_type _ (isfree_merge _ _) = Some _ |- _ ] => destruct (lookup_merge H); clear H; eauto end. induction e; my_crush; eauto. Defined. Fixpoint ccType (t : Source.type) : Closed.type := match t with | Nat%source => Nat | (dom --> ran)%source => ccType dom --> ccType ran end%cc. Open Local Scope cc_scope. Fixpoint envType (envT : list Source.type) : isfree envT -> Closed.type := match envT return (isfree envT -> _) with | nil => fun _ => Unit | t :: _ => fun tup => if fst tup then ccType t ** envType _ (snd tup) else envType _ (snd tup) end. Implicit Arguments envType [envT]. Fixpoint envOf (var : Closed.type -> Set) (envT : list Source.type) {struct envT} : isfree envT -> Set := match envT return (isfree envT -> _) with | nil => fun _ => unit | first :: rest => fun fvs => match fvs with | (true, fvs') => (var (ccType first) * envOf var rest fvs')%type | (false, fvs') => envOf var rest fvs' end end. Implicit Arguments envOf [envT]. Notation "var <| to" := (match to with | None => unit | Some t => var (ccType t) end) (no associativity, at level 70). Fixpoint lookup (var : Closed.type -> Set) (envT : list Source.type) : forall (n : nat) (fvs : isfree envT), envOf var fvs -> var <| lookup_type n fvs := match envT return (forall (n : nat) (fvs : isfree envT), envOf var fvs -> var <| lookup_type n fvs) with | nil => fun _ _ _ => tt | first :: rest => fun n fvs => match (eq_nat_dec n (length rest)) as Heq return (envOf var (envT := first :: rest) fvs -> var <| (if Heq then match fvs with | (true, _) => Some first | (false, _) => None end else lookup_type n (snd fvs))) with | left _ => match fvs return (envOf var (envT := first :: rest) fvs -> var <| (match fvs with | (true, _) => Some first | (false, _) => None end)) with | (true, _) => fun env => fst env | (false, _) => fun _ => tt end | right _ => match fvs return (envOf var (envT := first :: rest) fvs -> var <| (lookup_type n (snd fvs))) with | (true, fvs') => fun env => lookup var rest n fvs' (snd env) | (false, fvs') => fun env => lookup var rest n fvs' env end end end. Theorem lok : forall var n t envT (fvs : isfree envT), lookup_type n fvs = Some t -> var <| lookup_type n fvs = var (ccType t). crush. Defined. End isfree. Implicit Arguments lookup_type [envT]. Implicit Arguments lookup [envT fvs]. Implicit Arguments wfExp [t envT]. Implicit Arguments envType [envT]. Implicit Arguments envOf [envT]. Implicit Arguments lok [var n t envT fvs]. Section lookup_hints. Hint Resolve lookup_bound_contra. (*Ltac my_chooser T k := match T with | ptype => match goal with | [ H : lookup _ _ = Some ?t |- _ ] => k t end | _ => default_chooser T k end. Ltac my_matching := matching equation my_chooser.*) Hint Resolve lookup_bound_contra. Lemma lookup_type_push : forall t' envT (fvs1 fvs2 : isfree envT) b1 b2, (forall (n : nat) (t : Source.type), lookup_type (envT := t' :: envT) n (b1, fvs1) = Some t -> lookup_type (envT := t' :: envT) n (b2, fvs2) = Some t) -> (forall (n : nat) (t : Source.type), lookup_type n fvs1 = Some t -> lookup_type n fvs2 = Some t). intros until b2; intro H; intros n t; generalize (H n t); my_crush; elimtype False; eauto. Defined. Lemma lookup_type_push_contra : forall t' envT (fvs1 fvs2 : isfree envT), (forall (n : nat) (t : Source.type), lookup_type (envT := t' :: envT) n (true, fvs1) = Some t -> lookup_type (envT := t' :: envT) n (false, fvs2) = Some t) -> False. intros until fvs2; intro H; generalize (H (length envT) t'); my_crush. Defined. End lookup_hints. Section packing. Open Local Scope cc_scope. Hint Resolve lookup_type_push lookup_type_push_contra. Definition packExp (var : Closed.type -> Set) (envT : list Source.type) (fvs1 fvs2 : isfree envT) : (forall n t, lookup_type n fvs1 = Some t -> lookup_type n fvs2 = Some t) -> envOf var fvs2 -> exp var (envType fvs1). refine (fix packExp (var : Closed.type -> Set) (envT : list Source.type) {struct envT} : forall fvs1 fvs2 : isfree envT, (forall n t, lookup_type n fvs1 = Some t -> lookup_type n fvs2 = Some t) -> envOf var fvs2 -> exp var (envType fvs1) := match envT return (forall fvs1 fvs2 : isfree envT, (forall n t, lookup_type n fvs1 = Some t -> lookup_type n fvs2 = Some t) -> envOf var fvs2 -> exp var (envType fvs1)) with | nil => fun _ _ _ _ => () | first :: rest => fun fvs1 => match fvs1 return (forall fvs2 : isfree (first :: rest), (forall n t, lookup_type (envT := first :: rest) n fvs1 = Some t -> lookup_type n fvs2 = Some t) -> envOf var fvs2 -> exp var (envType (envT := first :: rest) fvs1)) with | (false, fvs1') => fun fvs2 => match fvs2 return ((forall n t, lookup_type (envT := first :: rest) n (false, fvs1') = Some t -> lookup_type (envT := first :: rest) n fvs2 = Some t) -> envOf (envT := first :: rest) var fvs2 -> exp var (envType (envT := first :: rest) (false, fvs1'))) with | (false, fvs2') => fun Hmin env => packExp var _ fvs1' fvs2' _ env | (true, fvs2') => fun Hmin env => packExp var _ fvs1' fvs2' _ (snd env) end | (true, fvs1') => fun fvs2 => match fvs2 return ((forall n t, lookup_type (envT := first :: rest) n (true, fvs1') = Some t -> lookup_type (envT := first :: rest) n fvs2 = Some t) -> envOf (envT := first :: rest) var fvs2 -> exp var (envType (envT := first :: rest) (true, fvs1'))) with | (false, fvs2') => fun Hmin env => False_rect _ _ | (true, fvs2') => fun Hmin env => [#(fst env), packExp var _ fvs1' fvs2' _ (snd env)] end end end); eauto. Defined. Hint Resolve fvsExp_correct fvsExp_minimal. Hint Resolve lookup_push_drop lookup_bound lookup_push_add. Implicit Arguments packExp [var envT]. Fixpoint unpackExp (var : Closed.type -> Set) t (envT : list Source.type) {struct envT} : forall fvs : isfree envT, exp var (envType fvs) -> (envOf var fvs -> exp var t) -> exp var t := match envT return (forall fvs : isfree envT, exp var (envType fvs) -> (envOf var fvs -> exp var t) -> exp var t) with | nil => fun _ _ f => f tt | first :: rest => fun fvs => match fvs return (exp var (envType (envT := first :: rest) fvs) -> (envOf var (envT := first :: rest) fvs -> exp var t) -> exp var t) with | (false, fvs') => fun p f => unpackExp rest fvs' p f | (true, fvs') => fun p f => x <- #1 p; unpackExp rest fvs' (#2 p) (fun env => f (x, env)) end end. Implicit Arguments unpackExp [var t envT fvs]. Theorem wfExp_lax : forall t t' envT (fvs : isfree envT) (e : Source.exp natvar t), wfExp (envT := t' :: envT) (true, fvs) e -> wfExp (envT := t' :: envT) (true, snd (fvsExp e (t' :: envT))) e. Hint Extern 1 (_ = _) => match goal with | [ H : lookup_type _ (fvsExp ?X ?Y) = _ |- _ ] => destruct (fvsExp X Y); my_crush end. eauto. Defined. Implicit Arguments wfExp_lax [t t' envT fvs e]. Lemma inclusion : forall t t' envT fvs (e : Source.exp natvar t), wfExp (envT := t' :: envT) (true, fvs) e -> (forall n t, lookup_type n (snd (fvsExp e (t' :: envT))) = Some t -> lookup_type n fvs = Some t). eauto. Defined. Implicit Arguments inclusion [t t' envT fvs e]. Definition env_prog var t envT (fvs : isfree envT) := funcs var (envOf var fvs -> Closed.exp var t). Implicit Arguments env_prog [envT]. Axiom cheat : forall T, T. Import Source. Open Local Scope cc_scope. Fixpoint ccExp var t (e : Source.exp natvar t) (envT : list Source.type) (fvs : isfree envT) {struct e} : wfExp fvs e -> env_prog var (ccType t) fvs := match e in (Source.exp _ t) return (wfExp fvs e -> env_prog var (ccType t) fvs) with | Const n => fun _ => Main (fun _ => ^n) | Plus e1 e2 => fun wf => n1 <-- ccExp var e1 _ fvs (proj1 wf); n2 <-- ccExp var e2 _ fvs (proj2 wf); Main (fun env => n1 env +^ n2 env) | Var _ n => fun wf => Main (fun env => #(match lok wf in _ = T return T with | refl_equal => lookup var n env end)) | App _ _ f x => fun wf => f' <-- ccExp var f _ fvs (proj1 wf); x' <-- ccExp var x _ fvs (proj2 wf); Main (fun env => f' env @ x' env) | Abs dom _ b => fun wf => b' <-- ccExp var (b (length envT)) (dom :: envT) _ (wfExp_lax wf); f <== \\env, arg, unpackExp (#env) (fun env => b' (arg, env)); Main (fun env => #f ## packExp (snd (fvsExp (b (length envT)) (dom :: envT))) fvs (inclusion wf) env) end. End packing. Implicit Arguments packExp [var envT]. Implicit Arguments unpackExp [var t envT fvs]. Implicit Arguments ccExp [var t envT]. Fixpoint map_funcs var result T1 T2 (f : T1 -> T2) (fs : cfuncs var result T1) {struct fs} : cfuncs var result T2 := match fs with | CMain v => CMain (f v) | CAbs _ _ e fs' => CAbs e (fun x => map_funcs f (fs' x)) end. Definition CcTerm' result (E : Pterm result) (Hwf : wfTerm (envT := nil) tt (E _)) : Cprog result := fun _ => map_funcs (fun f => f tt) (ccTerm (E _) (envT := nil) tt Hwf). (** * Correctness *) Scheme pterm_equiv_mut := Minimality for pterm_equiv Sort Prop with pprimop_equiv_mut := Minimality for pprimop_equiv Sort Prop. Section splicePrim_correct. Variables result t t' : ptype. Variable ps' : ctypeDenote ([< t >]) -> cprimops ctypeDenote t'. Theorem splicePrim_correct : forall (ps : cprimops ctypeDenote t), cprimopsDenote (splicePrim ps ps') = cprimopsDenote (ps' (cprimopsDenote ps)). induction ps; equation. Qed. End splicePrim_correct. Section spliceTerm_correct. Variables result t : ptype. Variable e : ctypeDenote ([< t >]) -> cterm ctypeDenote result. Variable k : ptypeDenote result -> bool. Theorem spliceTerm_correct : forall (ps : cprimops ctypeDenote t), ctermDenote (spliceTerm ps e) k = ctermDenote (e (cprimopsDenote ps)) k. induction ps; equation. Qed. End spliceTerm_correct. Section spliceFuncs'_correct. Variable result : ptype. Variables T1 T2 : Type. Variable f : T1 -> T2. Variable k : ptypeDenote result -> bool. Theorem spliceFuncs'_correct : forall fs, cfuncsDenote (spliceFuncs' fs f) k = f (cfuncsDenote fs k). induction fs; equation. Qed. End spliceFuncs'_correct. Section spliceFuncs_correct. Variable result : ptype. Variables T1 T2 T3 : Type. Variable fs2 : cfuncs ctypeDenote result T2. Variable f : T1 -> T2 -> T3. Variable k : ptypeDenote result -> bool. Hint Rewrite spliceFuncs'_correct : ltamer. Theorem spliceFuncs_correct : forall fs1, cfuncsDenote (spliceFuncs fs1 fs2 f) k = f (cfuncsDenote fs1 k) (cfuncsDenote fs2 k). induction fs1; equation. Qed. End spliceFuncs_correct. Section inside_correct. Variable result : ptype. Variables T1 T2 : Type. Variable fs2 : T1 -> cfuncs ctypeDenote result T2. Variable k : ptypeDenote result -> bool. Theorem inside_correct : forall fs1, cfuncsDenote (inside fs1 fs2) k = cfuncsDenote (fs2 (cfuncsDenote fs1 k)) k. induction fs1; equation. Qed. End inside_correct. Notation "var <| to" := (match to with | None => unit | Some t => var ([< t >])%cc end) (no associativity, at level 70). Section packing_correct. Variable result : ptype. Hint Rewrite splicePrim_correct spliceTerm_correct : ltamer. Ltac my_matching := matching my_equation default_chooser. Fixpoint makeEnv (envT : list ptype) : forall (fvs : isfree envT), ptypeDenote (envType fvs) -> envOf ctypeDenote fvs := match envT return (forall (fvs : isfree envT), ptypeDenote (envType fvs) -> envOf ctypeDenote fvs) with | nil => fun _ _ => tt | first :: rest => fun fvs => match fvs return (ptypeDenote (envType (envT := first :: rest) fvs) -> envOf (envT := first :: rest) ctypeDenote fvs) with | (false, fvs') => fun env => makeEnv rest fvs' env | (true, fvs') => fun env => (fst env, makeEnv rest fvs' (snd env)) end end. Theorem unpackExp_correct : forall (envT : list ptype) (fvs : isfree envT) (ps : cprimops ctypeDenote (envType fvs)) (e : envOf ctypeDenote fvs -> cterm ctypeDenote result) k, ctermDenote (unpackExp ps e) k = ctermDenote (e (makeEnv _ _ (cprimopsDenote ps))) k. induction envT; my_matching. Qed. Lemma lookup_type_more : forall v2 envT (fvs : isfree envT) t b v, (v2 = length envT -> False) -> lookup_type v2 (envT := t :: envT) (b, fvs) = v -> lookup_type v2 fvs = v. equation. Qed. Lemma lookup_type_less : forall v2 t envT (fvs : isfree (t :: envT)) v, (v2 = length envT -> False) -> lookup_type v2 (snd fvs) = v -> lookup_type v2 (envT := t :: envT) fvs = v. equation. Qed. Lemma lookup_bound_contra_eq : forall t envT (fvs : isfree envT) v, lookup_type v fvs = Some t -> v = length envT -> False. simpler; eapply lookup_bound_contra; eauto. Defined. Lemma lookup_type_inner : forall result t envT v t' (fvs : isfree envT) e, wfTerm (envT := t :: envT) (true, fvs) e -> lookup_type v (snd (fvsTerm (result := result) e (t :: envT))) = Some t' -> lookup_type v fvs = Some t'. Hint Resolve lookup_bound_contra_eq fvsTerm_minimal lookup_type_more lookup_type_less. Hint Extern 2 (Some _ = Some _) => contradictory. eauto 6. Qed. Lemma cast_irrel : forall T1 T2 x (H1 H2 : T1 = T2), (x :? H1) = (x :? H2). equation. Qed. Hint Immediate cast_irrel. Lemma cast_irrel_unit : forall T1 T2 x y (H1 : T1 = T2) (H2 : unit = T2), (x :? H1) = (y :? H2). intros; generalize H1; rewrite <- H2 in H1; equation. Qed. Hint Immediate cast_irrel_unit. Hint Extern 3 (_ = _) => match goal with | [ |- context[False_rect _ ?H] ] => apply False_rect; exact H end. Theorem packExp_correct : forall v2 t envT (fvs1 fvs2 : isfree envT) Heq1 (Heq2 : ctypeDenote <| lookup_type v2 fvs2 = ptypeDenote t) Hincl env, (lookup ctypeDenote v2 env :? Heq2) = (lookup ctypeDenote v2 (makeEnv envT fvs1 (cprimopsDenote (packExp fvs1 fvs2 Hincl env))) :? Heq1). induction envT; my_equation. Qed. End packing_correct. Lemma look : forall envT n (fvs : isfree envT) t, lookup_type n fvs = Some t -> ctypeDenote <| lookup_type n fvs = ptypeDenote t. equation. Qed. Implicit Arguments look [envT n fvs t]. Theorem ccTerm_correct : forall result G (e1 : pterm ptypeDenote result) (e2 : pterm natvar result), pterm_equiv G e1 e2 -> forall (envT : list ptype) (fvs : isfree envT) (env : envOf ctypeDenote fvs) (Hwf : wfTerm fvs e2) k, (forall t (v1 : ptypeDenote t) (v2 : natvar t), In (vars (x := t) (v1, v2)) G -> v2 < length envT) -> (forall t (v1 : ptypeDenote t) (v2 : natvar t), In (vars (x := t) (v1, v2)) G -> lookup_type v2 fvs = Some t -> forall Heq, (lookup ctypeDenote v2 env :? Heq) = v1) -> ptermDenote e1 k = ctermDenote (cfuncsDenote (ccTerm e2 fvs Hwf) k env) k. Hint Rewrite splicePrim_correct spliceTerm_correct spliceFuncs_correct inside_correct : ltamer. Hint Rewrite unpackExp_correct : ltamer. Hint Resolve packExp_correct lookup_type_inner. Hint Extern 1 (_ = _) => push_vars. Hint Extern 1 (_ = _) => match goal with | [ Hvars : forall t v1 v2, _, Hin : In _ _ |- _ ] => rewrite (Hvars _ _ _ Hin) end. Hint Extern 1 (wfPrimop _ _) => tauto. Hint Extern 1 (_ < _) => match goal with | [ Hvars : forall t v1 v2, _, Hin : In _ _ |- _ ] => exact (Hvars _ _ _ Hin) end. Hint Extern 1 (lookup_type _ _ = _) => tauto. Hint Extern 1 (_ = _) => match goal with | [ Hvars : forall t v1 v2, _, Hin : In (vars (_, length ?envT)) _ |- _ ] => contradictory; assert (length envT < length envT); [auto | omega] end. Hint Extern 5 (_ = _) => symmetry. Hint Extern 1 (_ = _) => match goal with | [ H : lookup_type ?v _ = Some ?t, fvs : isfree _ |- (lookup _ _ _ :? _) = _ ] => let Hty := fresh "Hty" in (assert (Hty : lookup_type v fvs = Some t); [eauto | eapply (trans_cast (look Hty))]) end. Hint Extern 3 (ptermDenote _ _ = ctermDenote _ _) => match goal with | [ H : _ |- ptermDenote (_ ?v1) _ = ctermDenote (cfuncsDenote (ccTerm (_ ?v2) (envT := ?envT) ?fvs _) _ _) _ ] => apply (H v1 v2 envT fvs); my_simpler end. intro. apply (pterm_equiv_mut (fun G (e1 : pterm ptypeDenote result) (e2 : pterm natvar result) => forall (envT : list ptype) (fvs : isfree envT) (env : envOf ctypeDenote fvs) (Hwf : wfTerm fvs e2) k, (forall t (v1 : ptypeDenote t) (v2 : natvar t), In (vars (x := t) (v1, v2)) G -> v2 < length envT) -> (forall t (v1 : ptypeDenote t) (v2 : natvar t), In (vars (x := t) (v1, v2)) G -> lookup_type v2 fvs = Some t -> forall Heq, (lookup ctypeDenote v2 env :? Heq) = v1) -> ptermDenote e1 k = ctermDenote (cfuncsDenote (ccTerm e2 fvs Hwf) k env) k) (fun G t (p1 : pprimop ptypeDenote result t) (p2 : pprimop natvar result t) => forall (envT : list ptype) (fvs : isfree envT) (env : envOf ctypeDenote fvs) (Hwf : wfPrimop fvs p2) Hwf k, (forall t (v1 : ptypeDenote t) (v2 : natvar t), In (vars (x := t) (v1, v2)) G -> v2 < length envT) -> (forall t (v1 : ptypeDenote t) (v2 : natvar t), In (vars (x := t) (v1, v2)) G -> lookup_type v2 fvs = Some t -> forall Heq, (lookup ctypeDenote v2 env :? Heq) = v1) -> pprimopDenote p1 k = cprimopsDenote (cfuncsDenote (ccPrimop p2 fvs Hwf) k env))); my_simpler; eauto. Qed. (** * Parametric version *) Section wf. Variable result : ptype. Lemma Pterm_wf' : forall G (e1 e2 : pterm natvar result), pterm_equiv G e1 e2 -> forall envT (fvs : isfree envT), (forall t (v1 v2 : natvar t), In (vars (v1, v2)) G -> lookup_type v1 fvs = Some t) -> wfTerm fvs e1. Hint Extern 3 (Some _ = Some _) => contradictory; eapply lookup_bound_contra; eauto. apply (pterm_equiv_mut (fun G (e1 e2 : pterm natvar result) => forall envT (fvs : isfree envT), (forall t (v1 v2 : natvar t), In (vars (v1, v2)) G -> lookup_type v1 fvs = Some t) -> wfTerm (envT:=envT) fvs e1) (fun G t (p1 p2 : pprimop natvar result t) => forall envT (fvs : isfree envT), (forall t (v1 v2 : natvar t), In (vars (v1, v2)) G -> lookup_type v1 fvs = Some t) -> wfPrimop (envT:=envT) fvs p1)); simpler; match goal with | [ envT : list ptype, H : _ |- _ ] => apply (H (length envT) (length envT)); simpler end. Qed. Theorem Pterm_wf : forall (E : Pterm result), wfTerm (envT := nil) tt (E _). intros; eapply Pterm_wf'; [apply Pterm_equiv | simpler]. Qed. End wf. Definition CcTerm result (E : Pterm result) : Cprog result := CcTerm' E (Pterm_wf E). Lemma map_funcs_correct : forall result T1 T2 (f : T1 -> T2) (fs : cfuncs ctypeDenote result T1) k, cfuncsDenote (map_funcs f fs) k = f (cfuncsDenote fs k). induction fs; equation. Qed. Theorem CcTerm_correct : forall result (E : Pterm result) k, PtermDenote E k = CprogDenote (CcTerm E) k. Hint Rewrite map_funcs_correct : ltamer. unfold PtermDenote, CprogDenote, CcTerm, CcTerm', cprogDenote; simpler; apply (ccTerm_correct (result := result) (G := nil) (e1 := E _) (e2 := E _) (Pterm_equiv _ _ _) nil tt tt); simpler. Qed.