소스 검색

proof reading

Jeremy Siek 4 년 전
부모
커밋
ccf51a1bbf
1개의 변경된 파일287개의 추가작업 그리고 247개의 파일을 삭제
  1. 287 247
      book.tex

+ 287 - 247
book.tex

@@ -1178,6 +1178,7 @@ $52$ then $10$, the following produces $42$ (not $-42$).
 \end{lstlisting}
 \end{lstlisting}
 
 
 \subsection{Extensible Interpreters via Method Overriding}
 \subsection{Extensible Interpreters via Method Overriding}
+\label{sec:extensible-interp}
 
 
 To prepare for discussing the interpreter for \LangVar{}, we need to
 To prepare for discussing the interpreter for \LangVar{}, we need to
 explain why we choose to implement the interpreter using
 explain why we choose to implement the interpreter using
@@ -4376,19 +4377,16 @@ separately because of its short-circuiting behavior.
       (match e
       (match e
         [(Bool b) b]
         [(Bool b) b]
         [(If cnd thn els)
         [(If cnd thn els)
-         (define b (recur cnd))
-         (match b
+         (match (recur cnd)
            [#t (recur thn)]
            [#t (recur thn)]
            [#f (recur els)])]
            [#f (recur els)])]
         [(Prim 'and (list e1 e2))
         [(Prim 'and (list e1 e2))
-         (define v1 (recur e1))
-         (match v1
+         (match (recur e1)
            [#t (match (recur e2) [#t #t] [#f #f])]
            [#t (match (recur e2) [#t #t] [#f #f])]
            [#f #f])]
            [#f #f])]
         [(Prim op args)
         [(Prim op args)
          (apply (interp-op op) (for/list ([e args]) (recur e)))]
          (apply (interp-op op) (for/list ([e args]) (recur e)))]
-        [else ((super interp-exp env) e)]
-        ))
+        [else ((super interp-exp env) e)]))
     ))
     ))
 
 
 (define (interp-Rif p)
 (define (interp-Rif p)
@@ -4427,8 +4425,7 @@ separately because of its short-circuiting behavior.
     ['>= (lambda (v1 v2)
     ['>= (lambda (v1 v2)
            (cond [(and (fixnum? v1) (fixnum? v2))
            (cond [(and (fixnum? v1) (fixnum? v2))
                   (>= v1 v2)]))]
                   (>= v1 v2)]))]
-    [else (error 'interp-op "unknown operator")]
-    ))
+    [else (error 'interp-op "unknown operator")]))
 \end{lstlisting}
 \end{lstlisting}
 \caption{Interpreter for the primitive operators in the \LangIf{} language.}
 \caption{Interpreter for the primitive operators in the \LangIf{} language.}
 \label{fig:interp-op-Rif}
 \label{fig:interp-op-Rif}
@@ -4455,39 +4452,56 @@ produces a \key{Boolean}.
 
 
 Another way to think about type checking is that it enforces a set of
 Another way to think about type checking is that it enforces a set of
 rules about which operators can be applied to which kinds of
 rules about which operators can be applied to which kinds of
-values. For example, our type checker for \LangIf{} will signal an error
-for the below expression because, as we have seen above, the
-expression \code{(+ 10 ...)} has type \key{Integer} but the type
-checker enforces the rule that the argument of \code{not} must be a
-\key{Boolean}.
+values. For example, our type checker for \LangIf{} signals an error
+for the below expression
 \begin{lstlisting}
 \begin{lstlisting}
    (not (+ 10 (- (+ 12 20))))
    (not (+ 10 (- (+ 12 20))))
 \end{lstlisting}
 \end{lstlisting}
-
-We implement type checking using classes and method overriding for the
-same reason that we use them to implement the interpreters. We
-separate the type checker for the \LangVar{} fragment into its own class,
-shown in Figure~\ref{fig:type-check-Rvar}. The type checker for \LangIf{} is
-shown in Figure~\ref{fig:type-check-Rif}; inherits from the one for
-\LangVar{}. The code for these type checkers are in the files
-\code{type-check-Rvar.rkt} and \code{type-check-Rif.rkt} of the support
-code.
+The subexpression \code{(+ 10 (- (+ 12 20)))} has type \key{Integer}
+but the type checker enforces the rule that the argument of \code{not}
+must be a \key{Boolean}.
+
+We implement type checking using classes and methods because they
+provide the open recursion needed to reuse code as we extend the type
+checker in later chapters, analogous to the use of classes and methods
+for the interpreters (Section~\ref{sec:extensible-interp}).
+
+We separate the type checker for the \LangVar{} fragment into its own
+class, shown in Figure~\ref{fig:type-check-Rvar}. The type checker for
+\LangIf{} is shown in Figure~\ref{fig:type-check-Rif} and it inherits
+from the type checker for \LangVar{}. These type checkers are in the
+files \code{type-check-Rvar.rkt} and \code{type-check-Rif.rkt} of the
+support code.
 %
 %
 Each type checker is a structurally recursive function over the AST.
 Each type checker is a structurally recursive function over the AST.
 Given an input expression \code{e}, the type checker either signals an
 Given an input expression \code{e}, the type checker either signals an
 error or returns an expression and its type (\key{Integer} or
 error or returns an expression and its type (\key{Integer} or
-\key{Boolean}). There are situations in which we want to change or
-update the expression.
-%
-The type of an integer literal is \code{Integer} and
-the type of a Boolean literal is \code{Boolean}.  To handle variables,
-the type checker uses the environment \code{env} to map variables to
-types. Consider the clause for \key{let}.  We type check the
-initializing expression to obtain its type \key{T} and then associate
-type \code{T} with the variable \code{x} in the environment used to
-type check the body of the \key{let}. Thus, when the type checker
-encounters a use of variable \code{x}, it can find its type in the
-environment.
+\key{Boolean}). It returns an expression because there are situations
+in which we want to change or update the expression.
+
+Next we discuss the \code{match} clauses in \code{type-check-exp} of
+Figure~\ref{fig:type-check-Rvar}.  The type of an integer constant is
+\code{Integer}.  To handle variables, the type checker uses the
+environment \code{env} to map variables to types. Consider the clause
+for \key{let}.  We type check the initializing expression to obtain
+its type \key{T} and then associate type \code{T} with the variable
+\code{x} in the environment used to type check the body of the
+\key{let}. Thus, when the type checker encounters a use of variable
+\code{x}, it can find its type in the environment.  Regarding
+primitive operators, we recursively analyze the arguments and then
+invoke \code{type-check-op} to check whether the argument types are
+allowed.
+
+Several auxiliary methods are used in the type checker. The method
+\code{operator-types} defines a dictionary that maps the operator
+names to their parameter and return types. The \code{type-equal?}
+method determines whether two types are equal, which for now simply
+dispatches to \code{equal?}  (deep equality). The
+\code{check-type-equal?} method triggers an error if the two types are
+not equal. The \code{type-check-op} method looks up the operator in
+the \code{operator-types} dictionary and then checks whether the
+argument types are equal to the parameter types.  The result is the
+return type of the operator.
 
 
 \begin{figure}[tbp]
 \begin{figure}[tbp]
 \begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
 \begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
@@ -4517,8 +4531,8 @@ environment.
     (define/public (type-check-exp env)
     (define/public (type-check-exp env)
       (lambda (e)
       (lambda (e)
         (match e
         (match e
-          [(Var x)  (values (Var x) (dict-ref env x))]
           [(Int n)  (values (Int n) 'Integer)]
           [(Int n)  (values (Int n) 'Integer)]
+          [(Var x)  (values (Var x) (dict-ref env x))]
           [(Let x e body)
           [(Let x e body)
            (define-values (e^ Te) ((type-check-exp env) e))
            (define-values (e^ Te) ((type-check-exp env) e))
            (define-values (b Tb) ((type-check-exp (dict-set env x Te)) body))
            (define-values (b Tb) ((type-check-exp (dict-set env x Te)) body))
@@ -4541,7 +4555,7 @@ environment.
 (define (type-check-Rvar p)
 (define (type-check-Rvar p)
   (send (new type-check-Rvar-class) type-check-program p))
   (send (new type-check-Rvar-class) type-check-program p))
 \end{lstlisting}
 \end{lstlisting}
-\caption{Type checker for the \LangVar{} fragment of \LangIf{}.}
+\caption{Type checker for the \LangVar{} language.}
 \label{fig:type-check-Rvar}
 \label{fig:type-check-Rvar}
 \end{figure}
 \end{figure}
 
 
@@ -4567,6 +4581,11 @@ environment.
     (define/override (type-check-exp env)
     (define/override (type-check-exp env)
       (lambda (e)
       (lambda (e)
         (match e
         (match e
+          [(Prim 'eq? (list e1 e2))
+           (define-values (e1^ T1) ((type-check-exp env) e1))
+           (define-values (e2^ T2) ((type-check-exp env) e2))
+           (check-type-equal? T1 T2 e)
+           (values (Prim 'eq? (list e1^ e2^)) 'Boolean)]
           [(Bool b) (values (Bool b) 'Boolean)]
           [(Bool b) (values (Bool b) 'Boolean)]
           [(If cnd thn els)
           [(If cnd thn els)
            (define-values (cnd^ Tc) ((type-check-exp env) cnd))
            (define-values (cnd^ Tc) ((type-check-exp env) cnd))
@@ -4575,11 +4594,6 @@ environment.
            (check-type-equal? Tc 'Boolean e)
            (check-type-equal? Tc 'Boolean e)
            (check-type-equal? Tt Te e)
            (check-type-equal? Tt Te e)
            (values (If cnd^ thn^ els^) Te)]
            (values (If cnd^ thn^ els^) Te)]
-          [(Prim 'eq? (list e1 e2))
-           (define-values (e1^ T1) ((type-check-exp env) e1))
-           (define-values (e2^ T2) ((type-check-exp env) e2))
-           (check-type-equal? T1 T2 e)
-           (values (Prim 'eq? (list e1^ e2^)) 'Boolean)]
           [else ((super type-check-exp env) e)])))
           [else ((super type-check-exp env) e)])))
     ))
     ))
 
 
@@ -4590,46 +4604,93 @@ environment.
 \label{fig:type-check-Rif}
 \label{fig:type-check-Rif}
 \end{figure}
 \end{figure}
 
 
-Three auxiliary methods are used in the type checker. The method
-\code{operator-types} defines a dictionary that maps the operator
-names to their parameter and return types. The \code{type-equal?}
-method determines whether two types are equal, which for now simply
-dispatches to \code{equal?}  (deep equality). The \code{type-check-op}
-method looks up the operator in the \code{operator-types} dictionary
-and then checks whether the argument types are equal to the parameter
-types.  The result is the return type of the operator.
+Next we discuss the type checker for \LangIf{} in
+Figure~\ref{fig:type-check-Rif}.  The operator \code{eq?} requires the
+two arguments to have the same type. The type of a Boolean constant is
+\code{Boolean}. The condition of an \code{if} must be of
+\code{Boolean} type and the two branches must have the same type.  The
+\code{operator-types} function adds dictionary entries for the other
+new operators.
 
 
 \begin{exercise}\normalfont
 \begin{exercise}\normalfont
-Create 10 new example programs in \LangIf{}. Half of the example programs
-should have a type error. For those programs, to signal that a type
-error is expected, create an empty file with the same base name but
-with file extension \code{.tyerr}. For example, if the test
-\code{r2\_14.rkt} is expected to error, then create an empty file
-named \code{r2\_14.tyerr}.  The other half of the example programs
-should not have type errors. Note that if the type checker does not
-signal an error for a program, then interpreting that program should
-not encounter an error.
+Create 10 new test programs in \LangIf{}. Half of the programs should
+have a type error. For those programs, create an empty file with the
+same base name but with file extension \code{.tyerr}. For example, if
+the test \code{cond\_test\_14.rkt} is expected to error, then create
+an empty file named \code{cond\_test\_14.tyerr}.  This indicates to
+\code{interp-tests} and \code{compiler-tests} that a type error is
+expected. The other half of the test programs should not have type
+errors.
+
+In the \code{run-tests.rkt} script, change the second argument of
+\code{interp-tests} and \code{compiler-tests} to
+\code{type-check-Rif}, which causes the type checker to run prior to
+the compiler passes. Temporarily change the \code{passes} to an empty
+list and run the script, thereby checking that the new test programs
+either type check or not as intended.
 \end{exercise}
 \end{exercise}
 
 
 
 
+\section{The \LangCIf{} Intermediate Language}
+\label{sec:Cif}
+
+Figure~\ref{fig:c1-syntax} defines the abstract syntax of the
+\LangCIf{} intermediate language. (The concrete syntax is in the
+Appendix, Figure~\ref{fig:c1-concrete-syntax}.)  Compared to
+\LangCVar{}, the \LangCIf{} language adds logical and comparison
+operators to the \Exp{} non-terminal and the literals \key{\#t} and
+\key{\#f} to the \Arg{} non-terminal.
+
+Regarding control flow, \LangCIf{} adds \key{goto} and \code{if}
+statements to the \Tail{} non-terminal. The condition of an \code{if}
+statement is a comparison operation and the branches are \code{goto}
+statements, making it straightforward to compile \code{if} statements
+to x86.
+
+
+\begin{figure}[tp]
+\fbox{
+\begin{minipage}{0.96\textwidth}
+\small    
+\[
+\begin{array}{lcl}
+\Atm &::=& \gray{\INT{\Int} \mid \VAR{\Var}} \mid \BOOL{\itm{bool}} \\
+\itm{cmp} &::= & \key{eq?} \mid \key{<}  \\
+\Exp &::= & \gray{ \Atm \mid \READ{} }\\
+     &\mid& \gray{ \NEG{\Atm} \mid \ADD{\Atm}{\Atm} } \\
+     &\mid& \UNIOP{\key{'not}}{\Atm} 
+     \mid \BINOP{\key{'}\itm{cmp}}{\Atm}{\Atm} \\
+\Stmt &::=& \gray{ \ASSIGN{\VAR{\Var}}{\Exp} } \\
+\Tail &::= & \gray{\RETURN{\Exp} \mid \SEQ{\Stmt}{\Tail} } 
+    \mid \GOTO{\itm{label}} \\
+    &\mid& \IFSTMT{\BINOP{\itm{cmp}}{\Atm}{\Atm}}{\GOTO{\itm{label}}}{\GOTO{\itm{label}}} \\
+\LangCIf{} & ::= & \gray{\CPROGRAM{\itm{info}}{\LP\LP\itm{label}\,\key{.}\,\Tail\RP\ldots\RP}}
+\end{array}
+\]
+\end{minipage}
+}
+\caption{The abstract syntax of \LangCIf{}, an extension of \LangCVar{}
+  (Figure~\ref{fig:c0-syntax}).}
+\label{fig:c1-syntax}
+\end{figure}
+
 \section{The \LangXASTIf{} Language}
 \section{The \LangXASTIf{} Language}
 \label{sec:x86-if}
 \label{sec:x86-if}
 
 
-\index{x86}
-To implement the new logical operations, the comparison operations,
-and the \key{if} expression, we need to delve further into the x86
-language. Figures~\ref{fig:x86-1-concrete} and \ref{fig:x86-1} define
-the concrete and abstract syntax for a larger subset of x86 that
-includes instructions for logical operations, comparisons, and
-conditional jumps.
-
-One small challenge is that x86 does not provide an instruction that
-directly implements logical negation (\code{not} in \LangIf{} and \LangCIf{}).
-However, the \code{xorq} instruction can be used to encode \code{not}.
-The \key{xorq} instruction takes two arguments, performs a pairwise
-exclusive-or ($\mathrm{XOR}$) operation on each bit of its arguments,
-and writes the results into its second argument.  Recall the truth
-table for exclusive-or:
+\index{x86} To implement the new logical operations, the comparison
+operations, and the \key{if} expression, we need to delve further into
+the x86 language. Figures~\ref{fig:x86-1-concrete} and \ref{fig:x86-1}
+define the concrete and abstract syntax for the \LangXASTIf{} subset
+of x86, which includes instructions for logical operations,
+comparisons, and conditional jumps.
+
+One challenge is that x86 does not provide an instruction that
+directly implements logical negation (\code{not} in \LangIf{} and
+\LangCIf{}).  However, the \code{xorq} instruction can be used to
+encode \code{not}.  The \key{xorq} instruction takes two arguments,
+performs a pairwise exclusive-or ($\mathrm{XOR}$) operation on each
+bit of its arguments, and writes the results into its second argument.
+Recall the truth table for exclusive-or:
 \begin{center}
 \begin{center}
 \begin{tabular}{l|cc}
 \begin{tabular}{l|cc}
    & 0 & 1 \\ \hline
    & 0 & 1 \\ \hline
@@ -4694,16 +4755,16 @@ the first argument:
 \Arg &::=&  \gray{\IMM{\Int} \mid \REG{\Reg} \mid \DEREF{\Reg}{\Int}} 
 \Arg &::=&  \gray{\IMM{\Int} \mid \REG{\Reg} \mid \DEREF{\Reg}{\Int}} 
      \mid \BYTEREG{\itm{bytereg}} \\
      \mid \BYTEREG{\itm{bytereg}} \\
 \itm{cc} & ::= & \key{e} \mid \key{l} \mid \key{le} \mid \key{g} \mid \key{ge} \\
 \itm{cc} & ::= & \key{e} \mid \key{l} \mid \key{le} \mid \key{g} \mid \key{ge} \\
-\Instr &::=& \gray{ \BININSTR{\code{'addq}}{\Arg}{\Arg} 
-       \mid \BININSTR{\code{'subq}}{\Arg}{\Arg} } \\
+\Instr &::=& \gray{ \BININSTR{\code{addq}}{\Arg}{\Arg} 
+       \mid \BININSTR{\code{subq}}{\Arg}{\Arg} } \\
        &\mid& \gray{ \BININSTR{\code{'movq}}{\Arg}{\Arg} 
        &\mid& \gray{ \BININSTR{\code{'movq}}{\Arg}{\Arg} 
-       \mid \UNIINSTR{\code{'negq}}{\Arg} } \\
+       \mid \UNIINSTR{\code{negq}}{\Arg} } \\
        &\mid& \gray{ \CALLQ{\itm{label}}{\itm{int}} \mid \RETQ{} 
        &\mid& \gray{ \CALLQ{\itm{label}}{\itm{int}} \mid \RETQ{} 
        \mid \PUSHQ{\Arg} \mid \POPQ{\Arg} \mid \JMP{\itm{label}} } \\
        \mid \PUSHQ{\Arg} \mid \POPQ{\Arg} \mid \JMP{\itm{label}} } \\
-       &\mid& \BININSTR{\code{'xorq}}{\Arg}{\Arg}
-       \mid \BININSTR{\code{'cmpq}}{\Arg}{\Arg}\\
-       &\mid& \BININSTR{\code{'set}}{\itm{cc}}{\Arg} 
-       \mid \BININSTR{\code{'movzbq}}{\Arg}{\Arg}\\
+       &\mid& \BININSTR{\code{xorq}}{\Arg}{\Arg}
+       \mid \BININSTR{\code{cmpq}}{\Arg}{\Arg}\\
+       &\mid& \BININSTR{\code{set}}{\itm{cc}}{\Arg} 
+       \mid \BININSTR{\code{movzbq}}{\Arg}{\Arg}\\
        &\mid&  \JMPIF{\itm{cc}}{\itm{label}} \\
        &\mid&  \JMPIF{\itm{cc}}{\itm{label}} \\
 \Block &::= & \gray{\BLOCK{\itm{info}}{\LP\Instr\ldots\RP}} \\
 \Block &::= & \gray{\BLOCK{\itm{info}}{\LP\Instr\ldots\RP}} \\
 \LangXASTIf{} &::= & \gray{\XPROGRAM{\itm{info}}{\LP\LP\itm{label} \,\key{.}\, \Block \RP\ldots\RP}}
 \LangXASTIf{} &::= & \gray{\XPROGRAM{\itm{info}}{\LP\LP\itm{label} \,\key{.}\, \Block \RP\ldots\RP}}
@@ -4724,91 +4785,45 @@ placed. The argument order is backwards: if you want to test whether
 $x < y$, then write \code{cmpq} $y$\code{,} $x$. The result of
 $x < y$, then write \code{cmpq} $y$\code{,} $x$. The result of
 \key{cmpq} is placed in the special EFLAGS register. This register
 \key{cmpq} is placed in the special EFLAGS register. This register
 cannot be accessed directly but it can be queried by a number of
 cannot be accessed directly but it can be queried by a number of
-instructions, including the \key{set} instruction. The \key{set}
-instruction puts a \key{1} or \key{0} into its destination depending
-on whether the comparison came out according to the condition code
-\itm{cc} (\key{e} for equal, \key{l} for less, \key{le} for
-less-or-equal, \key{g} for greater, \key{ge} for greater-or-equal).
-The \key{set} instruction has an annoying quirk in that its
-destination argument must be single byte register, such as \code{al}
-(L for lower bits) or \code{ah} (H for higher bits), which are part of
-the \code{rax} register.  Thankfully, the \key{movzbq} instruction can
-then be used to move from a single byte register to a normal 64-bit
-register.
-
-The x86 instruction for conditional jump are relevant to the
-compilation of \key{if} expressions.  The \key{JmpIf} instruction
-updates the program counter to point to the instruction after the
-indicated label depending on whether the result in the EFLAGS register
-matches the condition code \itm{cc}, otherwise the \key{JmpIf}
-instruction falls through to the next instruction.  The abstract
-syntax for \key{JmpIf} differs from the concrete syntax for x86 in
-that it separates the instruction name from the condition code. For
+instructions, including the \key{set} instruction. The instruction
+$\key{set}cc~d$ puts a \key{1} or \key{0} into the destination $d$
+depending on whether the comparison comes out according to the
+condition code \itm{cc} (\key{e} for equal, \key{l} for less, \key{le}
+for less-or-equal, \key{g} for greater, \key{ge} for
+greater-or-equal).  The \key{set} instruction has an annoying quirk in
+that its destination argument must be single byte register, such as
+\code{al} (L for lower bits) or \code{ah} (H for higher bits), which
+are part of the \code{rax} register.  Thankfully, the \key{movzbq}
+instruction can be used to move from a single byte register to a
+normal 64-bit register.  The abstract syntax for the \code{set}
+instruction differs from the concrete syntax in that it separates the
+instruction name from the condition code.
+
+The x86 instruction for conditional jump is relevant to the
+compilation of \key{if} expressions.  The instruction
+$\key{j}\itm{cc}~\itm{label}$ updates the program counter to point to
+the instruction after \itm{label} depending on whether the result in
+the EFLAGS register matches the condition code \itm{cc}, otherwise the
+jump instruction falls through to the next instruction.  Like the
+abstract syntax for \code{set}, the abstract syntax for conditional
+jump separates the instruction name from the condition code. For
 example, \code{(JmpIf le foo)} corresponds to \code{jle foo}.  Because
 example, \code{(JmpIf le foo)} corresponds to \code{jle foo}.  Because
-the \key{JmpIf} instruction relies on the EFLAGS register, it is
-common for the \key{JmpIf} to be immediately preceded by a \key{cmpq}
-instruction to set the EFLAGS register.
+the conditional jump instruction relies on the EFLAGS register, it is
+common for it to be immediately preceded by a \key{cmpq} instruction
+to set the EFLAGS register.
 
 
 
 
-\section{The \LangCIf{} Intermediate Language}
-\label{sec:Cif}
-
-As with \LangVar{}, we compile \LangIf{} to a C-like intermediate language, but
-we need to grow that intermediate language to handle the new features
-in \LangIf{}: Booleans and conditional expressions.
-Figure~\ref{fig:c1-syntax} defines the abstract syntax of \LangCIf{}. (The
-concrete syntax is in the Appendix,
-Figure~\ref{fig:c1-concrete-syntax}.)  The \LangCIf{} language adds logical
-and comparison operators to the $\Exp$ non-terminal and the literals
-\key{\#t} and \key{\#f} to the $\Arg$ non-terminal.  Regarding control
-flow, \LangCIf{} differs considerably from \LangIf{}.  Instead of \key{if}
-expressions, \LangCIf{} has \key{goto} and conditional \key{goto} in the
-grammar for $\Tail$. This means that a sequence of statements may now
-end with a \code{goto} or a conditional \code{goto}. The conditional
-\code{goto} jumps to one of two labels depending on the outcome of the
-comparison. In Section~\ref{sec:explicate-control-Rif} we discuss how
-to translate from \LangIf{} to \LangCIf{}, bridging this gap between \key{if}
-expressions and \key{goto}'s.
-
-\begin{figure}[tp]
-\fbox{
-\begin{minipage}{0.96\textwidth}
-\small    
-\[
-\begin{array}{lcl}
-\Atm &::=& \gray{\INT{\Int} \mid \VAR{\Var}} \mid \BOOL{\itm{bool}} \\
-\itm{cmp} &::= & \key{eq?} \mid \key{<}  \\
-\Exp &::= & \gray{ \Atm \mid \READ{} }\\
-     &\mid& \gray{ \NEG{\Atm} \mid \ADD{\Atm}{\Atm} } \\
-     &\mid& \UNIOP{\key{'not}}{\Atm} 
-     \mid \BINOP{\key{'}\itm{cmp}}{\Atm}{\Atm} \\
-\Stmt &::=& \gray{ \ASSIGN{\VAR{\Var}}{\Exp} } \\
-\Tail &::= & \gray{\RETURN{\Exp} \mid \SEQ{\Stmt}{\Tail} } 
-    \mid \GOTO{\itm{label}} \\
-    &\mid& \IFSTMT{\BINOP{\itm{cmp}}{\Atm}{\Atm}}{\GOTO{\itm{label}}}{\GOTO{\itm{label}}} \\
-\LangCIf{} & ::= & \gray{\CPROGRAM{\itm{info}}{\LP\LP\itm{label}\,\key{.}\,\Tail\RP\ldots\RP}}
-\end{array}
-\]
-\end{minipage}
-}
-\caption{The abstract syntax of \LangCIf{}, an extension of \LangCVar{}
-  (Figure~\ref{fig:c0-syntax}).}
-\label{fig:c1-syntax}
-\end{figure}
-
-\clearpage
-
 \section{Shrink the \LangIf{} Language}
 \section{Shrink the \LangIf{} Language}
 \label{sec:shrink-Rif}
 \label{sec:shrink-Rif}
 
 
 The \LangIf{} language includes several operators that are easily
 The \LangIf{} language includes several operators that are easily
-expressible in terms of other operators. For example, subtraction is
-expressible in terms of addition and negation.
+expressible with other operators. For example, subtraction is
+expressible using addition and negation.
 \[
 \[
  \key{(-}\; e_1 \; e_2\key{)} \quad \Rightarrow \quad \LP\key{+} \; e_1 \; \LP\key{-} \; e_2\RP\RP
  \key{(-}\; e_1 \; e_2\key{)} \quad \Rightarrow \quad \LP\key{+} \; e_1 \; \LP\key{-} \; e_2\RP\RP
 \]
 \]
-Several of the comparison operations are expressible in terms of
-less-than and logical negation.
+Several of the comparison operations are expressible using less-than
+and logical negation.
 \[
 \[
 \LP\key{<=}\; e_1 \; e_2\RP \quad \Rightarrow \quad
 \LP\key{<=}\; e_1 \; e_2\RP \quad \Rightarrow \quad
 \LP\key{let}~\LP\LS\key{tmp.1}~e_1\RS\RP~\LP\key{not}\;\LP\key{<}\;e_2\;\key{tmp.1})\RP\RP
 \LP\key{let}~\LP\LS\key{tmp.1}~e_1\RS\RP~\LP\key{not}\;\LP\key{<}\;e_2\;\key{tmp.1})\RP\RP
@@ -4816,40 +4831,57 @@ less-than and logical negation.
 The \key{let} is needed in the above translation to ensure that
 The \key{let} is needed in the above translation to ensure that
 expression $e_1$ is evaluated before $e_2$.
 expression $e_1$ is evaluated before $e_2$.
 
 
-By performing these translations near the front-end of the compiler,
-the later passes of the compiler do not need to deal with these
-constructs, making those passes shorter. On the other hand, sometimes
-these translations make it more difficult to generate the most
-efficient code with respect to the number of instructions. However,
-these differences typically do not affect the number of accesses to
-memory, which is the primary factor that determines execution time on
-modern computer architectures.
+By performing these translations in the front-end of the compiler, the
+later passes of the compiler do not need to deal with these operators,
+making the passes shorter.
+
+%% On the other hand, sometimes
+%% these translations make it more difficult to generate the most
+%% efficient code with respect to the number of instructions. However,
+%% these differences typically do not affect the number of accesses to
+%% memory, which is the primary factor that determines execution time on
+%% modern computer architectures.
 
 
 \begin{exercise}\normalfont
 \begin{exercise}\normalfont
-  Implement the pass \code{shrink} that removes subtraction,
-  \key{and}, \key{or}, \key{<=}, \key{>}, and \key{>=} from the language
-  by translating them to other constructs in \LangIf{}.  Create tests to
-  make sure that the behavior of all of these constructs stays the
-  same after translation.
+Implement the pass \code{shrink} to remove subtraction, \key{and},
+\key{or}, \key{<=}, \key{>}, and \key{>=} from the language by
+translating them to other constructs in \LangIf{}.
+%
+Create six test programs that involve these operators.
+%
+In the \code{run-tests.rkt} script, add the following entry for
+\code{shrink} to the list of passes (it should be the only pass at
+this point).
+\begin{lstlisting}
+(list "shrink" shrink interp-Rif type-check-Rif)
+\end{lstlisting}
+This instructs \code{interp-tests} to run the intepreter
+\code{interp-Rif} and the type checker \code{type-check-Rif} on the
+output of \code{shrink}.
+%
+Run the script to test the \code{shrink} pass on all the test
+programs.
+
 \end{exercise}
 \end{exercise}
 
 
 \section{Remove Complex Operands}
 \section{Remove Complex Operands}
 \label{sec:remove-complex-opera-Rif}
 \label{sec:remove-complex-opera-Rif}
 
 
+The output language for this pass is \LangIfANF{}
+(Figure~\ref{fig:Rif-anf-syntax}), the administrative normal form of
+\LangIf{}.  The \code{Bool} form is an atomic expressions but
+\code{If} is not.  All three sub-expressions of an \code{If} are
+allowed to be complex expressions but the operands of \code{not} and
+the comparisons must be atoms.
+
 Add cases for \code{Bool} and \code{If} to the \code{rco-exp} and
 Add cases for \code{Bool} and \code{If} to the \code{rco-exp} and
-\code{rco-atom} functions according to the definition of the output
-language for this pass, \LangIfANF{}, the administrative normal
-form of \LangIf{}, which is defined in Figure~\ref{fig:Rif-anf-syntax}. The
-\code{Bool} form is an atomic expressions but \code{If} is not. All
-three sub-expressions of an \code{If} are allowed to be complex
-expressions in the output of \code{remove-complex-opera*}, but the
-operands of \code{not} and the comparisons must be atoms.  Regarding
-the \code{If} form, it is particularly important to \textbf{not}
+\code{rco-atom} functions according to whether the output needs to be
+\Exp{} or \Atm{} as specified in the grammar for \LangIfANF{}.
+Regarding \code{If}, it is particularly important to \textbf{not}
 replace its condition with a temporary variable because that would
 replace its condition with a temporary variable because that would
 interfere with the generation of high-quality output in the
 interfere with the generation of high-quality output in the
 \code{explicate-control} pass.
 \code{explicate-control} pass.
 
 
-
 \begin{figure}[tp]
 \begin{figure}[tp]
 \centering
 \centering
 \fbox{
 \fbox{
@@ -4877,7 +4909,7 @@ R^{\dagger}_2  &::=& \PROGRAM{\code{'()}}{\Exp}
 
 
 Recall that the purpose of \code{explicate-control} is to make the
 Recall that the purpose of \code{explicate-control} is to make the
 order of evaluation explicit in the syntax of the program.  With the
 order of evaluation explicit in the syntax of the program.  With the
-addition of \key{if} in \LangIf{} this get more interesting.
+addition of \key{if} this get more interesting.
 
 
 As a motivating example, consider the following program that has an
 As a motivating example, consider the following program that has an
 \key{if} expression nested in the predicate of another \key{if}.
 \key{if} expression nested in the predicate of another \key{if}.
@@ -4899,7 +4931,7 @@ handle each of them in isolation, regardless of their context.  Each
 comparison would be translated into a \key{cmpq} instruction followed
 comparison would be translated into a \key{cmpq} instruction followed
 by a couple instructions to move the result from the EFLAGS register
 by a couple instructions to move the result from the EFLAGS register
 into a general purpose register or stack location. Each \key{if} would
 into a general purpose register or stack location. Each \key{if} would
-be translated into the combination of a \key{cmpq} and a conditional
+be translated into a \key{cmpq} instruction followed by a conditional
 jump. The generated code for the inner \key{if} in the above example
 jump. The generated code for the inner \key{if} in the above example
 would be as follows.
 would be as follows.
 \begin{center}
 \begin{center}
@@ -4909,7 +4941,7 @@ would be as follows.
     cmpq $1, x          ;; (< x 1)
     cmpq $1, x          ;; (< x 1)
     setl %al
     setl %al
     movzbq %al, tmp
     movzbq %al, tmp
-    cmpq $1, tmp        ;; (if (< x 1) ...)
+    cmpq $1, tmp        ;; (if ...)
     je then_branch_1
     je then_branch_1
     jmp else_branch_1
     jmp else_branch_1
     ...
     ...
@@ -4917,11 +4949,26 @@ would be as follows.
 \end{minipage}
 \end{minipage}
 \end{center}
 \end{center}
 However, if we take context into account we can do better and reduce
 However, if we take context into account we can do better and reduce
-the use of \key{cmpq} and EFLAG-accessing instructions.
+the use of \key{cmpq} instructions for accessing the EFLAG register.
 
 
-One idea is to try and reorganize the code at the level of \LangIf{},
-pushing the outer \key{if} inside the inner one. This would yield the
-following code.
+Our goal will be compile \key{if} expressions so that the relevant
+comparison instruction appears directly before the conditional jump.
+For example, we want to generate the following code for the inner
+\code{if}.
+\begin{center}
+\begin{minipage}{0.96\textwidth}
+\begin{lstlisting}
+    ...
+    cmpq $1, x
+    je then_branch_1
+    jmp else_branch_1
+    ...
+\end{lstlisting}
+\end{minipage}
+\end{center}
+One way to achieve this is to reorganize the code at the level of
+\LangIf{}, pushing the outer \key{if} inside the inner one, yielding
+the following code.
 \begin{center}
 \begin{center}
 \begin{minipage}{0.96\textwidth}
 \begin{minipage}{0.96\textwidth}
 \begin{lstlisting}
 \begin{lstlisting}
@@ -4937,24 +4984,24 @@ following code.
 \end{lstlisting}
 \end{lstlisting}
 \end{minipage}
 \end{minipage}
 \end{center}
 \end{center}
-Unfortunately, this approach duplicates the two branches, and a
-compiler must never duplicate code!
+Unfortunately, this approach duplicates the two branches from the
+outer \code{if} and a compiler must never duplicate code!
 
 
-We need a way to perform the above transformation, but without
+We need a way to perform the above transformation but without
 duplicating code. That is, we need a way for different parts of a
 duplicating code. That is, we need a way for different parts of a
-program to refer to the same piece of code, that is, to \emph{share}
-code. At the level of x86 assembly this is straightforward because we
-can label the code for each of the branches and insert jumps in all
-the places that need to execute the branches. At the higher level of
-our intermediate languages, we need to move away from abstract syntax
-\emph{trees} and instead use \emph{graphs}. In particular, we use a
-standard program representation called a \emph{control flow graph}
-(CFG), due to Frances Elizabeth \citet{Allen:1970uq}.
-\index{control-flow graph} Each vertex is a labeled sequence of code,
-called a \emph{basic block}, and each edge represents a jump to
-another block. The \key{Program} construct of \LangCVar{} and \LangCIf{} contains
-a control flow graph represented as an alist mapping labels to basic
-blocks. Each basic block is represented by the $\Tail$ non-terminal.
+program to refer to the same piece of code. At the level of x86
+assembly this is straightforward because we can label the code for
+each branch and insert jumps in all the places that need to execute
+the branch. In our intermediate language, we need to move away from
+abstract syntax \emph{trees} and instead use \emph{graphs}. In
+particular, we use a standard program representation called a
+\emph{control flow graph} (CFG), due to Frances Elizabeth
+\citet{Allen:1970uq}.  \index{control-flow graph} Each vertex is a
+labeled sequence of code, called a \emph{basic block}, and each edge
+represents a jump to another block. The \key{CProgram} construct of
+\LangCVar{} and \LangCIf{} contains a control flow graph represented
+as an alist mapping labels to basic blocks. Each basic block is
+represented by the $\Tail$ non-terminal.
 
 
 Figure~\ref{fig:explicate-control-s1-38} shows the output of the
 Figure~\ref{fig:explicate-control-s1-38} shows the output of the
 \code{remove-complex-opera*} pass and then the
 \code{remove-complex-opera*} pass and then the
@@ -4963,18 +5010,17 @@ the output program and then discuss the algorithm.
 %
 %
 Following the order of evaluation in the output of
 Following the order of evaluation in the output of
 \code{remove-complex-opera*}, we first have two calls to \code{(read)}
 \code{remove-complex-opera*}, we first have two calls to \code{(read)}
-and then the less-than-comparison to \code{1} in the predicate of the
+and then the comparison \lstinline{(< x 1)} in the predicate of the
 inner \key{if}.  In the output of \code{explicate-control}, in the
 inner \key{if}.  In the output of \code{explicate-control}, in the
-block labeled \code{start}, this becomes two assignment statements
-followed by a conditional \key{goto} to label \code{block40} or
+block labeled \code{start}, is two assignment statements followed by a
+\code{if} statement that branches to \code{block40} or
 \code{block41}. The blocks associated with those labels contain the
 \code{block41}. The blocks associated with those labels contain the
-translations of the code \code{(eq? x 0)} and \code{(eq? x 2)},
-respectively. Regarding the block labeled with \code{block40}, we
-start with the comparison to \code{0} and then have a conditional
-goto, either to label \code{block38} or label \code{block39}, which
-are the two branches of the outer \key{if}, i.e., \code{(+ y 2)} and
-\code{(+ y 10)}. The story for the block labeled \code{block41} is
-similar.
+translations of the code \lstinline{(eq? x 0)} and \lstinline{(eq? x 2)},
+respectively.  In particular, we start \code{block40} with the
+comparison \lstinline{(eq? x 0)} and then branch to \code{block38} or
+\code{block39}, the two branches of the outer \key{if}, i.e.,
+\lstinline{(+ y 2)} and \lstinline{(+ y 10)}. The story for
+\code{block41} is similar.
 
 
 \begin{figure}[tbp]
 \begin{figure}[tbp]
 \begin{tabular}{lll}
 \begin{tabular}{lll}
@@ -5008,20 +5054,14 @@ $\Rightarrow$
 start:
 start:
     x = (read);
     x = (read);
     y = (read);
     y = (read);
-    if (< x 1)
-       goto block40;
-    else
-       goto block41;
+    if (< x 1) goto block40;
+    else goto block41;
 block40:
 block40:
-    if (eq? x 0)
-       goto block38;
-    else
-       goto block39;
+    if (eq? x 0) goto block38;
+    else goto block39;
 block41:
 block41:
-    if (eq? x 2)
-       goto block38;
-    else
-       goto block39;
+    if (eq? x 2) goto block38;
+    else goto block39;
 block38:
 block38:
     return (+ y 2);
     return (+ y 2);
 block39:
 block39:
@@ -5049,10 +5089,10 @@ Recall that in Section~\ref{sec:explicate-control-r1} we implement
 functions, \code{explicate-tail} and \code{explicate-assign}.  The
 functions, \code{explicate-tail} and \code{explicate-assign}.  The
 former function translates expressions in tail position whereas the
 former function translates expressions in tail position whereas the
 later function translates expressions on the right-hand-side of a
 later function translates expressions on the right-hand-side of a
-\key{let}. With the addition of \key{if} expression in \LangIf{} we have a
-new kind of context to deal with: the predicate position of the
-\key{if}. We need another function, \code{explicate-pred}, that takes
-an \LangIf{} expression and two blocks for the then-branch and
+\key{let}. With the addition of \key{if} expression in \LangIf{} we
+have a new kind of position to deal with: the predicate position of
+the \key{if}. We need another function, \code{explicate-pred}, that
+takes an \LangIf{} expression and two blocks for the then-branch and
 else-branch. The output of \code{explicate-pred} is a block.
 else-branch. The output of \code{explicate-pred} is a block.
 %
 %
 %% Note that the three explicate functions need to construct a
 %% Note that the three explicate functions need to construct a
@@ -5060,15 +5100,14 @@ else-branch. The output of \code{explicate-pred} is a block.
 %% variable.
 %% variable.
 %
 %
 In the following paragraphs we discuss specific cases in the
 In the following paragraphs we discuss specific cases in the
-\code{explicate-pred} function as well as the additions to the
+\code{explicate-pred} function as well as additions to the
 \code{explicate-tail} and \code{explicate-assign} functions.
 \code{explicate-tail} and \code{explicate-assign} functions.
 
 
 The function \code{explicate-pred} will need a case for every
 The function \code{explicate-pred} will need a case for every
 expression that can have type \code{Boolean}. We detail a few cases
 expression that can have type \code{Boolean}. We detail a few cases
 here and leave the rest for the reader. The input to this function is
 here and leave the rest for the reader. The input to this function is
 an expression and two blocks, $B_1$ and $B_2$, for the two branches of
 an expression and two blocks, $B_1$ and $B_2$, for the two branches of
-the enclosing \key{if}, though some care will be needed regarding how
-we represent the blocks. Suppose the expression is the Boolean
+the enclosing \key{if}. Suppose the expression is the Boolean
 \code{\#t}.  Then we can perform a kind of partial evaluation
 \code{\#t}.  Then we can perform a kind of partial evaluation
 \index{partial evaluation} and translate it to the ``then'' branch
 \index{partial evaluation} and translate it to the ``then'' branch
 $B_1$. Likewise, we translate \code{\#f} to the ``else`` branch $B_2$.
 $B_1$. Likewise, we translate \code{\#f} to the ``else`` branch $B_2$.
@@ -5078,30 +5117,31 @@ $B_1$. Likewise, we translate \code{\#f} to the ``else`` branch $B_2$.
 \key{\#f} \quad\Rightarrow\quad B_2
 \key{\#f} \quad\Rightarrow\quad B_2
 \]
 \]
 These two cases demonstrate that we sometimes discard one of the
 These two cases demonstrate that we sometimes discard one of the
-blocks that are input to \code{explicate-pred}. We will need to
-arrange for the blocks that we actually use to appear in the resulting
-control-flow graph, but not the discarded blocks.
+blocks that are input to \code{explicate-pred}. We want the blocks
+that we actually use to appear in the resulting control-flow graph,
+but not the discarded blocks. We return to this issue later.
 
 
 The case for \key{if} in \code{explicate-pred} is particularly
 The case for \key{if} in \code{explicate-pred} is particularly
-illuminating as it deals with the challenges that we discussed above
+illuminating because it deals with the challenges we discussed above
 regarding the example of the nested \key{if} expressions.  The
 regarding the example of the nested \key{if} expressions.  The
 ``then'' and ``else'' branches of the current \key{if} inherit their
 ``then'' and ``else'' branches of the current \key{if} inherit their
 context from the current one, that is, predicate context. So we
 context from the current one, that is, predicate context. So we
 recursively apply \code{explicate-pred} to the ``then'' and ``else''
 recursively apply \code{explicate-pred} to the ``then'' and ``else''
-branches. For both of those recursive calls, we shall pass the blocks
-$B_1$ and $B_2$. Thus, $B_1$ may get used twice, once inside each
-recursive call, and likewise for $B_2$. As discussed above, to avoid
-duplicating code, we need to add these blocks to the control-flow
-graph so that we can instead refer to them by name and execute them
-with a \key{goto}. However, as we saw in the cases above for \key{\#t}
-and \key{\#f}, the blocks $B_1$ or $B_2$ may not get used at all and
-we don't want to prematurely add them to the control-flow graph if
-they end up being discarded.
-
-The solution to this conundrum is to use \emph{lazy evaluation} to
-delay adding the blocks to the control-flow graph until the points
-where we know they will be used~\citep{Friedman:1976aa}.\index{lazy
-  evaluation} Racket provides support for lazy evaluation with the
+branches. For both of those recursive calls, we pass the blocks $B_1$
+and $B_2$. Thus, $B_1$ may get used twice, once inside each recursive
+call, and likewise for $B_2$. As discussed above, to avoid duplicating
+code, we need to add these blocks to the control-flow graph so that we
+can instead refer to them by name and execute them with a
+\key{goto}. However, as we saw in the cases above for \key{\#t} and
+\key{\#f}, the blocks $B_1$ or $B_2$ may not get used at all and we
+don't want to prematurely add them to the control-flow graph if they
+end up being discarded.
+
+The solution to this conundrum is to use \emph{lazy
+  evaluation}\index{lazy evaluation} \citep{Friedman:1976aa} to delay
+adding the blocks to the control-flow graph until the points where we
+know they will be used. Racket provides support for lazy evaluation
+with the
 \href{https://docs.racket-lang.org/reference/Delayed_Evaluation.html}{\code{racket/promise}}
 \href{https://docs.racket-lang.org/reference/Delayed_Evaluation.html}{\code{racket/promise}}
 package. The expression \key{(delay} $e_1 \ldots e_n$\key{)}
 package. The expression \key{(delay} $e_1 \ldots e_n$\key{)}
 \index{delay} creates a \emph{promise}\index{promise} in which the
 \index{delay} creates a \emph{promise}\index{promise} in which the