Jeremy Siek 4 лет назад
Родитель
Сommit
3e015e62e0
1 измененных файлов с 257 добавлено и 193 удалено
  1. 257 193
      book.tex

+ 257 - 193
book.tex

@@ -1331,7 +1331,7 @@ extensible way.
 Having justified the use of classes and methods to implement
 interpreters, we turn to the definitional interpreter for \LangVar{}
 in Figure~\ref{fig:interp-Rvar}. It is similar to the interpreter for
-\LangInt{} but adds two new \key{match} clauses for variables and
+\LangInt{} but adds two new \key{match} cases for variables and
 \key{let}.  For \key{let} we need a way to communicate the value bound
 to a variable to all the uses of the variable. To accomplish this, we
 maintain a mapping from variables to values. Throughout the compiler
@@ -1973,8 +1973,8 @@ for the alist.
 The skeleton of the \code{uniquify-exp} function is shown in
 Figure~\ref{fig:uniquify-Rvar}.  The function is curried so that it is
 convenient to partially apply it to an alist and then apply it to
-different expressions, as in the last clause for primitive operations
-in Figure~\ref{fig:uniquify-Rvar}.  The
+different expressions, as in the last case for primitive operations in
+Figure~\ref{fig:uniquify-Rvar}.  The
 %
 \href{https://docs.racket-lang.org/reference/for.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._for%2Flist%29%29}{\key{for/list}}
 %
@@ -1985,7 +1985,7 @@ produce a new list.\index{for/list}
 \normalfont % I don't like the italics for exercises. -Jeremy
 
 Complete the \code{uniquify} pass by filling in the blanks in
-Figure~\ref{fig:uniquify-Rvar}, that is, implement the clauses for
+Figure~\ref{fig:uniquify-Rvar}, that is, implement the cases for
 variables and for the \key{let} form in the file \code{compiler.rkt}
 in the support code.
 \end{exercise}
@@ -2012,17 +2012,29 @@ in the support code.
 \begin{exercise}
 \normalfont % I don't like the italics for exercises. -Jeremy
 
-Creating five \LangVar{} programs to test the most interesting parts
-of the \key{uniquify} pass, that is, the programs should include
+Create five \LangVar{} programs that exercise the most interesting
+parts of the \key{uniquify} pass, that is, the programs should include
 \key{let} forms, variables, and variables that overshadow each other.
 The five programs should be placed in the subdirectory named
 \key{tests} and the file names should start with \code{var\_test\_}
 followed by a unique integer and end with the file extension
-\key{.rkt}. Run the \key{run-tests.rkt} script in the support code to
-check whether the output programs produce the same result as the input
-programs. The script uses the \key{interp-tests} function
+\key{.rkt}.
+%
+The \key{run-tests.rkt} script in the support code checks whether the
+output programs produce the same result as the input programs.  The
+script uses the \key{interp-tests} function
 (Appendix~\ref{appendix:utilities}) from \key{utilities.rkt} to test
-your \key{uniquify} pass on the example programs.
+your \key{uniquify} pass on the example programs.  The \code{passes}
+parameter of \key{interp-tests} is a list that should have one entry
+for each pass in your compiler.  For now, define \code{passes} to
+contain just one entry for \code{uniquify} as follows.
+\begin{lstlisting}
+(define passes 
+  (list (list "uniquify" uniquify interp-Rvar type-check-Rvar)))
+\end{lstlisting}
+Run the \key{run-tests.rkt} script in the support code to check
+whether the output programs produce the same result as the input
+programs.
 \end{exercise}
 
 
@@ -2040,7 +2052,7 @@ operand, as shown in the output of \code{remove-complex-opera*} on the
 right.\\
 \begin{tabular}{lll}
 \begin{minipage}{0.4\textwidth}
-% s0_19.rkt
+% var_test_19.rkt
 \begin{lstlisting}
 (+ 52 (- 10))
 \end{lstlisting}
@@ -2126,7 +2138,7 @@ variable to an atomic expression. You should leave such variable
 bindings unchanged, as shown in to the program on the right \\
 \begin{tabular}{lll}
 \begin{minipage}{0.4\textwidth}
-% s0_20.rkt
+% var_test_20.rkt
 \begin{lstlisting}
 (let ([a 42])
   (let ([b a])
@@ -2156,14 +2168,20 @@ produce the following output with unnecessary temporary variables.\\
 \end{lstlisting}
 \end{minipage}
 
-\begin{exercise}
-  \normalfont Implement the \code{remove-complex-opera*} in
-  \code{compiler.rkt}.  Create three new \LangInt{} programs that are
-  designed to exercise the interesting code in the
-  \code{remove-complex-opera*} pass (Following the same file name
-  guidelines as before.). In the \code{run-tests.rkt} script,
-  uncomment the line for this pass in the list of \code{passes} and
-  then run the script to test your compiler.
+\begin{exercise}\normalfont
+%
+Implement the \code{remove-complex-opera*} function in
+\code{compiler.rkt}.
+%
+Create three new \LangInt{} programs that exercise the interesting
+code in the \code{remove-complex-opera*} pass (Following the same file
+name guidelines as before.).
+%
+In the \code{run-tests.rkt} script, add the following entry to the
+list of \code{passes} and then run the script to test your compiler.
+\begin{lstlisting}
+(list "remove complex" remove-complex-opera* interp-Rvar type-check-Rvar)
+\end{lstlisting}
 \end{exercise}
 
 
@@ -2175,7 +2193,7 @@ programs that make the order of execution explicit in their
 syntax. For now this amounts to flattening \key{let} constructs into a
 sequence of assignment statements. For example, consider the following
 \LangVar{} program.\\
-% s0_11.rkt
+% var_test_11.rkt
 \begin{minipage}{0.96\textwidth}
 \begin{lstlisting}
 (let ([y (let ([x 20])
@@ -2274,6 +2292,18 @@ statements. We warn against that alternative because the
 accumulator-passing style is key to how we generate high-quality code
 for conditional expressions in Chapter~\ref{ch:bool-types}.
 
+\begin{exercise}\normalfont
+%
+Implement the \code{explicate-control} function in
+\code{compiler.rkt}.  Create three new \LangInt{} programs that
+exercise the code in \code{explicate-control}.
+%
+In the \code{run-tests.rkt} script, add the following entry to the
+list of \code{passes} and then run the script to test your compiler.
+\begin{lstlisting}
+(list "explicate control" explicate-control interp-Cvar type-check-Cvar)  
+\end{lstlisting}
+\end{exercise}
 
 \section{Select Instructions}
 \label{sec:select-r1}
@@ -2376,10 +2406,13 @@ recursively and then append the resulting instructions.
 \begin{exercise}
 \normalfont Implement the \key{select-instructions} pass in
 \code{compiler.rkt}. Create three new example programs that are
-designed to exercise all of the interesting cases in this pass.  In
-the \code{run-tests.rkt} script, uncomment the line for this pass in
-the list of \code{passes} and then run the script to test your
-compiler.
+designed to exercise all of the interesting cases in this pass.
+%
+In the \code{run-tests.rkt} script, add the following entry to the
+list of \code{passes} and then run the script to test your compiler.
+\begin{lstlisting}
+(list "instruction selection" select-instructions interp-pseudo-x86-0)
+\end{lstlisting}
 \end{exercise}
 
 
@@ -2399,7 +2432,7 @@ Chapter~\ref{ch:register-allocation-r1}.
 
 Consider again the following \LangVar{} program from
 Section~\ref{sec:remove-complex-opera-Rvar}.
-% s0_20.rkt
+% var_test_20.rkt
 \begin{lstlisting}
 (let ([a 42])
   (let ([b a])
@@ -2455,9 +2488,13 @@ Implement the \key{assign-homes} pass in \code{compiler.rkt}, defining
 auxiliary functions for the non-terminals \Arg{}, \Instr{}, and
 \Block{}.  We recommend that the auxiliary functions take an extra
 parameter that is an alist mapping variable names to homes (stack
-locations for now).  In the \code{run-tests.rkt} script, uncomment the
-line for this pass in the list of \code{passes} and then run the
-script to test your compiler.
+locations for now).
+%
+In the \code{run-tests.rkt} script, add the following entry to the
+list of \code{passes} and then run the script to test your compiler.
+\begin{lstlisting}
+(list "assign homes" assign-homes interp-x86-0)
+\end{lstlisting}
 \end{exercise}
 
 
@@ -2470,7 +2507,7 @@ restriction that at most one argument of an instruction may be a
 memory reference.
 
 We return to the following example.
-% s0_20.rkt
+% var_test_20.rkt
 \begin{lstlisting}
    (let ([a 42])
      (let ([b a])
@@ -2500,10 +2537,13 @@ from \key{rax} to the destination location, as follows.
 \begin{exercise}
 \normalfont Implement the \key{patch-instructions} pass in
 \code{compiler.rkt}. Create three new example programs that are
-designed to exercise all of the interesting cases in this pass.  In
-the \code{run-tests.rkt} script, uncomment the line for this pass in
-the list of \code{passes} and then run the script to test your
-compiler.
+designed to exercise all of the interesting cases in this pass.
+%
+In the \code{run-tests.rkt} script, add the following entry to the
+list of \code{passes} and then run the script to test your compiler.
+\begin{lstlisting}
+(list "patch instructions" patch-instructions interp-x86-0)
+\end{lstlisting}
 \end{exercise}
 
 
@@ -2527,15 +2567,21 @@ labels like \key{main}. The Racket call \code{(system-type 'os)} is
 useful for determining which operating system the compiler is running
 on. It returns \code{'macosx}, \code{'unix}, or \code{'windows}.
 
-\begin{exercise}
-  \normalfont Implement the \key{print-x86} pass in
-  \code{compiler.rkt}. Uncomment the line for this pass in the list of
-  \code{passes} in the \code{run-tests.rkt} script. Also uncomment the
-  call to the \key{compiler-tests} function
-  (Appendix~\ref{appendix:utilities}), which tests your complete
-  compiler by executing the generated x86 code. Compile the provided
-  \key{runtime.c} file to \key{runtime.o} using \key{gcc}. Run the
-  script to test your compiler.
+\begin{exercise}\normalfont
+%
+Implement the \key{print-x86} pass in \code{compiler.rkt}.
+%
+In the \code{run-tests.rkt} script, add the following entry to the
+list of \code{passes} and then run the script to test your compiler.
+\begin{lstlisting}
+(list "print x86" print-x86 #f)
+\end{lstlisting}
+%  
+Uncomment the call to the \key{compiler-tests} function
+(Appendix~\ref{appendix:utilities}), which tests your complete
+compiler by executing the generated x86 code. Compile the provided
+\key{runtime.c} file to \key{runtime.o} using \key{gcc}. Run the
+script to test your compiler.
 \end{exercise}
 
 
@@ -2614,7 +2660,7 @@ in the x86 assembly language but it still uses variables.
 \begin{figure}
 \begin{minipage}{0.45\textwidth}
 Example \LangVar{} program:
-% s0_28.rkt
+% var_test_28.rkt
 \begin{lstlisting}
 (let ([v 1])
   (let ([w 42])
@@ -2818,7 +2864,7 @@ instruction.  \index{prelude}\index{conclusion}
 \begin{figure}[tp]
 \begin{minipage}{0.45\textwidth}
 Example \LangVar{} program:
-%s0_14.rkt
+%var_test_14.rkt
 \begin{lstlisting}
 (let ([x (read)])
   (let ([y (read)])
@@ -4173,7 +4219,7 @@ done in the prelude. We move the stack pointer up by \code{8} bytes
 
   
 \begin{figure}[tbp]
-  % s0_28.rkt
+  % var_test_28.rkt
   % (use-minimal-set-of-registers! #t)
   % and only rbx rcx
 % tmp 0 rbx
@@ -4359,7 +4405,7 @@ evaluated if $e_1$ evaluates to \code{\#f}.
 
 With the increase in the number of primitive operations, the
 interpreter would become repetitive without some care.  We refactor
-the clause for \code{Prim}, moving the code that differs with each
+the case for \code{Prim}, moving the code that differs with each
 operation into the \code{interp-op} method shown in in
 Figure~\ref{fig:interp-op-Rif}. We handle the \code{and} operation
 separately because of its short-circuiting behavior.
@@ -4479,10 +4525,10 @@ error or returns an expression and its type (\key{Integer} or
 \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
+Next we discuss the \code{match} cases 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
+environment \code{env} to map variables to types. Consider the case
 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
@@ -4892,9 +4938,9 @@ interfere with the generation of high-quality output in the
 \Exp &::=& \gray{ \Atm \mid \READ{} } \\
      &\mid& \gray{ \NEG{\Atm} \mid \ADD{\Atm}{\Atm} } \\
      &\mid& \gray{ \LET{\Var}{\Exp}{\Exp} } \\
-     &\mid& \UNIOP{\key{'not}}{\Atm} \\
+     &\mid& \UNIOP{\key{not}}{\Atm} \\
       &\mid& \BINOP{\itm{cmp}}{\Atm}{\Atm} \mid \IF{\Exp}{\Exp}{\Exp} \\
-R^{\dagger}_2  &::=& \PROGRAM{\code{'()}}{\Exp}
+R^{\dagger}_2  &::=& \PROGRAM{\code{()}}{\Exp}
 \end{array}
 \]
 \end{minipage}
@@ -4913,7 +4959,7 @@ addition of \key{if} this get more interesting.
 
 As a motivating example, consider the following program that has an
 \key{if} expression nested in the predicate of another \key{if}.
-% s1_41.rkt
+% cond_test_41.rkt
 \begin{center}
 \begin{minipage}{0.96\textwidth}
 \begin{lstlisting}
@@ -5025,7 +5071,7 @@ comparison \lstinline{(eq? x 0)} and then branch to \code{block38} or
 \begin{figure}[tbp]
 \begin{tabular}{lll}
 \begin{minipage}{0.4\textwidth}
-% s1_41.rkt
+% cond_test_41.rkt
 \begin{lstlisting}
 (let ([x (read)])
    (let ([y (read)])
@@ -5095,50 +5141,61 @@ 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.
 %
-%% Note that the three explicate functions need to construct a
-%% control-flow graph, which we recommend they do via updates to a global
-%% variable.
-%
 In the following paragraphs we discuss specific cases in the
 \code{explicate-pred} function as well as additions to the
 \code{explicate-tail} and \code{explicate-assign} functions.
 
-The function \code{explicate-pred} will need a case for every
-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
-an expression and two blocks, $B_1$ and $B_2$, for the two branches of
-the enclosing \key{if}. Suppose the expression is the Boolean
-\code{\#t}.  Then we can perform a kind of partial evaluation
-\index{partial evaluation} and translate it to the ``then'' branch
-$B_1$. Likewise, we translate \code{\#f} to the ``else`` branch $B_2$.
-\[
-\key{\#t} \quad\Rightarrow\quad B_1,
-\qquad\qquad\qquad
-\key{\#f} \quad\Rightarrow\quad B_2
-\]
-These two cases demonstrate that we sometimes discard one of the
-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.
+\begin{figure}[tbp]
+\begin{lstlisting}
+(define (explicate-pred cnd thn els)
+  (match cnd
+    [(Var x) ___]
+    [(Let x rhs body) ___]
+    [(Prim 'not (list e)) ___]
+    [(Prim op es) #:when (or (eq? op 'eq?) (eq? op '<))
+     (IfStmt (Prim op arg*) (force (block->goto thn))
+              (force (block->goto els)))]
+    [(Bool b) (if b thn els)]
+    [(If cnd^ thn^ els^) ___]
+    [else (error "explicate-pred unhandled case" cnd)]))
+\end{lstlisting}
+\caption{Skeleton for the \key{explicate-pred} auxiliary function.}
+\label{fig:explicate-pred}
+\end{figure}
+
+The skeleton for the \code{explicate-pred} function is given in
+Figure~\ref{fig:explicate-pred}. It has a case for every 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 an
+expression and two blocks, \code{thn} and \code{els}, for the two
+branches of the enclosing \key{if}.
+%
+Consider the case for Boolean constants in
+Figure~\ref{fig:explicate-pred}.  We perform a kind of partial
+evaluation\index{partial evaluation} and output either the \code{thn}
+or \code{els} branch depending on whether the constant is true or
+false. This case demonstrates that we sometimes discard the \code{thn}
+or \code{els} blocks that are input to \code{explicate-pred}.
 
 The case for \key{if} in \code{explicate-pred} is particularly
 illuminating because it deals with the challenges we discussed above
-regarding the example of the nested \key{if} expressions.  The
-``then'' and ``else'' branches of the current \key{if} inherit their
-context from the current one, that is, predicate context. So we
-recursively apply \code{explicate-pred} to the ``then'' and ``else''
-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.
+regarding nested \key{if} expressions
+(Figure~\ref{fig:explicate-control-s1-38}).  The \lstinline{thn^} and
+\lstinline{els^} branches of the \key{if} inherit their context from
+the current one, that is, predicate context. So you should recursively
+apply \code{explicate-pred} to the \lstinline{thn^} and
+\lstinline{els^} branches. For both of those recursive calls, pass
+\code{thn} and \code{els} as the extra parameters. Thus, \code{thn}
+and \code{els} may get used twice, once inside each recursive call. As
+discussed above, to avoid duplicating code, we need to add them 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 Boolean constants, the blocks \code{thn} and \code{els} 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
+  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
@@ -5150,21 +5207,24 @@ $p$\key{)}\index{force} is applied to a promise $p$ for the first
 time, the expressions $e_1 \ldots e_n$ are evaluated and the result of
 $e_n$ is cached in the promise and returned. If \code{force} is
 applied again to the same promise, then the cached result is returned.
+If \code{force} is applied to an argument that is not a promise,
+\code{force} simply returns the argument.
 
 We use lazy evaluation for the input and output blocks of the
 functions \code{explicate-pred} and \code{explicate-assign} and for
 the output block of \code{explicate-tail}. So instead of taking and
-returning blocks, they take and return promised blocks. Furthermore,
-when we come to a situation in which we a block might be used more
-than once, as in the case for \code{if} above, we transform the
-promise into a new promise that will add the block to the control-flow
-graph and return a \code{goto}.  The following auxiliary function
-accomplishes this task. It begins with \code{delay} to create a
-promise. When forced, this promise will force the input block. If that
-block is already a \code{goto} (because it was already added to the
-control-flow graph), then we return that \code{goto}. Otherwise we add
-the block to the control-flow graph with another auxiliary function
-named \code{add-node} that returns the new label, and then return the
+returning blocks, they take and return promises. Furthermore, when we
+come to a situation in which we a block might be used more than once,
+as in the case for \code{if} in \code{explicate-pred}, we transform
+the promise into a new promise that will add the block to the
+control-flow graph and return a \code{goto}.  The following auxiliary
+function named \code{block->goto} accomplishes this task. It begins
+with \code{delay} to create a promise. When forced, this promise will
+force the original promise. If that returns a \code{goto} (because the
+block was already added to the control-flow graph), then we return the
+\code{goto}. Otherwise we add the block to the control-flow graph with
+another auxiliary function named \code{add-node}. That function
+returns the label for the new block, which we use to create a
 \code{goto}.
 \begin{lstlisting}
 (define (block->goto block)
@@ -5172,63 +5232,60 @@ named \code{add-node} that returns the new label, and then return the
     (define b (force block))
     (match b
       [(Goto label) (Goto label)]
-      [else (Goto (add-node b))]
-      )))
-\end{lstlisting}
-
-Getting back to the case for \code{if} in \code{explicate-pred}, we
-make the recursive calls to \code{explicate-pred} on the ``then'' and
-``else'' branches with the arguments \code{(block->goto} $B_1$\code{)}
-and \code{(block->goto} $B_2$\code{)}. Let $B_3$ and $B_4$ be the
-results from the two recursive calls.  We complete the case for
-\code{if} by recursively apply \code{explicate-pred} to the condition
-of the \code{if} with the promised blocks $B_3$ and $B_4$ to obtain
-the result $B_5$.
-\[
-(\key{if}\; \itm{cnd}\; \itm{thn}\; \itm{els})
-\quad\Rightarrow\quad
-B_5
-\]
-
-Next, consider the case for a less-than comparison in
-\code{explicate-pred}. We translate it to an \code{if} statement,
-whose two branches are required to be \code{goto}'s.  So we apply
-\code{block->goto} to $B_1$ and $B_2$ to obtain two promised goto's,
-which we can \code{force} to obtain the two actual goto's $G_1$ and
-$G_2$. The translation of the less-than comparison is as follows.
-\[
-(\key{<}~e_1~e_2) \quad\Rightarrow\quad
-\begin{array}{l}
-\key{if}~(\key{<}~e_1~e_2) \; G_1\\
-\key{else} \; G_2
-\end{array}
-\]
+      [else (Goto (add-node b))])))
+\end{lstlisting}
+
+Returning to the discussion of \code{explicate-pred}
+(Figure~\ref{fig:explicate-pred}), consider the case for comparison
+operators. This is one of the base cases of the recursive function so
+we translate the comparison to an \code{if} statement. We apply
+\code{block->goto} to \code{thn} and \code{els} to obtain two promises
+that will add then to the control-flow graph, which we can immediately
+\code{force} to obtain the two goto's that form the branches of the
+\code{if} statement.
+
+%% Getting back to the case for \code{if} in \code{explicate-pred}, we
+%% make the recursive calls to \code{explicate-pred} on the ``then'' and
+%% ``else'' branches with the arguments \code{(block->goto} $B_1$\code{)}
+%% and \code{(block->goto} $B_2$\code{)}. Let $B_3$ and $B_4$ be the
+%% results from the two recursive calls.  We complete the case for
+%% \code{if} by recursively apply \code{explicate-pred} to the condition
+%% of the \code{if} with the promised blocks $B_3$ and $B_4$ to obtain
+%% the result $B_5$.
+%% \[
+%% (\key{if}\; \itm{cnd}\; \itm{thn}\; \itm{els})
+%% \quad\Rightarrow\quad
+%% B_5
+%% \]
+
+The \code{explicate-tail} and \code{explicate-assign} functions need
+additional cases for Boolean constants and \key{if}.
+%
+In the cases for \code{if}, the two branches inherit the current
+context, so in \code{explicate-tail} they are in tail position and in
+\code{explicate-assign} they are in assignment position. The
+\code{cont} parameter of \code{explicate-assign} is used in both
+recursive calls, so make sure to use \code{block->goto} on it.
+
+%% In the case for \code{if} in \code{explicate-tail}, the two branches
+%% inherit the current context, so they are in tail position. Thus, the
+%% recursive calls on the ``then'' and ``else'' branch should be calls to
+%% \code{explicate-tail}.
+%% %
+%% We need to pass $B_0$ as the accumulator argument for both of these
+%% recursive calls, but we need to be careful not to duplicate $B_0$.
+%% Thus, we first apply \code{block->goto} to $B_0$ so that it gets added
+%% to the control-flow graph and obtain a promised goto $G_0$.
+%% %
+%% Let $B_1$ be the result of \code{explicate-tail} on the ``then''
+%% branch and $G_0$ and let $B_2$ be the result of \code{explicate-tail}
+%% on the ``else'' branch and $G_0$.  Let $B_3$ be the result of applying
+%% \code{explicate-pred} to the condition of the \key{if}, $B_1$, and
+%% $B_2$.  Then the \key{if} as a whole translates to promise $B_3$.
+%% \[
+%%     (\key{if}\; \itm{cnd}\; \itm{thn}\; \itm{els}) \quad\Rightarrow\quad B_3
+%% \]
 
-The \code{explicate-tail} function needs to be updated to use lazy
-evaluation and it needs an additional case for \key{if}.  Each of the
-cases that return an AST node need use \code{delay} to instead return
-a promise of an AST node. Recall that \code{explicate-tail} has an
-accumulator parameter that is a block, which now becomes a promise of
-a block, which we refer to as $B_0$.
-
-In the case for \code{if} in \code{explicate-tail}, the two branches
-inherit the current context, so they are in tail position. Thus, the
-recursive calls on the ``then'' and ``else'' branch should be calls to
-\code{explicate-tail}.
-%
-We need to pass $B_0$ as the accumulator argument for both of these
-recursive calls, but we need to be careful not to duplicate $B_0$.
-Thus, we first apply \code{block->goto} to $B_0$ so that it gets added
-to the control-flow graph and obtain a promised goto $G_0$.
-%
-Let $B_1$ be the result of \code{explicate-tail} on the ``then''
-branch and $G_0$ and let $B_2$ be the result of \code{explicate-tail}
-on the ``else'' branch and $G_0$.  Let $B_3$ be the result of applying
-\code{explicate-pred} to the condition of the \key{if}, $B_1$, and
-$B_2$.  Then the \key{if} as a whole translates to promise $B_3$.
-\[
-    (\key{if}\; \itm{cnd}\; \itm{thn}\; \itm{els}) \quad\Rightarrow\quad B_3
-\]
 %% In the above discussion, we use the metavariables $B_1$, $B_2$, and
 %% $B_3$ to refer to blocks for the purposes of our discussion, but they
 %% should not be confused with the labels for the blocks that appear in
@@ -5236,30 +5293,31 @@ $B_2$.  Then the \key{if} as a whole translates to promise $B_3$.
 %% attach labels to blocks when we add them to the control-flow graph, as
 %% we see in the next case.
 
-Next consider the case for \key{if} in the \code{explicate-assign}
-function. The context of the \key{if} is an assignment to some
-variable $x$ and then the control continues to some promised block
-$B_1$.  The code that we generate for both the ``then'' and ``else''
-branches needs to continue to $B_1$, so to avoid duplicating $B_1$ we
-apply \code{block->goto} to it and obtain a promised goto $G_1$.  The
-branches of the \key{if} inherit the current context, so they are in
-assignment positions.  Let $B_2$ be the result of applying
-\code{explicate-assign} to the ``then'' branch, variable $x$, and
-$G_1$.  Let $B_3$ be the result of applying \code{explicate-assign} to
-the ``else'' branch, variable $x$, and $G_1$. Finally, let $B_4$ be
-the result of applying \code{explicate-pred} to the predicate
-$\itm{cnd}$ and the promises $B_2$ and $B_3$. The \key{if} as a whole
-translates to the promise $B_4$.
-\[
-(\key{if}\; \itm{cnd}\; \itm{thn}\; \itm{els}) \quad\Rightarrow\quad B_4
-\]
-This completes the description of \code{explicate-control} for \LangIf{}.
+%% Next consider the case for \key{if} in the \code{explicate-assign}
+%% function. The context of the \key{if} is an assignment to some
+%% variable $x$ and then the control continues to some promised block
+%% $B_1$.  The code that we generate for both the ``then'' and ``else''
+%% branches needs to continue to $B_1$, so to avoid duplicating $B_1$ we
+%% apply \code{block->goto} to it and obtain a promised goto $G_1$.  The
+%% branches of the \key{if} inherit the current context, so they are in
+%% assignment positions.  Let $B_2$ be the result of applying
+%% \code{explicate-assign} to the ``then'' branch, variable $x$, and
+%% $G_1$.  Let $B_3$ be the result of applying \code{explicate-assign} to
+%% the ``else'' branch, variable $x$, and $G_1$. Finally, let $B_4$ be
+%% the result of applying \code{explicate-pred} to the predicate
+%% $\itm{cnd}$ and the promises $B_2$ and $B_3$. The \key{if} as a whole
+%% translates to the promise $B_4$.
+%% \[
+%% (\key{if}\; \itm{cnd}\; \itm{thn}\; \itm{els}) \quad\Rightarrow\quad B_4
+%% \]
+%% This completes the description of \code{explicate-control} for \LangIf{}.
+
 
 The way in which the \code{shrink} pass transforms logical operations
 such as \code{and} and \code{or} can impact the quality of code
 generated by \code{explicate-control}. For example, consider the
 following program.
-% s1_21.rkt
+% cond_test_21.rkt
 \begin{lstlisting}
 (if (and (eq? (read) 0) (eq? (read) 1))
     0
@@ -5274,16 +5332,12 @@ following for the above program.
 \begin{lstlisting}
 start:
     tmp1 = (read);
-    if (eq? tmp1 0)
-       goto block40;
-    else
-       goto block39;
+    if (eq? tmp1 0) goto block40;
+    else goto block39;
 block40:
     tmp2 = (read);
-    if (eq? tmp2 1)
-       goto block38;
-    else
-       goto block39;
+    if (eq? tmp2 1) goto block38;
+    else goto block39;
 block38:
     return 0;
 block39:
@@ -5292,10 +5346,20 @@ block39:
 \end{center}
 
 \begin{exercise}\normalfont
-  Implement the pass \code{explicate-control} by adding the cases for
-  \key{if} to the functions for tail and assignment contexts, and
-  implement \code{explicate-pred} for predicate contexts. Create test
-  cases that exercise all of the new cases in the code for this pass.
+Implement the pass \code{explicate-control} by adding the cases for
+Boolean constants and \key{if} to the \code{explicate-tail} and
+\code{explicate-assign}. Implement the auxiliary function
+\code{explicate-pred} for predicate contexts.
+%
+Create test cases that exercise all of the new cases in the code for
+this pass.
+%
+Add the following entry to the list of \code{passes} in
+\code{run-tests.rkt}
+\begin{lstlisting}
+(list "explicate-control" explicate-control interp-Cif type-check-Cif)
+\end{lstlisting}
+
 \end{exercise}
 
 
@@ -5566,7 +5630,7 @@ x86 assembly code.
 \begin{figure}[tbp]
 \begin{tabular}{lll}
 \begin{minipage}{0.5\textwidth}
-% s1_20.rkt
+% cond_test_20.rkt
 \begin{lstlisting}
 (if (eq? (read) 1) 42 0)
 \end{lstlisting}
@@ -5775,7 +5839,7 @@ optimization on the right.
 \begin{figure}[tbp]
 \begin{tabular}{lll}
 \begin{minipage}{0.5\textwidth}
-% s1_20.rkt
+% cond_test_20.rkt
 \begin{lstlisting}
 start:
     callq read_int
@@ -8576,8 +8640,8 @@ syntax for function application.
 \label{sec:interp-Rlambda}
 
 Figure~\ref{fig:interp-Rlambda} shows the definitional interpreter for
-\LangLam{}. The clause for \key{lambda} saves the current environment
-inside the returned \key{lambda}. Then the clause for \key{Apply} uses
+\LangLam{}. The case for \key{lambda} saves the current environment
+inside the returned \key{lambda}. Then the case for \key{Apply} uses
 the environment from the \key{lambda}, the \code{lam-env}, when
 interpreting the body of the \key{lambda}.  The \code{lam-env}
 environment is extended with the mapping of parameters to argument
@@ -8685,7 +8749,7 @@ that comes after \code{reveal-functions} and before
 \code{limit-functions}. 
 
 As usual, we implement the pass as a recursive function over the
-AST. All of the action is in the clauses for \key{Lambda} and
+AST. All of the action is in the cases for \key{Lambda} and
 \key{Apply}. We transform a \key{Lambda} expression into an expression
 that creates a closure, that is, a vector whose first element is a
 function pointer and the rest of the elements are the free variables
@@ -9195,7 +9259,7 @@ typed language (it's dynamically typed!).
 
 The definitional interpreter for \LangDyn{} is presented in
 Figure~\ref{fig:interp-Rdyn} and its auxiliary functions are defined in
-Figure~\ref{fig:interp-Rdyn-aux}. Consider the match clause for
+Figure~\ref{fig:interp-Rdyn-aux}. Consider the match case for
 \code{(Int n)}.  Instead of simply returning the integer \code{n} (as
 in the interpreter for \LangVar{} in Figure~\ref{fig:interp-Rvar}), the
 interpreter for \LangDyn{} creates a \emph{tagged value}\index{tagged
@@ -9212,7 +9276,7 @@ example, a vector of type \code{(Vector Any Any)} is tagged with
 \code{Vector} and a procedure of type \code{(Any Any -> Any)}
 is tagged with \code{Procedure}.
 
-Next consider the match clause for \code{vector-ref}.  The
+Next consider the match case for \code{vector-ref}.  The
 \code{check-tag} auxiliary function (Figure~\ref{fig:interp-Rdyn-aux})
 is used to ensure that the first argument is a vector and the second
 is an integer. If they are not, a \code{trapped-error} is raised.