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.