Mercurial > cpdt > repo
comparison src/StackMachine.v @ 14:8aed4562b62b
Typed expression language
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Wed, 03 Sep 2008 14:26:52 -0400 |
parents | ea400f692b07 |
children | d8c81e19e7d3 |
comparison
equal
deleted
inserted
replaced
13:ea400f692b07 | 14:8aed4562b62b |
---|---|
9 | 9 |
10 (* begin hide *) | 10 (* begin hide *) |
11 Require Import List. | 11 Require Import List. |
12 | 12 |
13 Require Import Tactics. | 13 Require Import Tactics. |
14 | |
15 Set Implicit Arguments. | |
14 (* end hide *) | 16 (* end hide *) |
15 | 17 |
16 | 18 |
17 (** I will start off by jumping right in to a fully-worked set of examples, building certified compilers from increasingly complicated source languages to stack machines. We will meet a few useful tactics and see how they can be used in manual proofs, and we will also see how easily these proofs can be automated instead. I assume that you have installed Coq and Proof General. | 19 (** I will start off by jumping right in to a fully-worked set of examples, building certified compilers from increasingly complicated source languages to stack machines. We will meet a few useful tactics and see how they can be used in manual proofs, and we will also see how easily these proofs can be automated instead. I assume that you have installed Coq and Proof General. |
18 | 20 |
463 | 465 |
464 We are almost done. The lefthand and righthand sides can be seen to match by simple symbolic evaluation. That means we are in luck, because Coq identifies any pair of terms as equal whenever they normalize to the same result by symbolic evaluation. By the definition of [progDenote], that is the case here, but we do not need to worry about such details. A simple invocation of [reflexivity] does the normalization and checks that the two results are syntactically equal. *) | 466 We are almost done. The lefthand and righthand sides can be seen to match by simple symbolic evaluation. That means we are in luck, because Coq identifies any pair of terms as equal whenever they normalize to the same result by symbolic evaluation. By the definition of [progDenote], that is the case here, but we do not need to worry about such details. A simple invocation of [reflexivity] does the normalization and checks that the two results are syntactically equal. *) |
465 | 467 |
466 reflexivity. | 468 reflexivity. |
467 Qed. | 469 Qed. |
470 | |
471 | |
472 (** * Typed expressions *) | |
473 | |
474 (** In this section, we will build on the initial example by adding additional expression forms that depend on static typing of terms for safety. *) | |
475 | |
476 (** ** Source language *) | |
477 | |
478 Inductive type : Set := Nat | Bool. | |
479 | |
480 Inductive tbinop : type -> type -> type -> Set := | |
481 | TPlus : tbinop Nat Nat Nat | |
482 | TTimes : tbinop Nat Nat Nat | |
483 | TEq : forall t, tbinop t t Bool | |
484 | TLt : tbinop Nat Nat Bool. | |
485 | |
486 Inductive texp : type -> Set := | |
487 | TNConst : nat -> texp Nat | |
488 | TBConst : bool -> texp Bool | |
489 | TBinop : forall arg1 arg2 res, tbinop arg1 arg2 res -> texp arg1 -> texp arg2 -> texp res. | |
490 | |
491 Definition typeDenote (t : type) : Set := | |
492 match t with | |
493 | Nat => nat | |
494 | Bool => bool | |
495 end. | |
496 | |
497 Definition eq_bool (b1 b2 : bool) : bool := | |
498 match b1, b2 with | |
499 | true, true => true | |
500 | false, false => true | |
501 | _, _ => false | |
502 end. | |
503 | |
504 Fixpoint eq_nat (n1 n2 : nat) {struct n1} : bool := | |
505 match n1, n2 with | |
506 | O, O => true | |
507 | S n1', S n2' => eq_nat n1' n2' | |
508 | _, _ => false | |
509 end. | |
510 | |
511 Fixpoint lt (n1 n2 : nat) {struct n1} : bool := | |
512 match n1, n2 with | |
513 | O, S _ => true | |
514 | S n1', S n2' => lt n1' n2' | |
515 | _, _ => false | |
516 end. | |
517 | |
518 Definition tbinopDenote arg1 arg2 res (b : tbinop arg1 arg2 res) | |
519 : typeDenote arg1 -> typeDenote arg2 -> typeDenote res := | |
520 match b in (tbinop arg1 arg2 res) return (typeDenote arg1 -> typeDenote arg2 -> typeDenote res) with | |
521 | TPlus => plus | |
522 | TTimes => mult | |
523 | TEq Nat => eq_nat | |
524 | TEq Bool => eq_bool | |
525 | TLt => lt | |
526 end. | |
527 | |
528 Fixpoint texpDenote t (e : texp t) {struct e} : typeDenote t := | |
529 match e in (texp t) return (typeDenote t) with | |
530 | TNConst n => n | |
531 | TBConst b => b | |
532 | TBinop _ _ _ b e1 e2 => (tbinopDenote b) (texpDenote e1) (texpDenote e2) | |
533 end. | |
534 | |
535 | |
536 (** ** Target language *) | |
537 | |
538 Definition tstack := list type. | |
539 | |
540 Inductive tinstr : tstack -> tstack -> Set := | |
541 | TINConst : forall s, nat -> tinstr s (Nat :: s) | |
542 | TIBConst : forall s, bool -> tinstr s (Bool :: s) | |
543 | TIBinop : forall arg1 arg2 res s, | |
544 tbinop arg1 arg2 res | |
545 -> tinstr (arg1 :: arg2 :: s) (res :: s). | |
546 | |
547 Inductive tprog : tstack -> tstack -> Set := | |
548 | TNil : forall s, tprog s s | |
549 | TCons : forall s1 s2 s3, | |
550 tinstr s1 s2 | |
551 -> tprog s2 s3 | |
552 -> tprog s1 s3. | |
553 | |
554 Fixpoint vstack (ts : tstack) : Set := | |
555 match ts with | |
556 | nil => unit | |
557 | t :: ts' => typeDenote t * vstack ts' | |
558 end%type. | |
559 | |
560 Definition tinstrDenote ts ts' (i : tinstr ts ts') : vstack ts -> vstack ts' := | |
561 match i in (tinstr ts ts') return (vstack ts -> vstack ts') with | |
562 | TINConst _ n => fun s => (n, s) | |
563 | TIBConst _ b => fun s => (b, s) | |
564 | TIBinop _ _ _ _ b => fun s => | |
565 match s with | |
566 (arg1, (arg2, s')) => ((tbinopDenote b) arg1 arg2, s') | |
567 end | |
568 end. | |
569 | |
570 Fixpoint tprogDenote ts ts' (p : tprog ts ts') {struct p} : vstack ts -> vstack ts' := | |
571 match p in (tprog ts ts') return (vstack ts -> vstack ts') with | |
572 | TNil _ => fun s => s | |
573 | TCons _ _ _ i p' => fun s => tprogDenote p' (tinstrDenote i s) | |
574 end. | |
575 | |
576 | |
577 (** ** Translation *) | |
578 | |
579 Fixpoint tconcat ts ts' ts'' (p : tprog ts ts') {struct p} : tprog ts' ts'' -> tprog ts ts'' := | |
580 match p in (tprog ts ts') return (tprog ts' ts'' -> tprog ts ts'') with | |
581 | TNil _ => fun p' => p' | |
582 | TCons _ _ _ i p1 => fun p' => TCons i (tconcat p1 p') | |
583 end. | |
584 | |
585 Fixpoint tcompile t (e : texp t) (ts : tstack) {struct e} : tprog ts (t :: ts) := | |
586 match e in (texp t) return (tprog ts (t :: ts)) with | |
587 | TNConst n => TCons (TINConst _ n) (TNil _) | |
588 | TBConst b => TCons (TIBConst _ b) (TNil _) | |
589 | TBinop _ _ _ b e1 e2 => tconcat (tcompile e2 _) | |
590 (tconcat (tcompile e1 _) (TCons (TIBinop _ b) (TNil _))) | |
591 end. | |
592 | |
593 Print tcompile. | |
594 | |
595 | |
596 (** ** Translation correctness *) | |
597 | |
598 Lemma tcompileCorrect' : forall t (e : texp t) | |
599 ts (s : vstack ts), | |
600 tprogDenote (tcompile e ts) s | |
601 = (texpDenote e, s). | |
602 induction e; crush. | |
603 Abort. | |
604 | |
605 Lemma tconcatCorrect : forall ts ts' ts'' (p : tprog ts ts') (p' : tprog ts' ts'') | |
606 (s : vstack ts), | |
607 tprogDenote (tconcat p p') s | |
608 = tprogDenote p' (tprogDenote p s). | |
609 induction p; crush. | |
610 Qed. | |
611 | |
612 Hint Rewrite tconcatCorrect : cpdt. | |
613 | |
614 Lemma tcompileCorrect' : forall t (e : texp t) | |
615 ts (s : vstack ts), | |
616 tprogDenote (tcompile e ts) s | |
617 = (texpDenote e, s). | |
618 induction e; crush. | |
619 Qed. | |
620 | |
621 Hint Rewrite tcompileCorrect' : cpdt. | |
622 | |
623 Theorem tcompileCorrect : forall t (e : texp t), tprogDenote (tcompile e nil) tt = (texpDenote e, tt). | |
624 crush. | |
625 Qed. |