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: