Mercurial > cpdt > repo
diff src/Extensional.v @ 244:0400fa005d5a
New release
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Wed, 09 Dec 2009 14:12:33 -0500 |
parents | 19902d0b6622 |
children | 4293dd6912cd |
line wrap: on
line diff
--- a/src/Extensional.v Wed Dec 09 13:59:01 2009 -0500 +++ b/src/Extensional.v Wed Dec 09 14:12:33 2009 -0500 @@ -384,631 +384,6 @@ End STLC. -(** * A Pattern Compiler *) - -Module PatMatch. - Module Source. - Inductive type : Type := - | Unit : type - | Arrow : type -> type -> type - | Prod : type -> type -> type - | Sum : type -> type -> type. - - Infix "-->" := Arrow (right associativity, at level 61). - Infix "++" := Sum (right associativity, at level 60). - Infix "**" := Prod (right associativity, at level 59). - - Inductive pat : type -> list type -> Type := - | PVar : forall t, - pat t (t :: nil) - | PPair : forall t1 t2 ts1 ts2, - pat t1 ts1 - -> pat t2 ts2 - -> pat (t1 ** t2) (ts1 ++ ts2) - | PInl : forall t1 t2 ts, - pat t1 ts - -> pat (t1 ++ t2) ts - | PInr : forall t1 t2 ts, - pat t2 ts - -> pat (t1 ++ t2) ts. - - Implicit Arguments PVar [t]. - Implicit Arguments PInl [t1 t2 ts]. - Implicit Arguments PInr [t1 t2 ts]. - - Notation "##" := PVar (at level 70) : pat_scope. - Notation "[ p1 , p2 ]" := (PPair p1 p2) : pat_scope. - Notation "'Inl' p" := (PInl p) (at level 71) : pat_scope. - Notation "'Inr' p" := (PInr p) (at level 71) : pat_scope. - - Bind Scope pat_scope with pat. - Delimit Scope pat_scope with pat. - - Section vars. - Variable var : type -> Type. - - Inductive exp : type -> Type := - | Var : forall t, - var t - -> exp t - - | EUnit : exp Unit - - | App : forall t1 t2, - exp (t1 --> t2) - -> exp t1 - -> exp t2 - | Abs : forall t1 t2, - (var t1 -> exp t2) - -> exp (t1 --> t2) - - | Pair : forall t1 t2, - exp t1 - -> exp t2 - -> exp (t1 ** t2) - - | EInl : forall t1 t2, - exp t1 - -> exp (t1 ++ t2) - | EInr : forall t1 t2, - exp t2 - -> exp (t1 ++ t2) - - | Case : forall t1 t2 (tss : list (list type)), - exp t1 - -> (forall ts, member ts tss -> pat t1 ts) - -> (forall ts, member ts tss -> hlist var ts -> exp t2) - -> exp t2 - -> exp t2. - End vars. - - Definition Exp t := forall var, exp var t. - - Implicit Arguments Var [var t]. - Implicit Arguments EUnit [var]. - Implicit Arguments App [var t1 t2]. - Implicit Arguments Abs [var t1 t2]. - Implicit Arguments Pair [var t1 t2]. - Implicit Arguments EInl [var t1 t2]. - Implicit Arguments EInr [var t1 t2]. - Implicit Arguments Case [var t1 t2]. - - Notation "# v" := (Var v) (at level 70) : source_scope. - - Notation "()" := EUnit : source_scope. - - Infix "@" := App (left associativity, at level 77) : source_scope. - Notation "\ x , e" := (Abs (fun x => e)) (at level 78) : source_scope. - - Notation "[ x , y ]" := (Pair x y) : source_scope. - - Notation "'Inl' e" := (EInl e) (at level 71) : source_scope. - Notation "'Inr' e" := (EInr e) (at level 71) : source_scope. - - Delimit Scope source_scope with source. - Bind Scope source_scope with exp. - - Local Open Scope source_scope. - - Fixpoint typeDenote (t : type) : Set := - match t with - | Unit => unit - | t1 --> t2 => typeDenote t1 -> typeDenote t2 - | t1 ** t2 => (typeDenote t1 * typeDenote t2)%type - | t1 ++ t2 => (typeDenote t1 + typeDenote t2)%type - end. - - Fixpoint patDenote t ts (p : pat t ts) - : typeDenote t -> option (hlist typeDenote ts) := - match p with - | PVar _ => fun v => Some (v ::: HNil) - | PPair _ _ _ _ p1 p2 => fun v => - match patDenote p1 (fst v), patDenote p2 (snd v) with - | Some tup1, Some tup2 => Some (happ tup1 tup2) - | _, _ => None - end - | PInl _ _ _ p' => fun v => - match v with - | inl v' => patDenote p' v' - | _ => None - end - | PInr _ _ _ p' => fun v => - match v with - | inr v' => patDenote p' v' - | _ => None - end - end. - - Section matchesDenote. - Variables t2 : type. - Variable default : typeDenote t2. - - Fixpoint matchesDenote (tss : list (list type)) - : (forall ts, member ts tss -> option (hlist typeDenote ts)) - -> (forall ts, member ts tss -> hlist typeDenote ts -> typeDenote t2) - -> typeDenote t2 := - match tss return (forall ts, member ts tss -> option (hlist typeDenote ts)) - -> (forall ts, member ts tss -> hlist typeDenote ts -> typeDenote t2) - -> _ with - | nil => fun _ _ => - default - | ts :: tss' => fun (envs : forall ts', member ts' (ts :: tss') - -> option (hlist typeDenote ts')) - (bodies : forall ts', member ts' (ts :: tss') - -> hlist typeDenote ts' -> typeDenote t2) => - match envs _ HFirst with - | None => matchesDenote - (fun _ mem => envs _ (HNext mem)) - (fun _ mem => bodies _ (HNext mem)) - | Some env => (bodies _ HFirst) env - end - end. - End matchesDenote. - - Implicit Arguments matchesDenote [t2 tss]. - - Fixpoint expDenote t (e : exp typeDenote t) : typeDenote t := - match e with - | Var _ v => v - - | EUnit => tt - - | App _ _ e1 e2 => (expDenote e1) (expDenote e2) - | Abs _ _ e' => fun x => expDenote (e' x) - - | Pair _ _ e1 e2 => (expDenote e1, expDenote e2) - - | EInl _ _ e' => inl _ (expDenote e') - | EInr _ _ e' => inr _ (expDenote e') - - | Case _ _ _ e ps es def => - matchesDenote (expDenote def) - (fun _ mem => patDenote (ps _ mem) (expDenote e)) - (fun _ mem env => expDenote (es _ mem env)) - end. - - Definition ExpDenote t (E : Exp t) := expDenote (E _). - End Source. - - Import Source. - - Module Elab. - Section vars. - Variable var : type -> Type. - - Inductive exp : type -> Type := - | Var : forall t, - var t - -> exp t - - | EUnit : exp Unit - - | App : forall t1 t2, - exp (t1 --> t2) - -> exp t1 - -> exp t2 - | Abs : forall t1 t2, - (var t1 -> exp t2) - -> exp (t1 --> t2) - - | 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 - - | EInl : forall t1 t2, - exp t1 - -> exp (t1 ++ t2) - | EInr : forall t1 t2, - exp t2 - -> exp (t1 ++ t2) - | Case : forall t1 t2 t, - exp (t1 ++ t2) - -> (var t1 -> exp t) - -> (var t2 -> exp t) - -> exp t. - End vars. - - Definition Exp t := forall var, exp var t. - - Implicit Arguments Var [var t]. - Implicit Arguments EUnit [var]. - Implicit Arguments App [var t1 t2]. - Implicit Arguments Abs [var t1 t2]. - Implicit Arguments Pair [var t1 t2]. - Implicit Arguments Fst [var t1 t2]. - Implicit Arguments Snd [var t1 t2]. - Implicit Arguments EInl [var t1 t2]. - Implicit Arguments EInr [var t1 t2]. - Implicit Arguments Case [var t1 t2 t]. - - - Notation "# v" := (Var v) (at level 70) : elab_scope. - - Notation "()" := EUnit : elab_scope. - - Infix "@" := App (left associativity, at level 77) : elab_scope. - Notation "\ x , e" := (Abs (fun x => e)) (at level 78) : elab_scope. - Notation "\ ? , e" := (Abs (fun _ => e)) (at level 78) : elab_scope. - - Notation "[ x , y ]" := (Pair x y) : elab_scope. - Notation "#1 e" := (Fst e) (at level 72) : elab_scope. - Notation "#2 e" := (Snd e) (at level 72) : elab_scope. - - Notation "'Inl' e" := (EInl e) (at level 71) : elab_scope. - Notation "'Inr' e" := (EInr e) (at level 71) : elab_scope. - - Bind Scope elab_scope with exp. - Delimit Scope elab_scope with elab. - - Open Scope elab_scope. - - Fixpoint expDenote t (e : exp typeDenote t) : typeDenote t := - match e with - | Var _ v => v - - | EUnit => tt - - | App _ _ e1 e2 => (expDenote e1) (expDenote e2) - | Abs _ _ e' => fun x => expDenote (e' x) - - | Pair _ _ e1 e2 => (expDenote e1, expDenote e2) - | Fst _ _ e' => fst (expDenote e') - | Snd _ _ e' => snd (expDenote e') - - | EInl _ _ e' => inl _ (expDenote e') - | EInr _ _ e' => inr _ (expDenote e') - | Case _ _ _ e' e1 e2 => - match expDenote e' with - | inl v => expDenote (e1 v) - | inr v => expDenote (e2 v) - end - end. - - Definition ExpDenote t (E : Exp t) := expDenote (E _). - End Elab. - - Import Elab. - - Notation "x <- e1 ; e2" := ((\x, e2) @ e1)%source - (right associativity, at level 76, e1 at next level) : source_scope. - Notation "x <- e1 ; e2" := ((\x, e2) @ e1)%elab - (right associativity, at level 76, e1 at next level) : elab_scope. - - Section choice_tree. - Open Scope source_scope. - - Fixpoint choice_tree var (t : type) (result : Type) : Type := - match t with - | t1 ** t2 => - choice_tree var t1 - (choice_tree var t2 - result) - | t1 ++ t2 => - choice_tree var t1 result - * choice_tree var t2 result - | t => exp var t -> result - end%type. - - Fixpoint merge var t result - : (result -> result -> result) - -> choice_tree var t result -> choice_tree var t result -> choice_tree var t result := - match t with - | _ ** _ => fun mr ct1 ct2 => - merge _ _ - (merge _ _ mr) - ct1 ct2 - - | _ ++ _ => fun mr ct1 ct2 => - (merge var _ mr (fst ct1) (fst ct2), - merge var _ mr (snd ct1) (snd ct2)) - - | _ => fun mr ct1 ct2 e => mr (ct1 e) (ct2 e) - end. - - Fixpoint everywhere var t result - : (exp var t -> result) -> choice_tree var t result := - match t with - | t1 ** t2 => fun r => - everywhere (t := t1) (fun e1 => - everywhere (t := t2) (fun e2 => - r ([e1, e2])%elab)) - - | _ ++ _ => fun r => - (everywhere (fun e => r (Inl e)%elab), - everywhere (fun e => r (Inr e)%elab)) - - | _ => fun r => r - end. - End choice_tree. - - Implicit Arguments merge [var t result]. - - Section elaborate. - Local Open Scope elab_scope. - - Fixpoint elaboratePat var t1 ts result (p : pat t1 ts) : - (hlist (exp var) ts -> result) -> result -> choice_tree var t1 result := - match p with - | PVar _ => fun succ fail => - everywhere (fun disc => succ (disc ::: HNil)) - - | PPair _ _ _ _ p1 p2 => fun succ fail => - elaboratePat p1 - (fun tup1 => - elaboratePat p2 - (fun tup2 => - succ (happ tup1 tup2)) - fail) - (everywhere (fun _ => fail)) - - | PInl _ _ _ p' => fun succ fail => - (elaboratePat p' succ fail, - everywhere (fun _ => fail)) - | PInr _ _ _ p' => fun succ fail => - (everywhere (fun _ => fail), - elaboratePat p' succ fail) - end. - - Implicit Arguments elaboratePat [var t1 ts result]. - - Fixpoint letify var t ts : (hlist var ts -> exp var t) - -> hlist (exp var) ts -> exp var t := - match ts with - | nil => fun f _ => f HNil - | _ :: _ => fun f tup => letify (fun tup' => x <- hhd tup; f (x ::: tup')) (htl tup) - end. - - Implicit Arguments letify [var t ts]. - - Fixpoint expand var result t1 t2 - (out : result -> exp var t2) - : forall ct : choice_tree var t1 result, - exp var t1 - -> exp var t2 := - match t1 with - | (_ ** _)%source => fun ct disc => - expand - (fun ct' => expand out ct' (#2 disc)%source) - ct - (#1 disc) - - | (_ ++ _)%source => fun ct disc => - Case disc - (fun x => expand out (fst ct) (#x)) - (fun y => expand out (snd ct) (#y)) - - | _ => fun ct disc => - x <- disc; out (ct (#x)) - end. - - Definition mergeOpt A (o1 o2 : option A) := - match o1 with - | None => o2 - | _ => o1 - end. - - Import Source. - - Fixpoint elaborateMatches var t1 t2 - (tss : list (list type)) - : (forall ts, member ts tss -> pat t1 ts) - -> (forall ts, member ts tss -> hlist var ts -> Elab.exp var t2) - -> choice_tree var t1 (option (Elab.exp var t2)) := - match tss return (forall ts, member ts tss -> pat t1 ts) - -> (forall ts, member ts tss -> hlist var ts -> Elab.exp var t2) - -> _ with - | nil => fun _ _ => - everywhere (fun _ => None) - | ts :: tss' => fun (ps : forall ts', member ts' (ts :: tss') -> pat t1 ts') - (es : forall ts', member ts' (ts :: tss') -> hlist var ts' -> Elab.exp var t2) => - merge (@mergeOpt _) - (elaboratePat (ps _ HFirst) - (fun ts => Some (letify - (fun ts' => es _ HFirst ts') - ts)) - None) - (elaborateMatches - (fun _ mem => ps _ (HNext mem)) - (fun _ mem => es _ (HNext mem))) - end. - - Implicit Arguments elaborateMatches [var t1 t2 tss]. - - Open Scope cps_scope. - - Fixpoint elaborate var t (e : Source.exp var t) : Elab.exp var t := - match e with - | Var _ v => #v - - | EUnit => () - - | App _ _ e1 e2 => elaborate e1 @ elaborate e2 - | Abs _ _ e' => \x, elaborate (e' x) - - | Pair _ _ e1 e2 => [elaborate e1, elaborate e2] - | EInl _ _ e' => Inl (elaborate e') - | EInr _ _ e' => Inr (elaborate e') - - | Case _ _ _ e' ps es def => - expand - (fun eo => match eo with - | None => elaborate def - | Some e => e - end) - (elaborateMatches ps (fun _ mem env => elaborate (es _ mem env))) - (elaborate e') - end. - End elaborate. - - Definition Elaborate t (E : Source.Exp t) : Elab.Exp t := - fun _ => elaborate (E _). - - Fixpoint grab t result : choice_tree typeDenote t result -> typeDenote t -> result := - match t with - | t1 ** t2 => fun ct v => - grab t2 _ (grab t1 _ ct (fst v)) (snd v) - | t1 ++ t2 => fun ct v => - match v with - | inl v' => grab t1 _ (fst ct) v' - | inr v' => grab t2 _ (snd ct) v' - end - | t => fun ct v => ct (#v)%elab - end%source%type. - - Implicit Arguments grab [t result]. - - Ltac my_crush := - crush; - repeat (match goal with - | [ |- context[match ?E with inl _ => _ | inr _ => _ end] ] => - destruct E - end; crush). - - Lemma expand_grab : forall t2 t1 result - (out : result -> Elab.exp typeDenote t2) - (ct : choice_tree typeDenote t1 result) - (disc : Elab.exp typeDenote t1), - Elab.expDenote (expand out ct disc) - = Elab.expDenote (out (grab ct (Elab.expDenote disc))). - induction t1; my_crush. - Qed. - - Lemma recreate_pair : forall t1 t2 - (x : Elab.exp typeDenote t1) - (x0 : Elab.exp typeDenote t2) - (v : typeDenote (t1 ** t2)), - expDenote x = fst v - -> expDenote x0 = snd v - -> @eq (typeDenote t1 * typeDenote t2) (expDenote [x, x0]) v. - destruct v; crush. - Qed. - - Lemma everywhere_correct : forall t1 result - (succ : Elab.exp typeDenote t1 -> result) disc, - exists disc', grab (everywhere succ) (Elab.expDenote disc) = succ disc' - /\ Elab.expDenote disc' = Elab.expDenote disc. - Hint Resolve recreate_pair. - - induction t1; my_crush; eauto; fold choice_tree; - repeat (fold typeDenote in *; crush; - match goal with - | [ IH : forall result succ, _ |- context[grab (everywhere ?S) _] ] => - generalize (IH _ S); clear IH - | [ e : exp typeDenote (?T ** _), IH : forall _ : exp typeDenote ?T, _ |- _ ] => - generalize (IH (#1 e)); clear IH - | [ e : exp typeDenote (_ ** ?T), IH : forall _ : exp typeDenote ?T, _ |- _ ] => - generalize (IH (#2 e)); clear IH - | [ e : typeDenote ?T, IH : forall _ : exp typeDenote ?T, _ |- _ ] => - generalize (IH (#e)); clear IH - end; crush); eauto. - Qed. - - Lemma merge_correct : forall t result - (ct1 ct2 : choice_tree typeDenote t result) - (mr : result -> result -> result) v, - grab (merge mr ct1 ct2) v = mr (grab ct1 v) (grab ct2 v). - induction t; crush. - Qed. - - Lemma everywhere_fail : forall t result - (fail : result) v, - grab (everywhere (fun _ : Elab.exp typeDenote t => fail)) v = fail. - induction t; crush. - Qed. - - Lemma elaboratePat_correct : forall t1 ts (p : pat t1 ts) - result (succ : hlist (Elab.exp typeDenote) ts -> result) - (fail : result) v env, - patDenote p v = Some env - -> exists env', grab (elaboratePat p succ fail) v = succ env' - /\ env = hmap Elab.expDenote env'. - Hint Resolve hmap_happ. - - induction p; crush; fold choice_tree; - repeat (match goal with - | [ |- context[grab (everywhere ?succ) ?v] ] => - generalize (everywhere_correct succ (#v)%elab) - - | [ H : forall result succ fail, _ - |- context[grab (elaboratePat _ ?S ?F) ?V] ] => - generalize (H _ S F V); clear H - | [ H1 : context[match ?E with Some _ => _ | None => _ end], - H2 : forall env, ?E = Some env -> _ |- _ ] => - destruct E - | [ H : forall env, Some ?E = Some env -> _ |- _ ] => - generalize (H _ (refl_equal _)); clear H - end; crush); eauto. - Qed. - - Lemma elaboratePat_fails : forall t1 ts (p : pat t1 ts) - result (succ : hlist (Elab.exp typeDenote) ts -> result) - (fail : result) v, - patDenote p v = None - -> grab (elaboratePat p succ fail) v = fail. - Hint Resolve everywhere_fail. - - induction p; try solve [ crush ]; - simpl; fold choice_tree; intuition; simpl in *; - repeat match goal with - | [ IH : forall result succ fail v, patDenote ?P v = _ -> _ - |- context[grab (elaboratePat ?P ?S ?F) ?V] ] => - generalize (IH _ S F V); clear IH; intro IH; - generalize (elaboratePat_correct P S F V); intros; - destruct (patDenote P V); try discriminate - | [ H : forall env, Some _ = Some env -> _ |- _ ] => - destruct (H _ (refl_equal _)); clear H; intuition - | [ H : _ |- _ ] => rewrite H; intuition - | [ |- context[match ?v with inl _ => _ | inr _ => _ end] ] => - destruct v; auto - end. - Qed. - - Implicit Arguments letify [var t ts]. - - Lemma letify_correct : forall t ts (f : hlist typeDenote ts -> Elab.exp typeDenote t) - (env : hlist (Elab.exp typeDenote) ts), - Elab.expDenote (letify f env) - = Elab.expDenote (f (hmap Elab.expDenote env)). - induction ts; crush; dep_destruct env; crush. - Qed. - - Theorem elaborate_correct : forall t (e : Source.exp typeDenote t), - Elab.expDenote (elaborate e) = Source.expDenote e. - Hint Rewrite expand_grab merge_correct letify_correct : cpdt. - Hint Rewrite everywhere_fail elaboratePat_fails using assumption : cpdt. - - induction e; crush; try (ext_eq; crush); - match goal with - | [ tss : list (list type) |- _ ] => - induction tss; crush; - match goal with - | [ |- context[grab (elaboratePat ?P ?S ?F) ?V] ] => - case_eq (patDenote P V); [intros env Heq; - destruct (elaboratePat_correct P S F _ Heq); crush; - match goal with - | [ H : _ |- _ ] => rewrite <- H; crush - end - | crush ] - end - end. - Qed. - - Theorem Elaborate_correct : forall t (E : Source.Exp t), - Elab.ExpDenote (Elaborate E) = Source.ExpDenote E. - unfold Elab.ExpDenote, Elaborate, Source.ExpDenote; - intros; apply elaborate_correct. - Qed. - -End PatMatch. - - (** * Exercises *) (** %\begin{enumerate}%#<ol>#