Mercurial > cpdt > repo
comparison src/StackMachine.v @ 277:a57e75752c80
PC comments for Chapter 2
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Tue, 21 Sep 2010 09:50:33 -0400 |
parents | a636eda02176 |
children | e7ed2fddd29a |
comparison
equal
deleted
inserted
replaced
276:6c6786a815dd | 277:a57e75752c80 |
---|---|
6 * The license text is available at: | 6 * The license text is available at: |
7 * http://creativecommons.org/licenses/by-nc-nd/3.0/ | 7 * http://creativecommons.org/licenses/by-nc-nd/3.0/ |
8 *) | 8 *) |
9 | 9 |
10 (* begin hide *) | 10 (* begin hide *) |
11 Require Import List. | 11 Require Import Arith Bool List. |
12 | 12 |
13 Require Import Tactics. | 13 Require Import Tactics. |
14 | 14 |
15 Set Implicit Arguments. | 15 Set Implicit Arguments. |
16 (* end hide *) | 16 (* end hide *) |
19 (** %\chapter{Some Quick Examples}% *) | 19 (** %\chapter{Some Quick Examples}% *) |
20 | 20 |
21 | 21 |
22 (** 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. The code in this book is tested with Coq version 8.2pl1, though parts may work with other versions. | 22 (** 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. The code in this book is tested with Coq version 8.2pl1, though parts may work with other versions. |
23 | 23 |
24 As always, you can step through the source file %\texttt{%#<tt>#StackMachine.v#</tt>#%}% 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 %\texttt{%#<tt>#.v#</tt>#%}% file in an Emacs buffer. If you do the latter, include two lines [Require Import List Tactics.] and [Set Implicit Arguments.] at the start of the file, to match some code hidden in this rendering of the chapter source, and be sure to run the Coq binary %\texttt{%#<tt>#coqtop#</tt>#%}% with the command-line argument %\texttt{%#<tt>#-I SRC#</tt>#%}%, where %\texttt{%#<tt>#SRC#</tt>#%}% is the path to a directory containing the source for this book. In either case, you will need to run %\texttt{%#<tt>#make#</tt>#%}% in the root directory of the source distribution for the book before getting started. If you have installed Proof General properly, it should start automatically when you visit a %\texttt{%#<tt>#.v#</tt>#%}% buffer in Emacs. | 24 As always, you can step through the source file %\texttt{%#<tt>#StackMachine.v#</tt>#%}% 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 %\texttt{%#<tt>#.v#</tt>#%}% file in an Emacs buffer. If you do the latter, include two lines [Require Import Arith Bool List Tactics.] and [Set Implicit Arguments.] at the start of the file, to match some code hidden in this rendering of the chapter source, and be sure to run the Coq binary %\texttt{%#<tt>#coqtop#</tt>#%}% with the command-line argument %\texttt{%#<tt>#-I SRC#</tt>#%}%, where %\texttt{%#<tt>#SRC#</tt>#%}% is the path to a directory containing the source for this book. In either case, you will need to run %\texttt{%#<tt>#make#</tt>#%}% in the root directory of the source distribution for the book before getting started. If you have installed Proof General properly, it should start automatically when you visit a %\texttt{%#<tt>#.v#</tt>#%}% buffer in Emacs. |
25 | 25 |
26 There are some minor headaches associated with getting Proof General to pass the proper command line arguments to the %\texttt{%#<tt>#coqtop#</tt>#%}% program. The best way to add settings that will be shared by many source files is to add a custom variable setting to your %\texttt{%#<tt>#.emacs#</tt>#%}% file, like this: | 26 There are some minor headaches associated with getting Proof General to pass the proper command line arguments to the %\texttt{%#<tt>#coqtop#</tt>#%}% program. The best way to add settings that will be shared by many source files is to add a custom variable setting to your %\texttt{%#<tt>#.emacs#</tt>#%}% file, like this: |
27 %\begin{verbatim}%#<pre>#(custom-set-variables | 27 %\begin{verbatim}%#<pre>#(custom-set-variables |
28 ... | 28 ... |
29 '(coq-prog-args '("-I" "/path/to/cpdt/src")) | 29 '(coq-prog-args '("-I" "/path/to/cpdt/src")) |
50 | Const : nat -> exp | 50 | Const : nat -> exp |
51 | Binop : binop -> exp -> exp -> exp. | 51 | Binop : binop -> exp -> exp -> exp. |
52 | 52 |
53 (** Now we define the type of arithmetic expressions. We write that a constant may be built from one argument, a natural number; and a binary operation may be built from a choice of operator and two operand expressions. | 53 (** Now we define the type of arithmetic expressions. We write that a constant may be built from one argument, a natural number; and a binary operation may be built from a choice of operator and two operand expressions. |
54 | 54 |
55 A note for readers following along in the PDF version: coqdoc supports pretty-printing of tokens in LaTeX or HTML. Where you see a right arrow character, the source contains the ASCII text %\texttt{%#<tt>#->#</tt>#%}%. Other examples of this substitution appearing in this chapter are a double right arrow for %\texttt{%#<tt>#=>#</tt>#%}% and the inverted 'A' symbol for %\texttt{%#<tt>#forall#</tt>#%}%. When in doubt about the ASCII version of a symbol, you can consult the chapter source code. | 55 A note for readers following along in the PDF version: coqdoc supports pretty-printing of tokens in LaTeX or HTML. Where you see a right arrow character, the source contains the ASCII text %\texttt{%#<tt>#->#</tt>#%}%. Other examples of this substitution appearing in this chapter are a double right arrow for %\texttt{%#<tt>#=>#</tt>#%}%, the inverted 'A' symbol for %\texttt{%#<tt>#forall#</tt>#%}%, and the Cartesian product 'X' for %\texttt{%#<tt>#*#</tt>#%}%. When in doubt about the ASCII version of a symbol, you can consult the chapter source code. |
56 | 56 |
57 %\medskip% | 57 %\medskip% |
58 | 58 |
59 Now we are ready to say what these programs mean. We will do this by writing an interpreter that can be thought of as a trivial operational or denotational semantics. (If you are not familiar with these semantic techniques, no need to worry; we will stick to "common sense" constructions.) *) | 59 Now we are ready to say what these programs mean. We will do this by writing an interpreter that can be thought of as a trivial operational or denotational semantics. (If you are not familiar with these semantic techniques, no need to worry; we will stick to "common sense" constructions.) *) |
60 | 60 |
417 progDenote ((compile e2 ++ compile e1 ++ IBinop b :: nil) ++ p) s = | 417 progDenote ((compile e2 ++ compile e1 ++ IBinop b :: nil) ++ p) s = |
418 progDenote p (binopDenote b (expDenote e1) (expDenote e2) :: s) | 418 progDenote p (binopDenote b (expDenote e1) (expDenote e2) :: s) |
419 | 419 |
420 ]] | 420 ]] |
421 | 421 |
422 What we need is the associative law of list concatenation, available as a theorem [app_ass] in the standard library. *) | 422 What we need is the associative law of list concatenation, which is available as a theorem [app_ass] in the standard library. *) |
423 | 423 |
424 Check app_ass. | 424 Check app_ass. |
425 (** [[ | 425 (** [[ |
426 app_ass | 426 app_ass |
427 : forall (A : Type) (l m n : list A), (l ++ m) ++ n = l ++ m ++ n | 427 : forall (A : Type) (l m n : list A), (l ++ m) ++ n = l ++ m ++ n |
428 | |
429 ]] | |
430 | |
431 If we did not already know the name of the theorem, we could use the [SearchRewrite] command to find it, based on a pattern that we would like to rewrite: *) | |
432 | |
433 SearchRewrite ((_ ++ _) ++ _). | |
434 (** [[ | |
435 app_ass: forall (A : Type) (l m n : list A), (l ++ m) ++ n = l ++ m ++ n | |
436 ass_app: forall (A : Type) (l m n : list A), l ++ m ++ n = (l ++ m) ++ n | |
428 | 437 |
429 ]] | 438 ]] |
430 | 439 |
431 We use it to perform a rewrite: *) | 440 We use it to perform a rewrite: *) |
432 | 441 |
543 | 552 |
544 (** We define a trivial language of types to classify our expressions: *) | 553 (** We define a trivial language of types to classify our expressions: *) |
545 | 554 |
546 Inductive type : Set := Nat | Bool. | 555 Inductive type : Set := Nat | Bool. |
547 | 556 |
548 (** Now we define an expanded set of binary operators. *) | 557 (** Like most programming languages, Coq uses case-sensitive variable names, so that our user-defined type [type] is distinct from the [Type] keyword that we have already seen appear in the statement of a polymorphic theorem (and that we will meet in more detail later), and our constructor names [Nat] and [Bool] are distinct from the types [nat] and [bool] in the standard library. |
558 | |
559 Now we define an expanded set of binary operators. *) | |
549 | 560 |
550 Inductive tbinop : type -> type -> type -> Set := | 561 Inductive tbinop : type -> type -> type -> Set := |
551 | TPlus : tbinop Nat Nat Nat | 562 | TPlus : tbinop Nat Nat Nat |
552 | TTimes : tbinop Nat Nat Nat | 563 | TTimes : tbinop Nat Nat Nat |
553 | TEq : forall t, tbinop t t Bool | 564 | TEq : forall t, tbinop t t Bool |
577 | Bool => bool | 588 | Bool => bool |
578 end. | 589 end. |
579 | 590 |
580 (** It can take a few moments to come to terms with the fact that [Set], the type of types of programs, is itself a first-class type, and that we can write functions that return [Set]s. Past that wrinkle, the definition of [typeDenote] is trivial, relying on the [nat] and [bool] types from the Coq standard library. | 591 (** It can take a few moments to come to terms with the fact that [Set], the type of types of programs, is itself a first-class type, and that we can write functions that return [Set]s. Past that wrinkle, the definition of [typeDenote] is trivial, relying on the [nat] and [bool] types from the Coq standard library. |
581 | 592 |
582 We need to define a few auxiliary functions, implementing our boolean binary operators that do not appear with the right types in the standard library. They are entirely standard and ML-like, with the one caveat being that the Coq [nat] type uses a unary representation, where [O] is zero and [S n] is the successor of [n]. | 593 We need to define one auxiliary function, implementing a boolean binary "less-than" operator, which only appears in the standard library with a type fancier than what we are prepared to deal with here. The code is entirely standard and ML-like, with the one caveat being that the Coq [nat] type uses a unary representation, where [O] is zero and [S n] is the successor of [n]. |
583 *) | 594 *) |
584 | |
585 Definition eq_bool (b1 b2 : bool) : bool := | |
586 match b1, b2 with | |
587 | true, true => true | |
588 | false, false => true | |
589 | _, _ => false | |
590 end. | |
591 | |
592 Fixpoint eq_nat (n1 n2 : nat) : bool := | |
593 match n1, n2 with | |
594 | O, O => true | |
595 | S n1', S n2' => eq_nat n1' n2' | |
596 | _, _ => false | |
597 end. | |
598 | 595 |
599 Fixpoint lt (n1 n2 : nat) : bool := | 596 Fixpoint lt (n1 n2 : nat) : bool := |
600 match n1, n2 with | 597 match n1, n2 with |
601 | O, S _ => true | 598 | O, S _ => true |
602 | S n1', S n2' => lt n1' n2' | 599 | S n1', S n2' => lt n1' n2' |
603 | _, _ => false | 600 | _, _ => false |
604 end. | 601 end. |
605 | 602 |
606 (** Now we can interpret binary operators: *) | 603 (** Now we can interpret binary operators, relying on standard-library equality test functions [eqb] and [beq_nat] for booleans and naturals, respectively: *) |
607 | 604 |
608 Definition tbinopDenote arg1 arg2 res (b : tbinop arg1 arg2 res) | 605 Definition tbinopDenote arg1 arg2 res (b : tbinop arg1 arg2 res) |
609 : typeDenote arg1 -> typeDenote arg2 -> typeDenote res := | 606 : typeDenote arg1 -> typeDenote arg2 -> typeDenote res := |
610 match b in (tbinop arg1 arg2 res) | 607 match b in (tbinop arg1 arg2 res) |
611 return (typeDenote arg1 -> typeDenote arg2 -> typeDenote res) with | 608 return (typeDenote arg1 -> typeDenote arg2 -> typeDenote res) with |
612 | TPlus => plus | 609 | TPlus => plus |
613 | TTimes => mult | 610 | TTimes => mult |
614 | TEq Nat => eq_nat | 611 | TEq Nat => beq_nat |
615 | TEq Bool => eq_bool | 612 | TEq Bool => eqb |
616 | TLt => lt | 613 | TLt => lt |
617 end. | 614 end. |
618 | 615 |
619 (** This function has just a few differences from the denotation functions we saw earlier. First, [tbinop] is an indexed type, so its indices become additional arguments to [tbinopDenote]. Second, we need to perform a genuine %\textit{%#<i>#dependent pattern match#</i>#%}% to come up with a definition of this function that type-checks. In each branch of the [match], we need to use branch-specific information about the indices to [tbinop]. General type inference that takes such information into account is undecidable, so it is often necessary to write annotations, like we see above on the line with [match]. | 616 (** This function has just a few differences from the denotation functions we saw earlier. First, [tbinop] is an indexed type, so its indices become additional arguments to [tbinopDenote]. Second, we need to perform a genuine %\textit{%#<i>#dependent pattern match#</i>#%}% to come up with a definition of this function that type-checks. In each branch of the [match], we need to use branch-specific information about the indices to [tbinop]. General type inference that takes such information into account is undecidable, so it is often necessary to write annotations, like we see above on the line with [match]. |
620 | 617 |
628 Definition tbinopDenote arg1 arg2 res (b : tbinop arg1 arg2 res) | 625 Definition tbinopDenote arg1 arg2 res (b : tbinop arg1 arg2 res) |
629 : typeDenote arg1 -> typeDenote arg2 -> typeDenote res := | 626 : typeDenote arg1 -> typeDenote arg2 -> typeDenote res := |
630 match b with | 627 match b with |
631 | TPlus => plus | 628 | TPlus => plus |
632 | TTimes => mult | 629 | TTimes => mult |
633 | TEq Nat => eq_nat | 630 | TEq Nat => beq_nat |
634 | TEq Bool => eq_bool | 631 | TEq Bool => eqb |
635 | TLt => lt | 632 | TLt => lt |
636 end. | 633 end. |
637 | 634 |
638 (** | 635 (** |
639 The same tricks suffice to define an expression denotation function in an unsurprising way: | 636 The same tricks suffice to define an expression denotation function in an unsurprising way: |