Mercurial > cpdt > repo
comparison src/StackMachine.v @ 447:9e3333bd08a1
Proofreading pass through Chapter 2
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Fri, 17 Aug 2012 12:22:26 -0400 |
parents | 89c67796754e |
children | 2740b8a23cce |
comparison
equal
deleted
inserted
replaced
446:a0c604da96d3 | 447:9e3333bd08a1 |
---|---|
8 *) | 8 *) |
9 | 9 |
10 | 10 |
11 (** %\chapter{Some Quick Examples}% *) | 11 (** %\chapter{Some Quick Examples}% *) |
12 | 12 |
13 (** 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. This chapter is not meant to give full explanations of the features that are employed. Rather, it is meant more as an advertisement of what is possible. Later chapters will introduce all of the concepts in bottom-up fashion. | 13 (** 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. This chapter is not meant to give full explanations of the features that are employed. Rather, it is meant more as an advertisement of what is possible. Later chapters will introduce all of the concepts in bottom-up fashion. In other words, it is expected that most readers will not understand what exactly is going on here, but I hope this demo will whet your appetite for the remaining chapters! |
14 | 14 |
15 As always, you can step through the source file <<StackMachine.v>> for this chapter interactively in Proof General. Alternatively, to get a feel for the whole lifecycle of creating a Coq development, you can enter the pieces of source code in this chapter in a new <<.v>> file in an Emacs buffer. If you do the latter, include these two lines at the start of the file. *) | 15 As always, you can step through the source file <<StackMachine.v>> for this chapter interactively in Proof General. Alternatively, to get a feel for the whole lifecycle of creating a Coq development, you can enter the pieces of source code in this chapter in a new <<.v>> file in an Emacs buffer. If you do the latter, include these two lines at the start of the file. *) |
16 | 16 |
17 Require Import Bool Arith List CpdtTactics. | 17 Require Import Bool Arith List CpdtTactics. |
18 Set Implicit Arguments. | 18 Set Implicit Arguments. |
28 | 28 |
29 (** We begin with the syntax of the source language.%\index{Vernacular commands!Inductive}% *) | 29 (** We begin with the syntax of the source language.%\index{Vernacular commands!Inductive}% *) |
30 | 30 |
31 Inductive binop : Set := Plus | Times. | 31 Inductive binop : Set := Plus | Times. |
32 | 32 |
33 (** Our first line of Coq code should be unsurprising to ML and Haskell programmers. We define an %\index{algebraic datatypes}%algebraic datatype [binop] to stand for the binary operators of our source language. There are just two wrinkles compared to ML and Haskell. First, we use the keyword [Inductive], in place of <<data>>, <<datatype>>, or <<type>>. This is not just a trivial surface syntax difference; inductive types in Coq are much more expressive than garden variety algebraic datatypes, essentially enabling us to encode all of mathematics, though we begin humbly in this chapter. Second, there is the %\index{Gallina terms!Set}%[: Set] fragment, which declares that we are defining a datatype that should be thought of as a constituent of programs. Later, we will see other options for defining datatypes in the universe of proofs or in an infinite hierarchy of universes, encompassing both programs and proofs, that bis useful in higher-order constructions. *) | 33 (** Our first line of Coq code should be unsurprising to ML and Haskell programmers. We define an %\index{algebraic datatypes}%algebraic datatype [binop] to stand for the binary operators of our source language. There are just two wrinkles compared to ML and Haskell. First, we use the keyword [Inductive], in place of <<data>>, <<datatype>>, or <<type>>. This is not just a trivial surface syntax difference; inductive types in Coq are much more expressive than garden variety algebraic datatypes, essentially enabling us to encode all of mathematics, though we begin humbly in this chapter. Second, there is the %\index{Gallina terms!Set}%[: Set] fragment, which declares that we are defining a datatype that should be thought of as a constituent of programs. Later, we will see other options for defining datatypes in the universe of proofs or in an infinite hierarchy of universes, encompassing both programs and proofs, that is useful in higher-order constructions. *) |
34 | 34 |
35 Inductive exp : Set := | 35 Inductive exp : Set := |
36 | Const : nat -> exp | 36 | Const : nat -> exp |
37 | Binop : binop -> exp -> exp -> exp. | 37 | Binop : binop -> exp -> exp -> exp. |
38 | 38 |
178 | 178 |
179 Eval simpl in progDenote (compile (Binop Times (Binop Plus (Const 2) (Const 2)) | 179 Eval simpl in progDenote (compile (Binop Times (Binop Plus (Const 2) (Const 2)) |
180 (Const 7))) nil. | 180 (Const 7))) nil. |
181 (** [= Some (28 :: nil) : option stack] *) | 181 (** [= Some (28 :: nil) : option stack] *) |
182 | 182 |
183 (** %\smallskip{}%So far so good, but how can we be sure the compiler operates correctly for _all_ input programs? *) | |
183 | 184 |
184 (** ** Translation Correctness *) | 185 (** ** Translation Correctness *) |
185 | 186 |
186 (** We are ready to prove that our compiler is implemented correctly. We can use a new vernacular command [Theorem] to start a correctness proof, in terms of the semantics we defined earlier:%\index{Vernacular commands!Theorem}% *) | 187 (** We are ready to prove that our compiler is implemented correctly. We can use a new vernacular command [Theorem] to start a correctness proof, in terms of the semantics we defined earlier:%\index{Vernacular commands!Theorem}% *) |
187 | 188 |
522 | 523 |
523 reflexivity. | 524 reflexivity. |
524 Qed. | 525 Qed. |
525 (* end thide *) | 526 (* end thide *) |
526 | 527 |
527 (** This proof can be shortened and made automated, but we leave that as an exercise for the reader. *) | 528 (** This proof can be shortened and made automated, but we leave that task as an exercise for the reader. *) |
528 | 529 |
529 | 530 |
530 (** * Typed Expressions *) | 531 (** * Typed Expressions *) |
531 | 532 |
532 (** In this section, we will build on the initial example by adding additional expression forms that depend on static typing of terms for safety. *) | 533 (** In this section, we will build on the initial example by adding additional expression forms that depend on static typing of terms for safety. *) |
563 Inductive texp : type -> Set := | 564 Inductive texp : type -> Set := |
564 | TNConst : nat -> texp Nat | 565 | TNConst : nat -> texp Nat |
565 | TBConst : bool -> texp Bool | 566 | TBConst : bool -> texp Bool |
566 | TBinop : forall t1 t2 t, tbinop t1 t2 t -> texp t1 -> texp t2 -> texp t. | 567 | TBinop : forall t1 t2 t, tbinop t1 t2 t -> texp t1 -> texp t2 -> texp t. |
567 | 568 |
568 (** Thanks to our use of dependent types, every well-typed [texp] represents a well-typed source expression, by construction. This turns out to be very convenient for many things we might want to do with expressions. For instance, it is easy to adapt our interpreter approach to defining semantics. We start by defining a function mapping the types of our languages into Coq types: *) | 569 (** Thanks to our use of dependent types, every well-typed [texp] represents a well-typed source expression, by construction. This turns out to be very convenient for many things we might want to do with expressions. For instance, it is easy to adapt our interpreter approach to defining semantics. We start by defining a function mapping the types of our object language into Coq types: *) |
569 | 570 |
570 Definition typeDenote (t : type) : Set := | 571 Definition typeDenote (t : type) : Set := |
571 match t with | 572 match t with |
572 | Nat => nat | 573 | Nat => nat |
573 | Bool => bool | 574 | Bool => bool |
682 | TiBConst _ b => (b, s) | 683 | TiBConst _ b => (b, s) |
683 | TiBinop _ _ _ _ b => | 684 | TiBinop _ _ _ _ b => |
684 let '(arg1, (arg2, s')) := s in | 685 let '(arg1, (arg2, s')) := s in |
685 ((tbinopDenote b) arg1 arg2, s') | 686 ((tbinopDenote b) arg1 arg2, s') |
686 end. | 687 end. |
687 | 688 ]] |
688 ]] | 689 |
689 | 690 The Coq type checker complains that: |
690 The Coq type-checker complains that: | |
691 | 691 |
692 << | 692 << |
693 The term "(n, s)" has type "(nat * vstack ts)%type" | 693 The term "(n, s)" has type "(nat * vstack ts)%type" |
694 while it is expected to have type "vstack ?119". | 694 while it is expected to have type "vstack ?119". |
695 >> | 695 >> |
702 Fixpoint tprogDenote ts ts' (p : tprog ts ts') : vstack ts -> vstack ts' := | 702 Fixpoint tprogDenote ts ts' (p : tprog ts ts') : vstack ts -> vstack ts' := |
703 match p with | 703 match p with |
704 | TNil _ => fun s => s | 704 | TNil _ => fun s => s |
705 | TCons _ _ _ i p' => fun s => tprogDenote p' (tinstrDenote i s) | 705 | TCons _ _ _ i p' => fun s => tprogDenote p' (tinstrDenote i s) |
706 end. | 706 end. |
707 | |
708 (** The same argument-postponing trick is crucial for this definition. *) | |
707 | 709 |
708 | 710 |
709 (** ** Translation *) | 711 (** ** Translation *) |
710 | 712 |
711 (** To define our compilation, it is useful to have an auxiliary function for concatenating two stack machine programs. *) | 713 (** To define our compilation, it is useful to have an auxiliary function for concatenating two stack machine programs. *) |