Mercurial > cpdt > repo
comparison 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 |
comparison
equal
deleted
inserted
replaced
243:b2c72c77ad47 | 244:0400fa005d5a |
---|---|
382 (* end thide *) | 382 (* end thide *) |
383 | 383 |
384 End STLC. | 384 End STLC. |
385 | 385 |
386 | 386 |
387 (** * A Pattern Compiler *) | |
388 | |
389 Module PatMatch. | |
390 Module Source. | |
391 Inductive type : Type := | |
392 | Unit : type | |
393 | Arrow : type -> type -> type | |
394 | Prod : type -> type -> type | |
395 | Sum : type -> type -> type. | |
396 | |
397 Infix "-->" := Arrow (right associativity, at level 61). | |
398 Infix "++" := Sum (right associativity, at level 60). | |
399 Infix "**" := Prod (right associativity, at level 59). | |
400 | |
401 Inductive pat : type -> list type -> Type := | |
402 | PVar : forall t, | |
403 pat t (t :: nil) | |
404 | PPair : forall t1 t2 ts1 ts2, | |
405 pat t1 ts1 | |
406 -> pat t2 ts2 | |
407 -> pat (t1 ** t2) (ts1 ++ ts2) | |
408 | PInl : forall t1 t2 ts, | |
409 pat t1 ts | |
410 -> pat (t1 ++ t2) ts | |
411 | PInr : forall t1 t2 ts, | |
412 pat t2 ts | |
413 -> pat (t1 ++ t2) ts. | |
414 | |
415 Implicit Arguments PVar [t]. | |
416 Implicit Arguments PInl [t1 t2 ts]. | |
417 Implicit Arguments PInr [t1 t2 ts]. | |
418 | |
419 Notation "##" := PVar (at level 70) : pat_scope. | |
420 Notation "[ p1 , p2 ]" := (PPair p1 p2) : pat_scope. | |
421 Notation "'Inl' p" := (PInl p) (at level 71) : pat_scope. | |
422 Notation "'Inr' p" := (PInr p) (at level 71) : pat_scope. | |
423 | |
424 Bind Scope pat_scope with pat. | |
425 Delimit Scope pat_scope with pat. | |
426 | |
427 Section vars. | |
428 Variable var : type -> Type. | |
429 | |
430 Inductive exp : type -> Type := | |
431 | Var : forall t, | |
432 var t | |
433 -> exp t | |
434 | |
435 | EUnit : exp Unit | |
436 | |
437 | App : forall t1 t2, | |
438 exp (t1 --> t2) | |
439 -> exp t1 | |
440 -> exp t2 | |
441 | Abs : forall t1 t2, | |
442 (var t1 -> exp t2) | |
443 -> exp (t1 --> t2) | |
444 | |
445 | Pair : forall t1 t2, | |
446 exp t1 | |
447 -> exp t2 | |
448 -> exp (t1 ** t2) | |
449 | |
450 | EInl : forall t1 t2, | |
451 exp t1 | |
452 -> exp (t1 ++ t2) | |
453 | EInr : forall t1 t2, | |
454 exp t2 | |
455 -> exp (t1 ++ t2) | |
456 | |
457 | Case : forall t1 t2 (tss : list (list type)), | |
458 exp t1 | |
459 -> (forall ts, member ts tss -> pat t1 ts) | |
460 -> (forall ts, member ts tss -> hlist var ts -> exp t2) | |
461 -> exp t2 | |
462 -> exp t2. | |
463 End vars. | |
464 | |
465 Definition Exp t := forall var, exp var t. | |
466 | |
467 Implicit Arguments Var [var t]. | |
468 Implicit Arguments EUnit [var]. | |
469 Implicit Arguments App [var t1 t2]. | |
470 Implicit Arguments Abs [var t1 t2]. | |
471 Implicit Arguments Pair [var t1 t2]. | |
472 Implicit Arguments EInl [var t1 t2]. | |
473 Implicit Arguments EInr [var t1 t2]. | |
474 Implicit Arguments Case [var t1 t2]. | |
475 | |
476 Notation "# v" := (Var v) (at level 70) : source_scope. | |
477 | |
478 Notation "()" := EUnit : source_scope. | |
479 | |
480 Infix "@" := App (left associativity, at level 77) : source_scope. | |
481 Notation "\ x , e" := (Abs (fun x => e)) (at level 78) : source_scope. | |
482 | |
483 Notation "[ x , y ]" := (Pair x y) : source_scope. | |
484 | |
485 Notation "'Inl' e" := (EInl e) (at level 71) : source_scope. | |
486 Notation "'Inr' e" := (EInr e) (at level 71) : source_scope. | |
487 | |
488 Delimit Scope source_scope with source. | |
489 Bind Scope source_scope with exp. | |
490 | |
491 Local Open Scope source_scope. | |
492 | |
493 Fixpoint typeDenote (t : type) : Set := | |
494 match t with | |
495 | Unit => unit | |
496 | t1 --> t2 => typeDenote t1 -> typeDenote t2 | |
497 | t1 ** t2 => (typeDenote t1 * typeDenote t2)%type | |
498 | t1 ++ t2 => (typeDenote t1 + typeDenote t2)%type | |
499 end. | |
500 | |
501 Fixpoint patDenote t ts (p : pat t ts) | |
502 : typeDenote t -> option (hlist typeDenote ts) := | |
503 match p with | |
504 | PVar _ => fun v => Some (v ::: HNil) | |
505 | PPair _ _ _ _ p1 p2 => fun v => | |
506 match patDenote p1 (fst v), patDenote p2 (snd v) with | |
507 | Some tup1, Some tup2 => Some (happ tup1 tup2) | |
508 | _, _ => None | |
509 end | |
510 | PInl _ _ _ p' => fun v => | |
511 match v with | |
512 | inl v' => patDenote p' v' | |
513 | _ => None | |
514 end | |
515 | PInr _ _ _ p' => fun v => | |
516 match v with | |
517 | inr v' => patDenote p' v' | |
518 | _ => None | |
519 end | |
520 end. | |
521 | |
522 Section matchesDenote. | |
523 Variables t2 : type. | |
524 Variable default : typeDenote t2. | |
525 | |
526 Fixpoint matchesDenote (tss : list (list type)) | |
527 : (forall ts, member ts tss -> option (hlist typeDenote ts)) | |
528 -> (forall ts, member ts tss -> hlist typeDenote ts -> typeDenote t2) | |
529 -> typeDenote t2 := | |
530 match tss return (forall ts, member ts tss -> option (hlist typeDenote ts)) | |
531 -> (forall ts, member ts tss -> hlist typeDenote ts -> typeDenote t2) | |
532 -> _ with | |
533 | nil => fun _ _ => | |
534 default | |
535 | ts :: tss' => fun (envs : forall ts', member ts' (ts :: tss') | |
536 -> option (hlist typeDenote ts')) | |
537 (bodies : forall ts', member ts' (ts :: tss') | |
538 -> hlist typeDenote ts' -> typeDenote t2) => | |
539 match envs _ HFirst with | |
540 | None => matchesDenote | |
541 (fun _ mem => envs _ (HNext mem)) | |
542 (fun _ mem => bodies _ (HNext mem)) | |
543 | Some env => (bodies _ HFirst) env | |
544 end | |
545 end. | |
546 End matchesDenote. | |
547 | |
548 Implicit Arguments matchesDenote [t2 tss]. | |
549 | |
550 Fixpoint expDenote t (e : exp typeDenote t) : typeDenote t := | |
551 match e with | |
552 | Var _ v => v | |
553 | |
554 | EUnit => tt | |
555 | |
556 | App _ _ e1 e2 => (expDenote e1) (expDenote e2) | |
557 | Abs _ _ e' => fun x => expDenote (e' x) | |
558 | |
559 | Pair _ _ e1 e2 => (expDenote e1, expDenote e2) | |
560 | |
561 | EInl _ _ e' => inl _ (expDenote e') | |
562 | EInr _ _ e' => inr _ (expDenote e') | |
563 | |
564 | Case _ _ _ e ps es def => | |
565 matchesDenote (expDenote def) | |
566 (fun _ mem => patDenote (ps _ mem) (expDenote e)) | |
567 (fun _ mem env => expDenote (es _ mem env)) | |
568 end. | |
569 | |
570 Definition ExpDenote t (E : Exp t) := expDenote (E _). | |
571 End Source. | |
572 | |
573 Import Source. | |
574 | |
575 Module Elab. | |
576 Section vars. | |
577 Variable var : type -> Type. | |
578 | |
579 Inductive exp : type -> Type := | |
580 | Var : forall t, | |
581 var t | |
582 -> exp t | |
583 | |
584 | EUnit : exp Unit | |
585 | |
586 | App : forall t1 t2, | |
587 exp (t1 --> t2) | |
588 -> exp t1 | |
589 -> exp t2 | |
590 | Abs : forall t1 t2, | |
591 (var t1 -> exp t2) | |
592 -> exp (t1 --> t2) | |
593 | |
594 | Pair : forall t1 t2, | |
595 exp t1 | |
596 -> exp t2 | |
597 -> exp (t1 ** t2) | |
598 | Fst : forall t1 t2, | |
599 exp (t1 ** t2) | |
600 -> exp t1 | |
601 | Snd : forall t1 t2, | |
602 exp (t1 ** t2) | |
603 -> exp t2 | |
604 | |
605 | EInl : forall t1 t2, | |
606 exp t1 | |
607 -> exp (t1 ++ t2) | |
608 | EInr : forall t1 t2, | |
609 exp t2 | |
610 -> exp (t1 ++ t2) | |
611 | Case : forall t1 t2 t, | |
612 exp (t1 ++ t2) | |
613 -> (var t1 -> exp t) | |
614 -> (var t2 -> exp t) | |
615 -> exp t. | |
616 End vars. | |
617 | |
618 Definition Exp t := forall var, exp var t. | |
619 | |
620 Implicit Arguments Var [var t]. | |
621 Implicit Arguments EUnit [var]. | |
622 Implicit Arguments App [var t1 t2]. | |
623 Implicit Arguments Abs [var t1 t2]. | |
624 Implicit Arguments Pair [var t1 t2]. | |
625 Implicit Arguments Fst [var t1 t2]. | |
626 Implicit Arguments Snd [var t1 t2]. | |
627 Implicit Arguments EInl [var t1 t2]. | |
628 Implicit Arguments EInr [var t1 t2]. | |
629 Implicit Arguments Case [var t1 t2 t]. | |
630 | |
631 | |
632 Notation "# v" := (Var v) (at level 70) : elab_scope. | |
633 | |
634 Notation "()" := EUnit : elab_scope. | |
635 | |
636 Infix "@" := App (left associativity, at level 77) : elab_scope. | |
637 Notation "\ x , e" := (Abs (fun x => e)) (at level 78) : elab_scope. | |
638 Notation "\ ? , e" := (Abs (fun _ => e)) (at level 78) : elab_scope. | |
639 | |
640 Notation "[ x , y ]" := (Pair x y) : elab_scope. | |
641 Notation "#1 e" := (Fst e) (at level 72) : elab_scope. | |
642 Notation "#2 e" := (Snd e) (at level 72) : elab_scope. | |
643 | |
644 Notation "'Inl' e" := (EInl e) (at level 71) : elab_scope. | |
645 Notation "'Inr' e" := (EInr e) (at level 71) : elab_scope. | |
646 | |
647 Bind Scope elab_scope with exp. | |
648 Delimit Scope elab_scope with elab. | |
649 | |
650 Open Scope elab_scope. | |
651 | |
652 Fixpoint expDenote t (e : exp typeDenote t) : typeDenote t := | |
653 match e with | |
654 | Var _ v => v | |
655 | |
656 | EUnit => tt | |
657 | |
658 | App _ _ e1 e2 => (expDenote e1) (expDenote e2) | |
659 | Abs _ _ e' => fun x => expDenote (e' x) | |
660 | |
661 | Pair _ _ e1 e2 => (expDenote e1, expDenote e2) | |
662 | Fst _ _ e' => fst (expDenote e') | |
663 | Snd _ _ e' => snd (expDenote e') | |
664 | |
665 | EInl _ _ e' => inl _ (expDenote e') | |
666 | EInr _ _ e' => inr _ (expDenote e') | |
667 | Case _ _ _ e' e1 e2 => | |
668 match expDenote e' with | |
669 | inl v => expDenote (e1 v) | |
670 | inr v => expDenote (e2 v) | |
671 end | |
672 end. | |
673 | |
674 Definition ExpDenote t (E : Exp t) := expDenote (E _). | |
675 End Elab. | |
676 | |
677 Import Elab. | |
678 | |
679 Notation "x <- e1 ; e2" := ((\x, e2) @ e1)%source | |
680 (right associativity, at level 76, e1 at next level) : source_scope. | |
681 Notation "x <- e1 ; e2" := ((\x, e2) @ e1)%elab | |
682 (right associativity, at level 76, e1 at next level) : elab_scope. | |
683 | |
684 Section choice_tree. | |
685 Open Scope source_scope. | |
686 | |
687 Fixpoint choice_tree var (t : type) (result : Type) : Type := | |
688 match t with | |
689 | t1 ** t2 => | |
690 choice_tree var t1 | |
691 (choice_tree var t2 | |
692 result) | |
693 | t1 ++ t2 => | |
694 choice_tree var t1 result | |
695 * choice_tree var t2 result | |
696 | t => exp var t -> result | |
697 end%type. | |
698 | |
699 Fixpoint merge var t result | |
700 : (result -> result -> result) | |
701 -> choice_tree var t result -> choice_tree var t result -> choice_tree var t result := | |
702 match t with | |
703 | _ ** _ => fun mr ct1 ct2 => | |
704 merge _ _ | |
705 (merge _ _ mr) | |
706 ct1 ct2 | |
707 | |
708 | _ ++ _ => fun mr ct1 ct2 => | |
709 (merge var _ mr (fst ct1) (fst ct2), | |
710 merge var _ mr (snd ct1) (snd ct2)) | |
711 | |
712 | _ => fun mr ct1 ct2 e => mr (ct1 e) (ct2 e) | |
713 end. | |
714 | |
715 Fixpoint everywhere var t result | |
716 : (exp var t -> result) -> choice_tree var t result := | |
717 match t with | |
718 | t1 ** t2 => fun r => | |
719 everywhere (t := t1) (fun e1 => | |
720 everywhere (t := t2) (fun e2 => | |
721 r ([e1, e2])%elab)) | |
722 | |
723 | _ ++ _ => fun r => | |
724 (everywhere (fun e => r (Inl e)%elab), | |
725 everywhere (fun e => r (Inr e)%elab)) | |
726 | |
727 | _ => fun r => r | |
728 end. | |
729 End choice_tree. | |
730 | |
731 Implicit Arguments merge [var t result]. | |
732 | |
733 Section elaborate. | |
734 Local Open Scope elab_scope. | |
735 | |
736 Fixpoint elaboratePat var t1 ts result (p : pat t1 ts) : | |
737 (hlist (exp var) ts -> result) -> result -> choice_tree var t1 result := | |
738 match p with | |
739 | PVar _ => fun succ fail => | |
740 everywhere (fun disc => succ (disc ::: HNil)) | |
741 | |
742 | PPair _ _ _ _ p1 p2 => fun succ fail => | |
743 elaboratePat p1 | |
744 (fun tup1 => | |
745 elaboratePat p2 | |
746 (fun tup2 => | |
747 succ (happ tup1 tup2)) | |
748 fail) | |
749 (everywhere (fun _ => fail)) | |
750 | |
751 | PInl _ _ _ p' => fun succ fail => | |
752 (elaboratePat p' succ fail, | |
753 everywhere (fun _ => fail)) | |
754 | PInr _ _ _ p' => fun succ fail => | |
755 (everywhere (fun _ => fail), | |
756 elaboratePat p' succ fail) | |
757 end. | |
758 | |
759 Implicit Arguments elaboratePat [var t1 ts result]. | |
760 | |
761 Fixpoint letify var t ts : (hlist var ts -> exp var t) | |
762 -> hlist (exp var) ts -> exp var t := | |
763 match ts with | |
764 | nil => fun f _ => f HNil | |
765 | _ :: _ => fun f tup => letify (fun tup' => x <- hhd tup; f (x ::: tup')) (htl tup) | |
766 end. | |
767 | |
768 Implicit Arguments letify [var t ts]. | |
769 | |
770 Fixpoint expand var result t1 t2 | |
771 (out : result -> exp var t2) | |
772 : forall ct : choice_tree var t1 result, | |
773 exp var t1 | |
774 -> exp var t2 := | |
775 match t1 with | |
776 | (_ ** _)%source => fun ct disc => | |
777 expand | |
778 (fun ct' => expand out ct' (#2 disc)%source) | |
779 ct | |
780 (#1 disc) | |
781 | |
782 | (_ ++ _)%source => fun ct disc => | |
783 Case disc | |
784 (fun x => expand out (fst ct) (#x)) | |
785 (fun y => expand out (snd ct) (#y)) | |
786 | |
787 | _ => fun ct disc => | |
788 x <- disc; out (ct (#x)) | |
789 end. | |
790 | |
791 Definition mergeOpt A (o1 o2 : option A) := | |
792 match o1 with | |
793 | None => o2 | |
794 | _ => o1 | |
795 end. | |
796 | |
797 Import Source. | |
798 | |
799 Fixpoint elaborateMatches var t1 t2 | |
800 (tss : list (list type)) | |
801 : (forall ts, member ts tss -> pat t1 ts) | |
802 -> (forall ts, member ts tss -> hlist var ts -> Elab.exp var t2) | |
803 -> choice_tree var t1 (option (Elab.exp var t2)) := | |
804 match tss return (forall ts, member ts tss -> pat t1 ts) | |
805 -> (forall ts, member ts tss -> hlist var ts -> Elab.exp var t2) | |
806 -> _ with | |
807 | nil => fun _ _ => | |
808 everywhere (fun _ => None) | |
809 | ts :: tss' => fun (ps : forall ts', member ts' (ts :: tss') -> pat t1 ts') | |
810 (es : forall ts', member ts' (ts :: tss') -> hlist var ts' -> Elab.exp var t2) => | |
811 merge (@mergeOpt _) | |
812 (elaboratePat (ps _ HFirst) | |
813 (fun ts => Some (letify | |
814 (fun ts' => es _ HFirst ts') | |
815 ts)) | |
816 None) | |
817 (elaborateMatches | |
818 (fun _ mem => ps _ (HNext mem)) | |
819 (fun _ mem => es _ (HNext mem))) | |
820 end. | |
821 | |
822 Implicit Arguments elaborateMatches [var t1 t2 tss]. | |
823 | |
824 Open Scope cps_scope. | |
825 | |
826 Fixpoint elaborate var t (e : Source.exp var t) : Elab.exp var t := | |
827 match e with | |
828 | Var _ v => #v | |
829 | |
830 | EUnit => () | |
831 | |
832 | App _ _ e1 e2 => elaborate e1 @ elaborate e2 | |
833 | Abs _ _ e' => \x, elaborate (e' x) | |
834 | |
835 | Pair _ _ e1 e2 => [elaborate e1, elaborate e2] | |
836 | EInl _ _ e' => Inl (elaborate e') | |
837 | EInr _ _ e' => Inr (elaborate e') | |
838 | |
839 | Case _ _ _ e' ps es def => | |
840 expand | |
841 (fun eo => match eo with | |
842 | None => elaborate def | |
843 | Some e => e | |
844 end) | |
845 (elaborateMatches ps (fun _ mem env => elaborate (es _ mem env))) | |
846 (elaborate e') | |
847 end. | |
848 End elaborate. | |
849 | |
850 Definition Elaborate t (E : Source.Exp t) : Elab.Exp t := | |
851 fun _ => elaborate (E _). | |
852 | |
853 Fixpoint grab t result : choice_tree typeDenote t result -> typeDenote t -> result := | |
854 match t with | |
855 | t1 ** t2 => fun ct v => | |
856 grab t2 _ (grab t1 _ ct (fst v)) (snd v) | |
857 | t1 ++ t2 => fun ct v => | |
858 match v with | |
859 | inl v' => grab t1 _ (fst ct) v' | |
860 | inr v' => grab t2 _ (snd ct) v' | |
861 end | |
862 | t => fun ct v => ct (#v)%elab | |
863 end%source%type. | |
864 | |
865 Implicit Arguments grab [t result]. | |
866 | |
867 Ltac my_crush := | |
868 crush; | |
869 repeat (match goal with | |
870 | [ |- context[match ?E with inl _ => _ | inr _ => _ end] ] => | |
871 destruct E | |
872 end; crush). | |
873 | |
874 Lemma expand_grab : forall t2 t1 result | |
875 (out : result -> Elab.exp typeDenote t2) | |
876 (ct : choice_tree typeDenote t1 result) | |
877 (disc : Elab.exp typeDenote t1), | |
878 Elab.expDenote (expand out ct disc) | |
879 = Elab.expDenote (out (grab ct (Elab.expDenote disc))). | |
880 induction t1; my_crush. | |
881 Qed. | |
882 | |
883 Lemma recreate_pair : forall t1 t2 | |
884 (x : Elab.exp typeDenote t1) | |
885 (x0 : Elab.exp typeDenote t2) | |
886 (v : typeDenote (t1 ** t2)), | |
887 expDenote x = fst v | |
888 -> expDenote x0 = snd v | |
889 -> @eq (typeDenote t1 * typeDenote t2) (expDenote [x, x0]) v. | |
890 destruct v; crush. | |
891 Qed. | |
892 | |
893 Lemma everywhere_correct : forall t1 result | |
894 (succ : Elab.exp typeDenote t1 -> result) disc, | |
895 exists disc', grab (everywhere succ) (Elab.expDenote disc) = succ disc' | |
896 /\ Elab.expDenote disc' = Elab.expDenote disc. | |
897 Hint Resolve recreate_pair. | |
898 | |
899 induction t1; my_crush; eauto; fold choice_tree; | |
900 repeat (fold typeDenote in *; crush; | |
901 match goal with | |
902 | [ IH : forall result succ, _ |- context[grab (everywhere ?S) _] ] => | |
903 generalize (IH _ S); clear IH | |
904 | [ e : exp typeDenote (?T ** _), IH : forall _ : exp typeDenote ?T, _ |- _ ] => | |
905 generalize (IH (#1 e)); clear IH | |
906 | [ e : exp typeDenote (_ ** ?T), IH : forall _ : exp typeDenote ?T, _ |- _ ] => | |
907 generalize (IH (#2 e)); clear IH | |
908 | [ e : typeDenote ?T, IH : forall _ : exp typeDenote ?T, _ |- _ ] => | |
909 generalize (IH (#e)); clear IH | |
910 end; crush); eauto. | |
911 Qed. | |
912 | |
913 Lemma merge_correct : forall t result | |
914 (ct1 ct2 : choice_tree typeDenote t result) | |
915 (mr : result -> result -> result) v, | |
916 grab (merge mr ct1 ct2) v = mr (grab ct1 v) (grab ct2 v). | |
917 induction t; crush. | |
918 Qed. | |
919 | |
920 Lemma everywhere_fail : forall t result | |
921 (fail : result) v, | |
922 grab (everywhere (fun _ : Elab.exp typeDenote t => fail)) v = fail. | |
923 induction t; crush. | |
924 Qed. | |
925 | |
926 Lemma elaboratePat_correct : forall t1 ts (p : pat t1 ts) | |
927 result (succ : hlist (Elab.exp typeDenote) ts -> result) | |
928 (fail : result) v env, | |
929 patDenote p v = Some env | |
930 -> exists env', grab (elaboratePat p succ fail) v = succ env' | |
931 /\ env = hmap Elab.expDenote env'. | |
932 Hint Resolve hmap_happ. | |
933 | |
934 induction p; crush; fold choice_tree; | |
935 repeat (match goal with | |
936 | [ |- context[grab (everywhere ?succ) ?v] ] => | |
937 generalize (everywhere_correct succ (#v)%elab) | |
938 | |
939 | [ H : forall result succ fail, _ | |
940 |- context[grab (elaboratePat _ ?S ?F) ?V] ] => | |
941 generalize (H _ S F V); clear H | |
942 | [ H1 : context[match ?E with Some _ => _ | None => _ end], | |
943 H2 : forall env, ?E = Some env -> _ |- _ ] => | |
944 destruct E | |
945 | [ H : forall env, Some ?E = Some env -> _ |- _ ] => | |
946 generalize (H _ (refl_equal _)); clear H | |
947 end; crush); eauto. | |
948 Qed. | |
949 | |
950 Lemma elaboratePat_fails : forall t1 ts (p : pat t1 ts) | |
951 result (succ : hlist (Elab.exp typeDenote) ts -> result) | |
952 (fail : result) v, | |
953 patDenote p v = None | |
954 -> grab (elaboratePat p succ fail) v = fail. | |
955 Hint Resolve everywhere_fail. | |
956 | |
957 induction p; try solve [ crush ]; | |
958 simpl; fold choice_tree; intuition; simpl in *; | |
959 repeat match goal with | |
960 | [ IH : forall result succ fail v, patDenote ?P v = _ -> _ | |
961 |- context[grab (elaboratePat ?P ?S ?F) ?V] ] => | |
962 generalize (IH _ S F V); clear IH; intro IH; | |
963 generalize (elaboratePat_correct P S F V); intros; | |
964 destruct (patDenote P V); try discriminate | |
965 | [ H : forall env, Some _ = Some env -> _ |- _ ] => | |
966 destruct (H _ (refl_equal _)); clear H; intuition | |
967 | [ H : _ |- _ ] => rewrite H; intuition | |
968 | [ |- context[match ?v with inl _ => _ | inr _ => _ end] ] => | |
969 destruct v; auto | |
970 end. | |
971 Qed. | |
972 | |
973 Implicit Arguments letify [var t ts]. | |
974 | |
975 Lemma letify_correct : forall t ts (f : hlist typeDenote ts -> Elab.exp typeDenote t) | |
976 (env : hlist (Elab.exp typeDenote) ts), | |
977 Elab.expDenote (letify f env) | |
978 = Elab.expDenote (f (hmap Elab.expDenote env)). | |
979 induction ts; crush; dep_destruct env; crush. | |
980 Qed. | |
981 | |
982 Theorem elaborate_correct : forall t (e : Source.exp typeDenote t), | |
983 Elab.expDenote (elaborate e) = Source.expDenote e. | |
984 Hint Rewrite expand_grab merge_correct letify_correct : cpdt. | |
985 Hint Rewrite everywhere_fail elaboratePat_fails using assumption : cpdt. | |
986 | |
987 induction e; crush; try (ext_eq; crush); | |
988 match goal with | |
989 | [ tss : list (list type) |- _ ] => | |
990 induction tss; crush; | |
991 match goal with | |
992 | [ |- context[grab (elaboratePat ?P ?S ?F) ?V] ] => | |
993 case_eq (patDenote P V); [intros env Heq; | |
994 destruct (elaboratePat_correct P S F _ Heq); crush; | |
995 match goal with | |
996 | [ H : _ |- _ ] => rewrite <- H; crush | |
997 end | |
998 | crush ] | |
999 end | |
1000 end. | |
1001 Qed. | |
1002 | |
1003 Theorem Elaborate_correct : forall t (E : Source.Exp t), | |
1004 Elab.ExpDenote (Elaborate E) = Source.ExpDenote E. | |
1005 unfold Elab.ExpDenote, Elaborate, Source.ExpDenote; | |
1006 intros; apply elaborate_correct. | |
1007 Qed. | |
1008 | |
1009 End PatMatch. | |
1010 | |
1011 | |
1012 (** * Exercises *) | 387 (** * Exercises *) |
1013 | 388 |
1014 (** %\begin{enumerate}%#<ol># | 389 (** %\begin{enumerate}%#<ol># |
1015 | 390 |
1016 %\item%#<li># When in the last chapter we implemented constant folding for simply-typed lambda calculus, it may have seemed natural to try applying beta reductions. This would have been a lot more trouble than is apparent at first, because we would have needed to convince Coq that our normalizing function always terminated. | 391 %\item%#<li># When in the last chapter we implemented constant folding for simply-typed lambda calculus, it may have seemed natural to try applying beta reductions. This would have been a lot more trouble than is apparent at first, because we would have needed to convince Coq that our normalizing function always terminated. |