Parcourir la source

copy edits for ch 5

Jeremy Siek il y a 3 ans
Parent
commit
1ae70bcd6f
1 fichiers modifiés avec 125 ajouts et 126 suppressions
  1. 125 126
      book.tex

+ 125 - 126
book.tex

@@ -9216,11 +9216,10 @@ conclusion:
 \begin{tcolorbox}[colback=white]  
 {\if\edition\racketEd
 \begin{tikzpicture}[baseline=(current  bounding  box.center),scale=0.90]
-\node (Lif) at (0,2)  {\large \LangIf{}};
-\node (Lif-2) at (3,2)  {\large \LangIf{}};
-\node (Lif-3) at (6,2)  {\large \LangIf{}};
-\node (Lif-4) at (9,2)  {\large \LangIf{}};
-\node (Lif-5) at (9,0)  {\large \LangIfANF{}};
+\node (Lif-2) at (0,2)  {\large \LangIf{}};
+\node (Lif-3) at (3,2)  {\large \LangIf{}};
+\node (Lif-4) at (6,2)  {\large \LangIf{}};
+\node (Lif-5) at (10,2)  {\large \LangIfANF{}};
 \node (C1-1) at (0,0)  {\large \LangCIf{}};
 
 \node (x86-2) at (0,-2)  {\large \LangXIfVar{}};
@@ -9230,11 +9229,10 @@ conclusion:
 \node (x86-4) at (8,-2) {\large \LangXIf{}};
 \node (x86-5) at (8,-4) {\large \LangXIf{}};
 
-\path[->,bend left=15] (Lif) edge [above] node {\ttfamily\footnotesize type\_check} (Lif-2);
 \path[->,bend left=15] (Lif-2) edge [above] node {\ttfamily\footnotesize shrink} (Lif-3);
 \path[->,bend left=15] (Lif-3) edge [above] node {\ttfamily\footnotesize uniquify} (Lif-4);
-\path[->,bend left=15] (Lif-4) edge [left] node {\ttfamily\footnotesize remove\_complex\_operands} (Lif-5);
-\path[->,bend left=10] (Lif-5) edge [above] node {\ttfamily\footnotesize explicate\_control} (C1-1);
+\path[->,bend left=15] (Lif-4) edge [above] node {\ttfamily\footnotesize remove\_complex\_operands} (Lif-5);
+\path[->,bend left=10] (Lif-5) edge [right] node {\ttfamily\footnotesize explicate\_control} (C1-1);
 \path[->,bend right=15] (C1-1) edge [right] node {\ttfamily\footnotesize select\_instructions} (x86-2);
 \path[->,bend left=15] (x86-2) edge [right] node {\ttfamily\footnotesize uncover\_live} (x86-2-1);
 \path[->,bend right=15] (x86-2-1) edge [below] node {\ttfamily\footnotesize build\_interference} (x86-2-2);
@@ -9794,7 +9792,7 @@ and the case-of-case transformation~\citep{PeytonJones:1998}.
 In this chapter we study two features that are the hallmarks of
 imperative programming languages: loops and assignments to local
 variables. The following example demonstrates these new features by
-computing the sum of the first five positive integers.
+computing the sum of the first five positive integers:
 % similar to loop_test_1.rkt
 \begin{lstlisting}
 (let ([sum 0])
@@ -9807,10 +9805,10 @@ computing the sum of the first five positive integers.
       sum)))
 \end{lstlisting}
 The \code{while} loop consists of a condition and a
-body\footnote{The \code{while} loop is not a built-in
+body.\footnote{The \code{while} loop is not a built-in
 feature of the Racket language, but Racket includes many looping
 constructs and it is straightforward to define \code{while} as a
-macro.}. The body is evaluated repeatedly so long as the condition
+macro.} The body is evaluated repeatedly so long as the condition
 remains true.
 %
 The \code{set!} consists of a variable and a right-hand side
@@ -9818,26 +9816,27 @@ expression.  The \code{set!} updates value of the variable to the
 value of the right-hand side.
 %
 The primary purpose of both the \code{while} loop and \code{set!} is
-to cause side effects, so they do not have a meaningful result
-value. Instead their result is the \code{\#<void>} value.  The
+to cause side effects, so they do not give a meaningful result
+value. Instead, their result is the \code{\#<void>} value.  The
 expression \code{(void)} is an explicit way to create the
-\code{\#<void>} value and it has type \code{Void}.  The
+\code{\#<void>} value, and it has type \code{Void}.  The
 \code{\#<void>} value can be passed around just like other values
-inside an \LangLoop{} program and it can be compared for equality with
+inside an \LangLoop{} program, and it can be compared for equality with
 another \code{\#<void>} value. However, there are no other operations
-specific to the the \code{\#<void>} value in \LangLoop{}. In contrast,
+specific to the \code{\#<void>} value in \LangLoop{}. In contrast,
 Racket defines the \code{void?}  predicate that returns \code{\#t}
 when applied to \code{\#<void>} and \code{\#f} otherwise.%
 %
 \footnote{Racket's \code{Void} type corresponds to what is often
   called the \code{Unit} type. Racket's \code{Void} type is inhabited
-  by a single value \code{\#<void>} which corresponds to \code{unit}
-  or \code{()} in the literature~\citep{Pierce:2002hj}.}.
+  by a single value \code{\#<void>}, which corresponds to \code{unit}
+  or \code{()} in the literature~\citep{Pierce:2002hj}.}
 %
-With the addition of side-effecting features such as \code{while} loop
-and \code{set!}, it is helpful to also include in a language feature
-for sequencing side effects: the \code{begin} expression. It consists
-of one or more subexpressions that are evaluated left-to-right.
+With the addition of side effect-producing features such as
+\code{while} loop and \code{set!}, it is helpful to include a language
+feature for sequencing side effects: the \code{begin} expression. It
+consists of one or more subexpressions that are evaluated
+left to right.
 %
 \fi}
 
@@ -9966,9 +9965,9 @@ the condition remains true.
 \label{fig:Lwhile-syntax}
 \end{figure}
 
-The concrete syntax of \LangLoop{} is defined in
-figure~\ref{fig:Lwhile-concrete-syntax} and its abstract syntax is defined
-in figure~\ref{fig:Lwhile-syntax}.
+Figure~\ref{fig:Lwhile-concrete-syntax} shows the definition of the
+concrete syntax of \LangLoop{}, and figure~\ref{fig:Lwhile-syntax}
+shows the definition of its abstract syntax.
 %
 The definitional interpreter for \LangLoop{} is shown in
 figure~\ref{fig:interp-Lwhile}.
@@ -9976,20 +9975,20 @@ figure~\ref{fig:interp-Lwhile}.
 {\if\edition\racketEd    
 %
 We add new cases for \code{SetBang}, \code{WhileLoop}, \code{Begin},
-and \code{Void} and we make changes to the cases for \code{Var} and
+and \code{Void}, and we make changes to the cases for \code{Var} and
 \code{Let} regarding variables. To support assignment to variables and
 to make their lifetimes indefinite (see the second example in
 section~\ref{sec:assignment-scoping}), we box the value that is bound
 to each variable (in \code{Let}). The case for \code{Var} unboxes the
 value.
 %
-Now to discuss the new cases. For \code{SetBang}, we find the
-variable in the environment to obtain a boxed value and then we change
+Now we discuss the new cases. For \code{SetBang}, we find the
+variable in the environment to obtain a boxed value, and then we change
 it using \code{set-box!} to the result of evaluating the right-hand
 side.  The result value of a \code{SetBang} is \code{\#<void>}.
 %
-For the \code{WhileLoop}, we repeatedly 1) evaluate the condition, and
-if the result is true, 2) evaluate the body.
+For the \code{WhileLoop}, we repeatedly (1) evaluate the condition, and
+if the result is true, (2) evaluate the body.
 The result value of a \code{while} loop is also \code{\#<void>}.
 %
 The $\BEGIN{\itm{es}}{\itm{body}}$ expression evaluates the
@@ -10062,7 +10061,7 @@ class InterpLwhile(InterpLif):
 \label{fig:interp-Lwhile}
 \end{figure}
 
-The type checker for \LangLoop{} is defined in
+The definition of the type checker for \LangLoop{} is shown in
 figure~\ref{fig:type-check-Lwhile}.
 %
 {\if\edition\racketEd    
@@ -10146,9 +10145,9 @@ class TypeCheckLwhile(TypeCheckLif):
 %  
 At first glance, the translation of these language features to x86
 seems straightforward because the \LangCIf{} intermediate language
-already supports all of the ingredients that we need: assignment,
+already supports all the ingredients that we need: assignment,
 \code{goto}, conditional branching, and sequencing. However, there are
-complications that arise which we discuss in the next section. After
+complications that arise, which we discuss in the next section. After
 that we introduce the changes necessary to the existing passes.
 %
 \fi}
@@ -10166,16 +10165,16 @@ that we introduce the changes necessary to the existing passes.
 \section{Cyclic Control Flow and Dataflow Analysis}
 \label{sec:dataflow-analysis}
 
-Up until this point the programs generated in
+Up until this point, the programs generated in
 \code{explicate\_control} were guaranteed to be acyclic. However, each
-\code{while} loop introduces a cycle. But does that matter?
+\code{while} loop introduces a cycle. Does that matter?
 %
-Indeed it does.  Recall that for register allocation, the compiler
+Indeed, it does.  Recall that for register allocation, the compiler
 performs liveness analysis to determine which variables can share the
-same register.  To accomplish this we analyzed the control-flow graph
+same register.  To accomplish this, we analyzed the control-flow graph
 in reverse topological order
 (section~\ref{sec:liveness-analysis-Lif}), but topological order is
-only well-defined for acyclic graphs.
+well defined only for acyclic graphs.
 
 Let us return to the example of computing the sum of the first five
 positive integers. Here is the program after instruction selection but
@@ -10242,10 +10241,10 @@ block8:
   \end{minipage}
 \fi}
 \end{center}
-Recall that liveness analysis works backwards, starting at the end
+Recall that liveness analysis works backward, starting at the end
 of each function. For this example we could start with \code{block8}
-because we know what is live at the beginning of the conclusion,
-just \code{rax} and \code{rsp}. So the live-before set
+because we know what is live at the beginning of the conclusion:
+only \code{rax} and \code{rsp}. So the live-before set
 for \code{block8} is \code{\{rsp,sum\}}.
 %
 Next we might try to analyze \code{block5} or \code{block7}, but
@@ -10253,26 +10252,26 @@ Next we might try to analyze \code{block5} or \code{block7}, but
 we are stuck.
 
 The way out of this impasse is to realize that we can compute an
-under-approximation of each live-before set by starting with empty
-live-after sets.  By \emph{under-approximation}, we mean that the set
-only contains variables that are live for some execution of the
+underapproximation of each live-before set by starting with empty
+live-after sets.  By \emph{underapproximation}, we mean that the set
+contains only variables that are live for some execution of the
 program, but the set may be missing some variables that are live.
-Next, the under-approximations for each block can be improved by 1)
+Next, the underapproximations for each block can be improved by (1)
 updating the live-after set for each block using the approximate
-live-before sets from the other blocks and 2) perform liveness
+live-before sets from the other blocks, and (2) performing liveness
 analysis again on each block.  In fact, by iterating this process, the
-under-approximations eventually become the correct solutions!
+underapproximations eventually become the correct solutions!
 %
 This approach of iteratively analyzing a control-flow graph is
 applicable to many static analysis problems and goes by the name
 \emph{dataflow analysis}\index{subject}{dataflow analysis}.  It was invented by
-\citet{Kildall:1973vn} in his Ph.D. thesis at the University of
+\citet{Kildall:1973vn} in his PhD thesis at the University of
 Washington.
 
-Let us apply this approach to the above example. We use the empty set
-for the initial live-before set for each block. Let $m_0$ be the
-following mapping from label names to sets of locations (variables and
-registers).
+Let us apply this approach to the previously presented example. We use
+the empty set for the initial live-before set for each block. Let
+$m_0$ be the following mapping from label names to sets of locations
+(variables and registers):
 \begin{center}
 \begin{lstlisting}
 mainstart: {}, block5: {}, block7: {}, block8: {}
@@ -10289,8 +10288,8 @@ mainstart: {}, block5: {i}, block7: {i, sum}, block8: {rsp, sum}
 \end{center}
 
 For the second round, the live-after for \code{mainstart} is the
-current live-before for \code{block5}, which is \code{\{i\}}.  So the
-liveness analysis for \code{mainstart} computes the empty set. The
+current live-before for \code{block5}, which is \code{\{i\}}.  Therefore
+the liveness analysis for \code{mainstart} computes the empty set. The
 live-after for \code{block5} is the union of the live-before sets for
 \code{block7} and \code{block8}, which is \code{\{i , rsp, sum\}}.
 So the liveness analysis for \code{block5} computes \code{\{i , rsp,
@@ -10298,7 +10297,7 @@ So the liveness analysis for \code{block5} computes \code{\{i , rsp,
 \code{block5} (from the previous iteration), which is \code{\{i\}}.
 So the liveness analysis for \code{block7} remains \code{\{i,
   sum\}}.  Together these yield the following approximation $m_2$ of
-the live-before sets.
+the live-before sets:
 \begin{center}
   \begin{lstlisting}
 mainstart: {}, block5: {i, rsp, sum}, block7: {i, sum}, block8: {rsp, sum}
@@ -10308,7 +10307,7 @@ In the preceding iteration, only \code{block5} changed, so we can
 limit our attention to \code{mainstart} and \code{block7}, the two
 blocks that jump to \code{block5}.  As a result, the live-before sets
 for \code{mainstart} and \code{block7} are updated to include
-\code{rsp}, yielding the following approximation $m_3$.
+\code{rsp}, yielding the following approximation $m_3$:
 \begin{center}
   \begin{lstlisting}
 mainstart: {rsp}, block5: {i,rsp,sum}, block7: {i,rsp,sum}, block8: {rsp,sum}
@@ -10319,20 +10318,21 @@ its live-before set remains \code{\{i,rsp,sum\}}.  At this point
 our approximations have converged, so $m_3$ is the solution.
 
 This iteration process is guaranteed to converge to a solution by the
-Kleene Fixed-Point Theorem, a general theorem about functions on
+Kleene fixed-point theorem, a general theorem about functions on
 lattices~\citep{Kleene:1952aa}. Roughly speaking, a \emph{lattice} is
 any collection that comes with a partial ordering $\sqsubseteq$ on its
-elements, a least element $\bot$ (pronounced bottom), and a join
-operator $\sqcup$.\index{subject}{lattice}\index{subject}{bottom}\index{subject}{partial
-  ordering}\index{subject}{join}\footnote{Technically speaking, we will be
-  working with join semi-lattices.} When two elements are ordered $m_i
-\sqsubseteq m_j$, it means that $m_j$ contains at least as much
-information as $m_i$, so we can think of $m_j$ as a better-or-equal
-approximation than $m_i$.  The bottom element $\bot$ represents the
-complete lack of information, i.e., the worst approximation.  The join
-operator takes two lattice elements and combines their information,
-i.e., it produces the least upper bound of the two.\index{subject}{least upper
-  bound}
+elements, a least element $\bot$ (pronounced \emph{bottom}), and a
+join operator
+$\sqcup$.\index{subject}{lattice}\index{subject}{bottom}\index{subject}{partial
+  ordering}\index{subject}{join}\footnote{Technically speaking, we
+  will be working with join semilattices.} When two elements are
+ordered $m_i \sqsubseteq m_j$, it means that $m_j$ contains at least
+as much information as $m_i$, so we can think of $m_j$ as a
+better-than-or-equal-to approximation in relation to $m_i$.  The
+bottom element $\bot$ represents the complete lack of information,
+that is, the worst approximation.  The join operator takes two lattice
+elements and combines their information; that is, it produces the
+least upper bound of the two.\index{subject}{least upper bound}
 
 A dataflow analysis typically involves two lattices: one lattice to
 represent abstract states and another lattice that aggregates the
@@ -10344,11 +10344,11 @@ set, and the join operator to be set union.
 %
 We form a second lattice $M$ by taking its elements to be mappings
 from the block labels to sets of locations (elements of $L$).  We
-order the mappings point-wise, using the ordering of $L$. So given any
+order the mappings point-wise, using the ordering of $L$. So, given any
 two mappings $m_i$ and $m_j$, $m_i \sqsubseteq_M m_j$ when $m_i(\ell)
 \subseteq m_j(\ell)$ for every block label $\ell$ in the program.  The
 bottom element of $M$ is the mapping $\bot_M$ that sends every label
-to the empty set, i.e., $\bot_M(\ell) = \emptyset$.
+to the empty set; that is, $\bot_M(\ell) = \emptyset$.
 
 We can think of one iteration of liveness analysis applied to the
 whole program as being a function $f$ on the lattice $M$. It takes a
@@ -10363,20 +10363,20 @@ solution should be a \emph{fixed point} of the function $f$.\index{subject}{fixe
 \[
    f(m_s) = m_s
 \]
-Furthermore, the solution should only include locations that are
+Furthermore, the solution should include only locations that are
 forced to be there by performing liveness analysis on the program, so
 the solution should be the \emph{least} fixed point.\index{subject}{least fixed point}
 
-The Kleene Fixed-Point Theorem states that if a function $f$ is
+The Kleene fixed-point theorem states that if a function $f$ is
 monotone (better inputs produce better outputs), then the least fixed
 point of $f$ is the least upper bound of the \emph{ascending Kleene
-  chain} obtained by starting at $\bot$ and iterating $f$ as
-follows.\index{subject}{Kleene Fixed-Point Theorem}
+  chain} obtained by starting at $\bot$ and iterating $f$, as
+follows:\index{subject}{Kleene Fixed-Point Theorem}
 \[
 \bot \sqsubseteq f(\bot) \sqsubseteq f(f(\bot)) \sqsubseteq \cdots
   \sqsubseteq f^n(\bot) \sqsubseteq \cdots
 \]
-When a lattice contains only finitely-long ascending chains, then
+When a lattice contains only finitely long ascending chains, then
 every Kleene chain tops out at some fixed point after some number of
 iterations of $f$.
 \[
@@ -10385,7 +10385,7 @@ iterations of $f$.
 \]
 
 The liveness analysis is indeed a monotone function and the lattice
-$M$ only has finitely-long ascending chains because there are only a
+$M$ has finitely long ascending chains because there are only a
 finite number of variables and blocks in the program. Thus we are
 guaranteed that iteratively applying liveness analysis to all blocks
 in the program will eventually produce the least fixed point solution.
@@ -10394,17 +10394,17 @@ Next let us consider dataflow analysis in general and discuss the
 generic work list algorithm (figure~\ref{fig:generic-dataflow}). 
 %
 The algorithm has four parameters: the control-flow graph \code{G}, a
-function \code{transfer} that applies the analysis to one block, the
-\code{bottom} and \code{join} operator for the lattice of abstract
+function \code{transfer} that applies the analysis to one block, and the
+\code{bottom} and \code{join} operators for the lattice of abstract
 states. The \code{analyze\_dataflow} function is formulated as a
-\emph{forward} dataflow analysis, that is, the inputs to the transfer
+\emph{forward} dataflow analysis; that is, the inputs to the transfer
 function come from the predecessor nodes in the control-flow
 graph. However, liveness analysis is a \emph{backward} dataflow
 analysis, so in that case one must supply the \code{analyze\_dataflow}
 function with the transpose of the control-flow graph.
 
 The algorithm begins by creating the bottom mapping, represented by a
-hash table.  It then pushes all of the nodes in the control-flow graph
+hash table.  It then pushes all the nodes in the control-flow graph
 onto the work list (a queue). The algorithm repeats the \code{while}
 loop as long as there are items in the work list. In each iteration, a
 node is popped from the work list and processed. The \code{input} for
@@ -10414,7 +10414,6 @@ obtain the \code{output} abstract state. If the output differs from
 the previous state for this block, the mapping for this block is
 updated and its successor nodes are pushed onto the work list.
 
-
 \begin{figure}[tb]
 \begin{tcolorbox}[colback=white]  
 {\if\edition\racketEd    
@@ -10468,7 +10467,7 @@ def analyze_dataflow(G, transfer, bottom, join):
 There is a subtle interaction between the
 \code{remove\_complex\_operands} pass, the addition of \code{set!},
 and the left-to-right order of evaluation of Racket. Consider the
-following example.
+following example:
 \begin{lstlisting}
 (let ([x 2])
   (+ x (begin (set! x 40) x)))
@@ -10482,7 +10481,7 @@ example we obtain the following program whose result is \code{80}!
   (let ([tmp (begin (set! x 40) x)])
     (+ x tmp)))
 \end{lstlisting}
-The problem is that, with mutable variables, the ordering between
+The problem is that with mutable variables, the ordering between
 reads and writes is important, and the
 \code{remove\_complex\_operands} pass moved the \code{set!} to happen
 before the first read of \code{x}.
@@ -10493,16 +10492,16 @@ side of a \code{set!}. We mark each read from a mutable variable with
 the form \code{get!} (\code{GetBang} in abstract syntax) to indicate
 that the read operation is effectful in that it can produce different
 results at different points in time. Let's apply this idea to the
-following variation that also involves a variable that is not mutated.
+following variation that also involves a variable that is not mutated:
 % loop_test_24.rkt
 \begin{lstlisting}
 (let ([x 2])
   (let ([y 0])
     (+ y (+ x (begin (set! x 40) x)))))
 \end{lstlisting}
-We first analyze the above program to discover that variable \code{x}
+We first analyze this program to discover that variable \code{x}
 is mutable but \code{y} is not. We then transform the program as
-follows, replacing each occurrence of \code{x} with \code{(get! x)}.
+follows, replacing each occurrence of \code{x} with \code{(get! x)}:
 \begin{lstlisting}
 (let ([x 2])
   (let ([y 0])
@@ -10513,7 +10512,7 @@ immutable variables, we can apply the \code{remove\_complex\_operands}
 pass, where reads from immutable variables are still classified as
 atomic expressions but reads from mutable variables are classified as
 complex.  Thus, \code{remove\_complex\_operands} yields the following
-program.\\
+program:\\
 \begin{minipage}{\textwidth}
 \begin{lstlisting}
 (let ([x 2])
@@ -10533,7 +10532,7 @@ variables, making it more likely for some of them to be spilled.  The
 result of this program is \code{42}, the same as the result prior to
 \code{remove\_complex\_operands}.
 
-The approach that we've sketched above requires only a small
+The approach that we've sketched requires only a small
 modification to \code{remove\_complex\_operands} to handle
 \code{get!}. However, it requires a new pass, called
 \code{uncover-get!}, that we discuss in
@@ -10563,10 +10562,10 @@ passes.
 \section{Uncover \texttt{get!}}
 \label{sec:uncover-get-bang}
 
-The goal of this pass it to mark uses of mutable variables so that
+The goal of this pass is to mark uses of mutable variables so that
 \code{remove\_complex\_operands} can treat them as complex expressions
-and thereby preserve their ordering relative to the side-effects in
-other operands. So the first step is to collect all the mutable
+and thereby preserve their ordering relative to the side effects in
+other operands. So, the first step is to collect all the mutable
 variables. We recommend creating an auxiliary function for this,
 named \code{collect-set!}, that recursively traverses expressions,
 returning the set of all variables that occur on the left-hand side of a
@@ -10587,14 +10586,14 @@ returning the set of all variables that occur on the left-hand side of a
 \end{minipage}
 \end{center}
 By placing this pass after \code{uniquify}, we need not worry about
-variable shadowing and our logic for \code{Let} can remain simple, as
-in the excerpt above.
+variable shadowing, and our logic for \code{Let} can remain simple, as
+in this excerpt.
 
 The second step is to mark the occurrences of the mutable variables
 with the new \code{GetBang} AST node (\code{get!} in concrete
 syntax). The following is an excerpt of the \code{uncover-get!-exp}
 function, which takes two parameters: the set of mutable variables
-\code{set!-vars}, and the expression \code{e} to be processed. The
+\code{set!-vars} and the expression \code{e} to be processed. The
 case for \code{(Var x)} replaces it with \code{(GetBang x)} if it is a
 mutable variable or leaves it alone if not.
 \begin{center}
@@ -10710,7 +10709,7 @@ must introduce a temporary variable and bind it to the complex
 expression.  This approach applies, unchanged, to handle the new
 language forms.  For example, in the following code there are two
 \code{begin} expressions appearing as arguments to the \code{+}
-operator.  The output of \code{rco\_exp} is shown below, in which the
+operator.  The output of \code{rco\_exp} is then shown, in which the
 \code{begin} expressions have been bound to temporary
 variables. Recall that \code{let} expressions in \LangLoopANF{} are
 allowed to have arbitrary expressions in their right-hand side
@@ -10768,7 +10767,7 @@ $\Rightarrow$
 
 Recall that in the \code{explicate\_control} pass we define one helper
 function for each kind of position in the program.  For the \LangVar{}
-language of integers and variables we needed assignment and tail
+language of integers and variables, we needed assignment and tail
 positions. The \code{if} expressions of \LangIf{} introduced predicate
 positions. For \LangLoop{}, the \code{begin} expression introduces yet
 another kind of position: effect position. Except for the last
@@ -10778,11 +10777,11 @@ generate better code by taking this fact into account.
 
 The output language of \code{explicate\_control} is \LangCLoop{}
 (figure~\ref{fig:c7-syntax}), which is nearly identical to
-\LangCIf{}. The only syntactic difference is the addition of \VOID{}
+\LangCIf{}. The only syntactic differences are the addition of \VOID{}
 and that \code{read} may appear as a statement.  The most significant
 difference between the programs generated by \code{explicate\_control}
 in chapter~\ref{ch:Lif} versus \code{explicate\_control} in this
-chapter is that the control-flow graphs of the later may contain
+chapter is that the control-flow graphs of the latter may contain
 cycles.
 
 \begin{figure}[tp]
@@ -10813,7 +10812,7 @@ causes side effects, then the expression can be removed, so the result
 is just the continuation.
 %
 The case for $\WHILE{\itm{cnd}}{\itm{body}}$ expressions is
-interesting; the generated code is depicted in the following diagram.
+interesting; the generated code is depicted in the following diagram:
 \begin{center}
   \begin{minipage}{0.3\textwidth}
 \xymatrix{
@@ -10828,8 +10827,8 @@ We start by creating a fresh label $\itm{loop}$ for the top of the
 loop.  Next, recursively process the \itm{body} (in effect position)
 with a \code{goto} to $\itm{loop}$ as the continuation, producing
 \itm{body'}. Process the \itm{cnd} (in predicate position) with
-\itm{body'} as the then-branch and the continuation block as the
-else-branch. The result should be added to the dictionary of
+\itm{body'} as the \emph{then} branch and the continuation block as the
+\emph{else} branch. The result should be added to the dictionary of
 \code{basic-blocks} with the label \itm{loop}. The result for the
 whole \code{while} loop is a \code{goto} to the \itm{loop} label.
 
@@ -10862,8 +10861,8 @@ the condition expression.
 Only two small additions are needed in the \code{select\_instructions}
 pass to handle the changes to \LangCLoop{}. First, to handle the
 addition of \VOID{} we simply translate it to \code{0}.  Second,
-\code{read} may appear as a stand-alone statement instead of only
-appearing on the right-hand side of an assignment statement. The code
+\code{read} may appear as a stand-alone statement instead of 
+appearing only on the right-hand side of an assignment statement. The code
 generation is nearly identical to the one for assignment; just leave
 off the instruction for moving the result into the left-hand side.
 
@@ -10883,7 +10882,7 @@ perform liveness analysis, replacing the code in
 \code{uncover\_live} that processed the basic blocks in topological
 order (section~\ref{sec:liveness-analysis-Lif}).
 
-The \code{analyze\_dataflow} function has four parameters.
+The \code{analyze\_dataflow} function has the following four parameters.
 \begin{enumerate}
 \item The first parameter \code{G} should be passed the transpose
   of the control-flow graph.
@@ -10893,7 +10892,7 @@ The \code{analyze\_dataflow} function has four parameters.
   set for that block.  The transfer function should return the
   live-before set for the block.
   %
-  \racket{Also, as a side-effect, it should update the block's
+  \racket{Also, as a side effect, it should update the block's
     $\itm{info}$ with the liveness information for each instruction.}
   %
   \python{Also, as a side-effect, it should update the live-before and
@@ -10903,14 +10902,14 @@ The \code{analyze\_dataflow} function has four parameters.
   reuse the code you already have for analyzing basic blocks.
 \item The third and fourth parameters of \code{analyze\_dataflow} are
   \code{bottom} and \code{join} for the lattice of abstract states,
-  i.e.  sets of locations. For liveness analysis, the bottom of the
-  lattice is the empty set and the join operator is set union.
+  that is, sets of locations. For liveness analysis, the bottom of the
+  lattice is the empty set, and the join operator is set union.
 \end{enumerate}
 
 
 \begin{figure}[p]
 \begin{tcolorbox}[colback=white]      
-\begin{tikzpicture}[baseline=(current  bounding  box.center)]
+\begin{tikzpicture}[baseline=(current  bounding  box.center),scale=0.90]
 \node (Lfun) at (0,2)  {\large \LangLoop{}};
 \node (Lfun-2) at (3,2)  {\large \LangLoop{}};
 %\node (Lfun-3) at (6,2)  {\large \LangLoop{}};
@@ -10921,14 +10920,14 @@ The \code{analyze\_dataflow} function has four parameters.
 \node (F1-4) at (6,2)  {\large \LangLoop{}};
 \node (F1-5) at (9,2)  {\large \LangLoop{}};
 \node (F1-6) at (9,0)  {\large \LangLoopANF{}};
-\node (C3-2) at (3,0)  {\large \racket{\LangCLoop{}}\python{\LangCIf{}}};
+\node (C3-2) at (0,0)  {\large \racket{\LangCLoop{}}\python{\LangCIf{}}};
 
-\node (x86-2) at (3,-2)  {\large \LangXIfVar{}};
-\node (x86-2-1) at (3,-4)  {\large \LangXIfVar{}};
-\node (x86-2-2) at (6,-4)  {\large \LangXIfVar{}};
-\node (x86-3) at (6,-2)  {\large \LangXIfVar{}};
-\node (x86-4) at (9,-2) {\large \LangXIf{}};
-\node (x86-5) at (9,-4) {\large \LangXIf{}};
+\node (x86-2) at (0,-2)  {\large \LangXIfVar{}};
+\node (x86-2-1) at (0,-4)  {\large \LangXIfVar{}};
+\node (x86-2-2) at (4,-4)  {\large \LangXIfVar{}};
+\node (x86-3) at (4,-2)  {\large \LangXIfVar{}};
+\node (x86-4) at (8,-2) {\large \LangXIf{}};
+\node (x86-5) at (8,-4) {\large \LangXIf{}};
 
 
 %% \path[->,bend left=15] (Lfun) edge [above] node
@@ -10949,22 +10948,22 @@ The \code{analyze\_dataflow} function has four parameters.
 %%      {\ttfamily\footnotesize expose-alloc.} (F1-4);
 \path[->,bend left=15] (F1-4) edge [above] node
      {\ttfamily\footnotesize uncover\_get!} (F1-5);
-\path[->,bend left=15] (F1-5) edge [right] node
-     {\ttfamily\footnotesize remove\_complex.} (F1-6);
-\path[->,bend right=15] (F1-6) edge [above] node
+\path[->,bend left=15] (F1-5) edge [left] node
+     {\ttfamily\footnotesize remove\_complex\_operands} (F1-6);
+\path[->,bend left=10] (F1-6) edge [above] node
      {\ttfamily\footnotesize explicate\_control} (C3-2);
-\path[->,bend left=15] (C3-2) edge [left] node
-     {\ttfamily\footnotesize select\_instr.} (x86-2);
-\path[->,bend right=15] (x86-2) edge [left] node
+\path[->,bend left=15] (C3-2) edge [right] node
+     {\ttfamily\footnotesize select\_instructions} (x86-2);
+\path[->,bend right=15] (x86-2) edge [right] node
      {\ttfamily\footnotesize uncover\_live} (x86-2-1);
 \path[->,bend right=15] (x86-2-1) edge [below] node 
-     {\ttfamily\footnotesize build\_inter.} (x86-2-2);
-\path[->,bend right=15] (x86-2-2) edge [left] node
-     {\ttfamily\footnotesize allocate\_reg.} (x86-3);
+     {\ttfamily\footnotesize build\_interference} (x86-2-2);
+\path[->,bend right=15] (x86-2-2) edge [right] node
+     {\ttfamily\footnotesize allocate\_registers} (x86-3);
 \path[->,bend left=15] (x86-3) edge [above] node
-     {\ttfamily\footnotesize patch\_instr.} (x86-4);
+     {\ttfamily\footnotesize patch\_instructions} (x86-4);
 \path[->,bend left=15] (x86-4) edge [right] node
-     {\ttfamily\footnotesize pre.\_and\_concl.} (x86-5);
+     {\ttfamily\footnotesize prelude\_and\_conclusion} (x86-5);
 \end{tikzpicture}
 \end{tcolorbox}