Jeremy Siek hace 4 años
padre
commit
2229f55d7c
Se han modificado 1 ficheros con 157 adiciones y 166 borrados
  1. 157 166
      book.tex

+ 157 - 166
book.tex

@@ -134,7 +134,7 @@ showstringspaces=false
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 \title{\Huge \textbf{Essentials of Compilation} \\
-  \huge An Incremental Approach}
+  \huge The Incremental, Nano-Pass Approach}
 
 \author{\textsc{Jeremy G. Siek} \\
 %\thanks{\url{http://homes.soic.indiana.edu/jsiek/}} \\
@@ -188,15 +188,19 @@ The compiler course evolved to incorporate novel pedagogical ideas
 while also including elements of effective real-world compilers.  One
 of Friedman's ideas was to split the compiler into many small
 ``passes'' so that the code for each pass would be easy to understood
-in isolation.  (In contrast, most compilers of the time were organized
+in isolation.  In contrast, most compilers of the time were organized
 into only a few monolithic passes for reasons of compile-time
-efficiency.)  Dybvig, with later help from his students Dipanwita
-Sarkar and Andrew Keep, developed infrastructure to support this
-approach and evolved the course, first to use smaller micro-passes and
-then into even smaller
-nano-passes~\citep{Sarkar:2004fk,Keep:2012aa}. I was a student in this
-compiler course in the early 2000's as part of his Ph.D. studies at
-Indiana University. Needless to say, I enjoyed the course immensely!
+efficiency. Another idea, called ``the game'', was to test the code
+generated by each pass on interpreters for each intermediate language,
+thereby helping to pinpoint errors in individual passes.
+%
+Dybvig, with later help from his students Dipanwita Sarkar and Andrew
+Keep, developed infrastructure to support this approach and evolved
+the course, first to use smaller micro-passes and then into even
+smaller nano-passes~\citep{Sarkar:2004fk,Keep:2012aa}. I was a student
+in this compiler course in the early 2000's as part of my
+Ph.D. studies at Indiana University. Needless to say, I enjoyed the
+course immensely!
 
 During that time, another graduate student named Abdulaziz Ghuloum
 observed that the front-to-back organization of the course made it
@@ -219,30 +223,28 @@ same content from the Indiana compiler course. I very much enjoyed
 teaching the course organized in this way, and even better, many of
 the students learned a lot and got excited about compilers.
 
-I returned to teach at Indiana University in 2013.  In my absence the
-compiler course had switched from the front-to-back organization to a
-back-to-front organization. Seeing how well the incremental approach
-worked at Colorado, I started porting and adapting the structure of
-the Colorado course back into the land of Scheme. In the meantime
-Indiana University had moved on from Scheme to Racket, so the course
-is now about compiling a subset of Racket (and Typed Racket) to the
-x86 assembly language. The compiler is implemented in
-Racket~\citep{plt-tr}.
+I returned to Indiana University in 2013.  In my absence the compiler
+course had switched from the front-to-back organization to a
+back-to-front organization~\cite{Dybvig:2010aa}. Seeing how well the
+incremental approach worked at Colorado, I started porting and
+adapting the structure of the Colorado course back into the land of
+Scheme. In the meantime Indiana University had moved on from Scheme to
+Racket~\citep{plt-tr}, so the course is now about compiling a subset
+of Racket (and Typed Racket) to the x86 assembly language.
 
 This is the textbook for the incremental version of the compiler
-course at Indiana University (Spring 2016 - present) and it is the
-first open textbook for an Indiana compiler course.  With this book I
-hope to make the Indiana compiler course available to people that have
-not had the chance to study compilers at Indiana University.  Many of
-the compiler design decisions in this book are drawn from the
-assignment descriptions of \cite{Dybvig:2010aa}. I have captured what
-I think are the most important topics from \cite{Dybvig:2010aa} but
-have omitted topics that are less interesting conceptually. I have
-also made simplifications to reduce complexity.  In this way, this
-book leans more towards pedagogy than towards the efficiency of the
-generated code. Also, the book differs in places where we I the
-opportunity to make the topics more fun, such as in relating register
-allocation to Sudoku (Chapter~\ref{ch:register-allocation-r1}).
+course at Indiana University (Spring 2016 - present).  With this book
+I hope to make the Indiana compiler course available to people that
+have not had the chance to study compilers at Indiana University.
+
+%% I have captured what
+%% I think are the most important topics from \cite{Dybvig:2010aa} but
+%% have omitted topics that are less interesting conceptually. I have
+%% also made simplifications to reduce complexity.  In this way, this
+%% book leans more towards pedagogy than towards the efficiency of the
+%% generated code. Also, the book differs in places where we I the
+%% opportunity to make the topics more fun, such as in relating register
+%% allocation to Sudoku (Chapter~\ref{ch:register-allocation-r1}).
 
 \section*{Prerequisites}
 
@@ -289,11 +291,12 @@ is to run a virtual machine with Linux as the guest operating system.
 \section*{Acknowledgments}
 
 Many people have contributed to the ideas, techniques, and
-organization of this book and have taught courses based on it. We
-especially thank John Clements, Bor-Yuh Evan Chang, Kent Dybvig,
-Daniel P. Friedman, Ronald Garcia, Abdulaziz Ghuloum, Andrew Keep, Jay
-McCarthy, Nate Nystrom, Dipanwita Sarkar, Oscar Waddell, and Michael
-Wollowski.
+organization of this book and have taught courses based on it.  Many
+of the compiler design decisions in this book are drawn from the
+assignment descriptions of \cite{Dybvig:2010aa}.  We also would like
+to thank John Clements, Bor-Yuh Evan Chang, Daniel P. Friedman, Ronald
+Garcia, Abdulaziz Ghuloum, Jay McCarthy, Nate Nystrom, Dipanwita
+Sarkar, Oscar Waddell, and Michael Wollowski.
 
 \mbox{}\\
 \noindent Jeremy G. Siek \\
@@ -313,44 +316,37 @@ called \emph{concrete syntax}. We use concrete syntax to concisely
 write down and talk about programs. Inside the compiler, we use
 \emph{abstract syntax trees} (ASTs) to represent programs in a way
 that efficiently supports the operations that the compiler needs to
-perform.
-\index{concrete syntax}
-\index{abstract syntax}
-\index{abstract syntax tree}
-\index{AST}
-\index{program}
-\index{parse}
-%
-The translation from concrete syntax to abstract syntax is a process
-called \emph{parsing}~\cite{Aho:1986qf}. We do not cover the theory
-and implementation of parsing in this book. A parser is provided in
-the supporting materials for translating from concrete syntax to
-abstract syntax for the languages used in this book.
+perform.\index{concrete syntax}\index{abstract syntax}\index{abstract
+  syntax tree}\index{AST}\index{program}\index{parse} The translation
+from concrete syntax to abstract syntax is a process called
+\emph{parsing}~\citep{Aho:1986qf}. We do not cover the theory and
+implementation of parsing in this book. A parser is provided in the
+supporting materials for translating from concrete to abstract syntax.
 
 ASTs can be represented in many different ways inside the compiler,
 depending on the programming language used to write the compiler.
 %
-We use Racket's \href{https://docs.racket-lang.org/guide/define-struct.html}{\code{struct}}
+We use Racket's
+\href{https://docs.racket-lang.org/guide/define-struct.html}{\code{struct}}
 feature to represent ASTs (Section~\ref{sec:ast}). We use grammars to
-define the abstract syntax of programming languages (Section~\ref{sec:grammar})
-and pattern matching to inspect individual nodes in an AST
-(Section~\ref{sec:pattern-matching}).  We use recursion to construct
-and deconstruct entire ASTs (Section~\ref{sec:recursion}).  This
-chapter provides an brief introduction to these ideas.
-\index{struct}
+define the abstract syntax of programming languages
+(Section~\ref{sec:grammar}) and pattern matching to inspect individual
+nodes in an AST (Section~\ref{sec:pattern-matching}).  We use
+recursive functions to construct and deconstruct entire ASTs
+(Section~\ref{sec:recursion}).  This chapter provides an brief
+introduction to these ideas.  \index{struct}
 
 \section{Abstract Syntax Trees and Racket Structures}
 \label{sec:ast}
 
-Compilers use abstract syntax trees to represent programs because
-compilers often need to ask questions like: for a given part of a
-program, what kind of language feature is it? What are the sub-parts
-of this part of the program? Consider the program on the left and its
-AST on the right. This program is an addition and it has two
-sub-parts, a read operation and a negation. The negation has another
-sub-part, the integer constant \code{8}. By using a tree to represent
-the program, we can easily follow the links to go from one part of a
-program to its sub-parts.
+Compilers use abstract syntax trees to represent programs because they
+often need to ask questions like: for a given part of a program, what
+kind of language feature is it? What are its sub-parts? Consider the
+program on the left and its AST on the right. This program is an
+addition and it has two sub-parts, a read operation and a
+negation. The negation has another sub-part, the integer constant
+\code{8}. By using a tree to represent the program, we can easily
+follow the links to go from one part of a program to its sub-parts.
 \begin{center}
 \begin{minipage}{0.4\textwidth}
 \begin{lstlisting}
@@ -452,10 +448,10 @@ We say that the value created by \code{(Int 8)} is an
 
 The following is the \code{struct} definition for primitives operations.
 \begin{lstlisting}
-(struct Prim (op arg*))
+(struct Prim (op args))
 \end{lstlisting}
 A primitive operation node includes an operator symbol \code{op}
-and a list of children \code{arg*}. For example, to create
+and a list of children \code{args}. For example, to create
 an AST that negates the number $8$, we write \code{(Prim '- (list eight))}.
 \begin{lstlisting}
 (define neg-eight (Prim '- (list eight)))
@@ -521,13 +517,12 @@ instance of the \code{Int} structure is an expression:
 \end{equation}
 %
 Each rule has a left-hand-side and a right-hand-side. The way to read
-a rule is that if you have all the program parts on the
-right-hand-side, then you can create an AST node and categorize it
-according to the left-hand-side.
+a rule is that if you have an AST node that matches the
+right-hand-side, then you can categorize it according to the
+left-hand-side.
 %
-A name such as $\Exp$ that is
-defined by the grammar rules is a \emph{non-terminal}.
-\index{non-terminal}
+A name such as $\Exp$ that is defined by the grammar rules is a
+\emph{non-terminal}.  \index{non-terminal}
 %
 The name $\Int$ is a also a non-terminal, but instead of defining it
 with a grammar rule, we define it with the following explanation.  We
@@ -557,10 +552,9 @@ Symbols in typewriter font such as \key{-} and \key{read} are
 the rule to be applicable.
 \index{terminal}
 
-We can apply the rules to build ASTs in the $R_0$
-language. For example, by rule \eqref{eq:arith-int}, \texttt{(Int 8)} is an
-$\Exp$, then by rule \eqref{eq:arith-neg}, the following AST is
-an $\Exp$.
+We can apply these rules to build ASTs in the $R_0$ language. By rule
+\eqref{eq:arith-int}, \texttt{(Int 8)} is an $\Exp$, then by rule
+\eqref{eq:arith-neg}, the following AST is an $\Exp$.
 \begin{center}
 \begin{minipage}{0.4\textwidth}
 \begin{lstlisting}
@@ -586,8 +580,8 @@ The next grammar rule defines addition expressions:
 \end{equation}
 We can now justify that the AST \eqref{eq:arith-prog} is an $\Exp$ in
 $R_0$.  We know that \lstinline{(Prim 'read '())} is an $\Exp$ by rule
-\eqref{eq:arith-read} and we have already shown that \code{(Prim '-
-  (list (Int 8)))} is an $\Exp$, so we apply rule \eqref{eq:arith-add}
+\eqref{eq:arith-read} and we have already categorized \code{(Prim '-
+  (list (Int 8)))} as an $\Exp$, so we apply rule \eqref{eq:arith-add}
 to show that
 \begin{lstlisting}
 (Prim '+ (list (Prim 'read '()) (Prim '- (list (Int 8)))))
@@ -636,7 +630,7 @@ Appendix~\ref{appendix:utilities} for more details.
 \[
 \begin{array}{rcl}
 \begin{array}{rcl}
-  \Exp &::=& \Int \mid (\key{read}) \mid (\key{-}\;\Exp) \mid (\key{+} \; \Exp\;\Exp)\\
+  \Exp &::=& \Int \mid \LP\key{read}\RP \mid \LP\key{-}\;\Exp\RP \mid \LP\key{+} \; \Exp\;\Exp\RP\\
   R_0 &::=& \Exp
 \end{array}
 \end{array}
@@ -704,14 +698,15 @@ Reference\footnote{\url{https://docs.racket-lang.org/reference/match.html}}
 for a complete description of \code{match}.)
 %
 The body of a match clause may contain arbitrary Racket code.  The
-pattern variables can be used in the scope of the body.
+pattern variables can be used in the scope of the body, such as
+\code{op} in \code{(print op)}.
 
 A \code{match} form may contain several clauses, as in the following
-function \code{leaf?} that recognizes when an $R_0$ node is
-a leaf. The \code{match} proceeds through the clauses in order,
-checking whether the pattern can match the input AST. The
-body of the first clause that matches is executed. The output of
-\code{leaf?} for several ASTs is shown on the right.
+function \code{leaf?} that recognizes when an $R_0$ node is a leaf in
+the AST. The \code{match} proceeds through the clauses in order,
+checking whether the pattern can match the input AST. The body of the
+first clause that matches is executed. The output of \code{leaf?} for
+several ASTs is shown on the right.
 \begin{center}
 \begin{minipage}{0.6\textwidth}
 \begin{lstlisting}
@@ -719,8 +714,8 @@ body of the first clause that matches is executed. The output of
   (match arith
     [(Int n) #t]
     [(Prim 'read '()) #t]
-    [(Prim '- (list c1)) #f]
-    [(Prim '+ (list c1 c2)) #f]))
+    [(Prim '- (list e1)) #f]
+    [(Prim '+ (list e1 e2)) #f]))
 
 (leaf? (Prim 'read '()))
 (leaf? (Prim '- (list (Int 8))))
@@ -753,13 +748,13 @@ in the \code{leaf?} function, we refer to the grammar for $R_0$ in
 Figure~\ref{fig:r0-syntax}. The $\Exp$ non-terminal has 4
 alternatives, so the \code{match} has 4 clauses.  The pattern in each
 clause corresponds to the right-hand side of a grammar rule. For
-example, the pattern \code{(Prim '+ (list c1 c2))} corresponds to the
+example, the pattern \code{(Prim '+ (list e1 e2))} corresponds to the
 right-hand side $\ADD{\Exp}{\Exp}$. When translating from grammars to
 patterns, replace non-terminals such as $\Exp$ with pattern variables
-of your choice (e.g. \code{c1} and \code{c2}).
+of your choice (e.g. \code{e1} and \code{e2}).
 
 
-\section{Recursion}
+\section{Recursive Functions}
 \label{sec:recursion}
 \index{recursive function}
 
@@ -770,17 +765,16 @@ such a recursive function, we define \texttt{exp?} below, which takes
 an arbitrary value and determines whether or not it is an $R_0$
 expression.
 %
-When a recursive function is defined using a sequence of match clauses
-that correspond to a grammar, and the body of each clause makes a
-recursive call on each child node, then we say the function is defined
-by \emph{structural recursion}\footnote{This principle of structuring
-  code according to the data definition is advocated in the book
-  \emph{How to Design Programs}
-  \url{http://www.ccs.neu.edu/home/matthias/HtDP2e/}.}. Below we also
-define a second function, named \code{R0?}, that determines whether a
-value is an $R_0$ program.  In general we can expect to write one
-recursive function to handle each non-terminal in a grammar.
-\index{structural recursion}
+We say that a function is defined by \emph{structural recursion} when
+it is defined using a sequence of match clauses that correspond to a
+grammar, and the body of each clause makes a recursive call on each
+child node.\footnote{This principle of structuring code according to
+  the data definition is advocated in the book \emph{How to Design
+    Programs}\url{http://www.ccs.neu.edu/home/matthias/HtDP2e/}.}.
+Below we also define a second function, named \code{R0?}, that
+determines whether an AST is an $R_0$ program.  In general we can
+expect to write one recursive function to handle each non-terminal in
+a grammar.\index{structural recursion}
 %
 \begin{center}
 \begin{minipage}{0.7\textwidth}
@@ -850,27 +844,23 @@ it comes to the \code{Program} wrapper.  Yet this style is generally
 %
 For example, the above function is subtly wrong:
 \lstinline{(R0? (Program '() (Program '() (Int 3))))}
-will return true, when it should return false.
-
-%% NOTE FIXME - must check for consistency on this issue throughout.
+would return true, when it should return false.
 
 
 \section{Interpreters}
 \label{sec:interp-R0}
 \index{interpreter}
 
-The meaning, or semantics, of a program is typically defined in the
+In general, the intended behavior of a program is defined by the
 specification of the language. For example, the Scheme language is
 defined in the report by \cite{SPERBER:2009aa}. The Racket language is
-defined in its reference manual~\citep{plt-tr}. In this book we use an
-interpreter to define the meaning of each language that we consider,
-following Reynolds' advice~\citep{reynolds72:_def_interp}. An
-interpreter that is designated (by some people) as the definition of a
-language is called a \emph{definitional interpreter}.
-\index{definitional interpreter}
-We warm up by creating a definitional interpreter for the $R_0$ language, which
-serves as a second example of structural recursion. The
-\texttt{interp-R0} function is defined in
+defined in its reference manual~\citep{plt-tr}. In this book we use
+interpreters to specify each language that we consider. An interpreter
+that is designated as the definition of a language is called a
+\emph{definitional interpreter}~\citep{reynolds72:_def_interp}.
+\index{definitional interpreter} We warm up by creating a definitional
+interpreter for the $R_0$ language, which serves as a second example
+of structural recursion. The \texttt{interp-R0} function is defined in
 Figure~\ref{fig:interp-R0}. The body of the function is a match on the
 input program followed by a call to the \lstinline{interp-exp} helper
 function, which in turn has one match clause per grammar rule for
@@ -1197,7 +1187,7 @@ interpreters. We want to write down those common parts just once
 instead of many times. A naive approach would be to have, for example,
 the interpreter for $R_2$ handle all of the new features in that
 language and then have a default case that dispatches to the
-interpreter for $R_1$. The follow code sketches this idea.
+interpreter for $R_1$. The following code sketches this idea.
 \begin{center}
   \begin{minipage}{0.45\textwidth}
 \begin{lstlisting}
@@ -1242,7 +1232,7 @@ To make our intepreters extensible we need something called \emph{open
 always invoke the ``top'' interpreter, even if the recursive call is
 made from interpreters that are lower down.  Object-oriented languages
 provide open recursion in the form of method overriding\index{method
-  overriding}. The follow code sketches this idea for interpreting
+  overriding}. The following code sketches this idea for interpreting
 $R_1$ and $R_2$ using the
 \href{https://docs.racket-lang.org/guide/classes.html}{\code{class}}
 \index{class} feature of Racket.  We define one class for each
@@ -1297,12 +1287,13 @@ expression by creating an object of the $R_2$ class and sending it the
 \begin{lstlisting}
 (send (new interp-R2-class) interp-exp e0)
 \end{lstlisting}
-This will again hit the default case and dispatch to the
-\code{interp-exp} method for $R_1$, which will handle the \code{-}
-operator. But then for the recursive method call, it will dispatch
-back to \code{interp-exp} for $R_2$, where the \code{If} will be
-correctly handled. Thus, method overriding gives us the open recursion
-that we need to implement our interpreters in an extensible way.
+This will again hit the default case of \code{interp-exp} in $R_2$ and
+dispatch to the \code{interp-exp} method for $R_1$, which will handle
+the \code{-} operator. But then for the recursive method call, it will
+dispatch back to \code{interp-exp} for $R_2$, where the \code{If} will
+be correctly handled. Thus, method overriding gives us the open
+recursion that we need to implement our interpreters in an extensible
+way.
 
 \newpage
 
@@ -3840,9 +3831,9 @@ shown in Figure~\ref{fig:reg-alloc-passes}.
 \path[->,bend left=15] (R1-2) edge [above] node {\ttfamily\footnotesize remove-complex.} (R1-3);
 \path[->,bend left=15] (R1-3) edge [right] node {\ttfamily\footnotesize explicate-control} (C0-1);
 \path[->,bend right=15] (C0-1) edge [left] node {\ttfamily\footnotesize select-instr.} (x86-2);
-\path[->,bend left=15] (x86-2) edge [right] node {\ttfamily\footnotesize\color{red} uncover-live} (x86-2-1);
-\path[->,bend right=15] (x86-2-1) edge [below] node {\ttfamily\footnotesize\color{red} build-inter.} (x86-2-2);
-\path[->,bend right=15] (x86-2-2) edge [right] node {\ttfamily\footnotesize\color{red} allocate-reg.} (x86-3);
+\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-inter.} (x86-2-2);
+\path[->,bend right=15] (x86-2-2) edge [right] node {\ttfamily\footnotesize allocate-reg.} (x86-3);
 \path[->,bend left=15] (x86-3) edge [above] node {\ttfamily\footnotesize patch-instr.} (x86-4);
 \path[->,bend left=15] (x86-4) edge [right] node {\ttfamily\footnotesize print-x86} (x86-5);
 \end{tikzpicture}
@@ -5518,17 +5509,17 @@ Test your compiler using your previously created programs on the
 \node (x86-2-1) at (3,-4)  {\large $\text{x86}^{*}_1$};
 \node (x86-2-2) at (6,-4)  {\large $\text{x86}^{*}_1$};
 
-\path[->,bend left=15] (R2) edge [above] node {\ttfamily\footnotesize\color{red} type-check} (R2-2);
-\path[->,bend left=15] (R2-2) edge [above] node {\ttfamily\footnotesize\color{red} shrink} (R2-3);
+\path[->,bend left=15] (R2) edge [above] node {\ttfamily\footnotesize type-check} (R2-2);
+\path[->,bend left=15] (R2-2) edge [above] node {\ttfamily\footnotesize shrink} (R2-3);
 \path[->,bend left=15] (R2-3) edge [above] node {\ttfamily\footnotesize uniquify} (R2-4);
 \path[->,bend left=15] (R2-4) edge [above] node {\ttfamily\footnotesize remove-complex.} (R2-5);
-\path[->,bend left=15] (R2-5) edge [left] node {\ttfamily\footnotesize\color{red} explicate-control} (C1-1);
-\path[->,bend right=15] (C1-1) edge [left] node {\ttfamily\footnotesize\color{red} select-instructions} (x86-2);
-\path[->,bend left=15] (x86-2) edge [right] node {\ttfamily\footnotesize\color{red} uncover-live} (x86-2-1);
+\path[->,bend left=15] (R2-5) edge [left] node {\ttfamily\footnotesize explicate-control} (C1-1);
+\path[->,bend right=15] (C1-1) edge [left] 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-inter.} (x86-2-2);
 \path[->,bend right=15] (x86-2-2) edge [right] node {\ttfamily\footnotesize allocate-reg.} (x86-3);
-\path[->,bend left=15] (x86-3) edge [above] node {\ttfamily\footnotesize\color{red} patch-instr.} (x86-4);
-\path[->,bend left=15] (x86-4) edge [right] node {\ttfamily\footnotesize\color{red} print-x86 } (x86-5);
+\path[->,bend left=15] (x86-3) edge [above] node {\ttfamily\footnotesize patch-instr.} (x86-4);
+\path[->,bend left=15] (x86-4) edge [right] node {\ttfamily\footnotesize print-x86 } (x86-5);
 \end{tikzpicture}
 \caption{Diagram of the passes for $R_2$, a language with conditionals.}
  \label{fig:R2-passes}
@@ -7029,18 +7020,18 @@ conclusion:
 \node (x86-2-1) at (3,-4)  {\large $\text{x86}^{*}_2$};
 \node (x86-2-2) at (6,-4)  {\large $\text{x86}^{*}_2$};
 
-%\path[->,bend left=15] (R3) edge [above] node {\ttfamily\footnotesize\color{red} type-check} (R3-2);
+%\path[->,bend left=15] (R3) edge [above] node {\ttfamily\footnotesize type-check} (R3-2);
 \path[->,bend left=15] (R3) edge [above] node {\ttfamily\footnotesize shrink} (R3-2);
 \path[->,bend left=15] (R3-2) edge [above] node {\ttfamily\footnotesize uniquify} (R3-3);
-\path[->,bend left=15] (R3-3) edge [above] node {\ttfamily\footnotesize\color{red} expose-alloc.} (R3-4);
+\path[->,bend left=15] (R3-3) edge [above] node {\ttfamily\footnotesize expose-alloc.} (R3-4);
 \path[->,bend left=15] (R3-4) edge [above] node {\ttfamily\footnotesize remove-complex.} (R3-5);
 \path[->,bend left=20] (R3-5) edge [left] node {\ttfamily\footnotesize explicate-control} (C2-4);
-\path[->,bend left=15] (C2-4) edge [right] node {\ttfamily\footnotesize\color{red} select-instr.} (x86-2);
+\path[->,bend left=15] (C2-4) edge [right] node {\ttfamily\footnotesize select-instr.} (x86-2);
 \path[->,bend right=15] (x86-2) edge [left] node {\ttfamily\footnotesize uncover-live} (x86-2-1);
-\path[->,bend right=15] (x86-2-1) edge [below] node {\ttfamily\footnotesize\color{red} build-inter.} (x86-2-2);
-\path[->,bend right=15] (x86-2-2) edge [right] node {\ttfamily\footnotesize\color{red} allocate-reg.} (x86-3);
+\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 [right] node {\ttfamily\footnotesize allocate-reg.} (x86-3);
 \path[->,bend left=15] (x86-3) edge [above] node {\ttfamily\footnotesize patch-instr.} (x86-4);
-\path[->,bend left=15] (x86-4) edge [right] node {\ttfamily\footnotesize\color{red} print-x86} (x86-5);
+\path[->,bend left=15] (x86-4) edge [right] node {\ttfamily\footnotesize print-x86} (x86-5);
 \end{tikzpicture}
 \caption{Diagram of the passes for $R_3$, a language with tuples.}
 \label{fig:R3-passes}
@@ -8253,8 +8244,8 @@ previously created test programs.
 \begin{figure}[tbp]
 \begin{tikzpicture}[baseline=(current  bounding  box.center)]
 \node (R4) at (0,2)  {\large $R_4$};
-\node (R4-2) at (3,2)  {\large $R_4$};
-%\node (R4-3) at (6,2)  {\large $R_4$};
+\node (R4-1) at (3,2)  {\large $R_4$};
+\node (R4-2) at (6,2)  {\large $R_4$};
 \node (F1-1) at (12,0)  {\large $F_1$};
 \node (F1-2) at (9,0)  {\large $F_1$};
 \node (F1-3) at (6,0)  {\large $F_1$};
@@ -8269,31 +8260,31 @@ previously created test programs.
 \node (x86-2-1) at (3,-6)  {\large $\text{x86}^{*}_3$};
 \node (x86-2-2) at (6,-6)  {\large $\text{x86}^{*}_3$};
 
-%\path[->,bend left=15] (R4) edge [above] node
-%     {\ttfamily\footnotesize\color{red} type-check} (R4-2);
 \path[->,bend left=15] (R4) edge [above] node
+     {\ttfamily\footnotesize shrink} (R4-1);
+\path[->,bend left=15] (R4-1) edge [above] node
      {\ttfamily\footnotesize uniquify} (R4-2);
 \path[->,bend left=15] (R4-2) edge [right] node
-     {\ttfamily\footnotesize\color{red} reveal-functions} (F1-1);
+     {\ttfamily\footnotesize ~~reveal-functions} (F1-1);
 \path[->,bend left=15] (F1-1) edge [below] node
-     {\ttfamily\footnotesize\color{red} limit-functions} (F1-2);
+     {\ttfamily\footnotesize limit-functions} (F1-2);
 \path[->,bend right=15] (F1-2) edge [above] node
      {\ttfamily\footnotesize expose-alloc.} (F1-3);
 \path[->,bend right=15] (F1-3) edge [above] node
-     {\ttfamily\footnotesize\color{red} remove-complex.} (F1-4);
+     {\ttfamily\footnotesize remove-complex.} (F1-4);
 \path[->,bend left=15] (F1-4) edge [right] node
-     {\ttfamily\footnotesize\color{red} explicate-control} (C3-2);
+     {\ttfamily\footnotesize explicate-control} (C3-2);
 \path[->,bend right=15] (C3-2) edge [left] node
-     {\ttfamily\footnotesize\color{red} select-instr.} (x86-2);
+     {\ttfamily\footnotesize select-instr.} (x86-2);
 \path[->,bend left=15] (x86-2) edge [left] node
-     {\ttfamily\footnotesize\color{red} uncover-live} (x86-2-1);
+     {\ttfamily\footnotesize uncover-live} (x86-2-1);
 \path[->,bend right=15] (x86-2-1) edge [below] node 
-     {\ttfamily\footnotesize \color{red}build-inter.} (x86-2-2);
+     {\ttfamily\footnotesize build-inter.} (x86-2-2);
 \path[->,bend right=15] (x86-2-2) edge [left] node
      {\ttfamily\footnotesize allocate-reg.} (x86-3);
 \path[->,bend left=15] (x86-3) edge [above] node
-     {\ttfamily\footnotesize\color{red} patch-instr.} (x86-4);
-\path[->,bend right=15] (x86-4) edge [left] node {\ttfamily\footnotesize\color{red} print-x86} (x86-5);
+     {\ttfamily\footnotesize patch-instr.} (x86-4);
+\path[->,bend right=15] (x86-4) edge [left] node {\ttfamily\footnotesize print-x86} (x86-5);
 \end{tikzpicture}
 \caption{Diagram of the passes for $R_4$, a language with functions.}
 \label{fig:R4-passes}
@@ -8949,19 +8940,19 @@ shift it by $57$ bits to the right.
 \path[->,bend left=15] (R4-2) edge [above] node
      {\ttfamily\footnotesize uniquify} (R4-3);
 \path[->,bend left=15] (R4-3) edge [right] node
-     {\ttfamily\footnotesize\color{red} reveal-functions} (F1-1);
+     {\ttfamily\footnotesize reveal-functions} (F1-1);
 \path[->,bend left=15] (F1-1) edge [below] node
-     {\ttfamily\footnotesize\color{red} convert-to-clos.} (F1-2);
+     {\ttfamily\footnotesize convert-to-clos.} (F1-2);
 \path[->,bend right=15] (F1-2) edge [above] node
      {\ttfamily\footnotesize limit-fun.} (F1-3);
 \path[->,bend right=15] (F1-3) edge [above] node
-     {\ttfamily\footnotesize\color{red} expose-alloc.} (F1-4);
+     {\ttfamily\footnotesize expose-alloc.} (F1-4);
 \path[->,bend right=15] (F1-4) edge [above] node
      {\ttfamily\footnotesize remove-complex.} (F1-5);
 \path[->,bend right=15] (F1-5) edge [right] node
      {\ttfamily\footnotesize explicate-control} (C3-2);
 \path[->,bend left=15] (C3-2) edge [left] node
-     {\ttfamily\footnotesize\color{red} select-instr.} (x86-2);
+     {\ttfamily\footnotesize select-instr.} (x86-2);
 \path[->,bend right=15] (x86-2) edge [left] node
      {\ttfamily\footnotesize uncover-live} (x86-2-1);
 \path[->,bend right=15] (x86-2-1) edge [below] node 
@@ -9998,7 +9989,7 @@ The \code{analyze-dataflow} function has four parameters.
 \node (x86-2-2) at (6,-6)  {\large $\text{x86}^{*}_3$};
 
 %% \path[->,bend left=15] (R4) edge [above] node
-%%      {\ttfamily\footnotesize\color{red} type-check} (R4-2);
+%%      {\ttfamily\footnotesize type-check} (R4-2);
 \path[->,bend left=15] (R4) edge [above] node
      {\ttfamily\footnotesize shrink} (R4-2);
 \path[->,bend left=15] (R4-2) edge [above] node
@@ -10006,7 +9997,7 @@ The \code{analyze-dataflow} function has four parameters.
 \path[->,bend left=15] (R4-3) edge [above] node
      {\ttfamily\footnotesize reveal-functions} (R4-4);
 \path[->,bend left=15] (R4-4) edge [right] node
-     {\ttfamily\footnotesize\color{red} convert-assignments} (F1-1);
+     {\ttfamily\footnotesize convert-assignments} (F1-1);
 \path[->,bend left=15] (F1-1) edge [below] node
      {\ttfamily\footnotesize convert-to-clos.} (F1-2);
 \path[->,bend right=15] (F1-2) edge [above] node
@@ -10014,13 +10005,13 @@ The \code{analyze-dataflow} function has four parameters.
 \path[->,bend right=15] (F1-3) edge [above] node
      {\ttfamily\footnotesize expose-alloc.} (F1-4);
 \path[->,bend right=15] (F1-4) edge [above] node
-     {\ttfamily\footnotesize\color{red} remove-complex.} (F1-5);
+     {\ttfamily\footnotesize remove-complex.} (F1-5);
 \path[->,bend right=15] (F1-5) edge [right] node
-     {\ttfamily\footnotesize\color{red} explicate-control} (C3-2);
+     {\ttfamily\footnotesize explicate-control} (C3-2);
 \path[->,bend left=15] (C3-2) edge [left] node
-     {\ttfamily\footnotesize\color{red} select-instr.} (x86-2);
+     {\ttfamily\footnotesize select-instr.} (x86-2);
 \path[->,bend right=15] (x86-2) edge [left] node
-     {\ttfamily\footnotesize\color{red} uncover-live} (x86-2-1);
+     {\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
@@ -11051,11 +11042,11 @@ completion without error.
 \path[->,bend left=15] (R4-3) edge [above] node
      {\ttfamily\footnotesize reveal-functions} (R4-4);
 \path[->,bend right=15] (R4-4) edge [left] node
-     {\ttfamily\footnotesize\color{red} cast-insert} (R4-5);
+     {\ttfamily\footnotesize cast-insert} (R4-5);
 \path[->,bend left=15] (R4-5) edge [above] node
-     {\ttfamily\footnotesize\color{red} check-bounds} (R4-6);
+     {\ttfamily\footnotesize check-bounds} (R4-6);
 \path[->,bend left=15] (R4-6) edge [left] node
-     {\ttfamily\footnotesize\color{red} reveal-casts} (R4-7);
+     {\ttfamily\footnotesize reveal-casts} (R4-7);
      
 \path[->,bend left=15] (R4-7) edge [below] node
      {\ttfamily\footnotesize convert-to-clos.} (F1-2);
@@ -11068,7 +11059,7 @@ completion without error.
 \path[->,bend right=15] (F1-5) edge [right] node
      {\ttfamily\footnotesize explicate-control} (C3-2);
 \path[->,bend left=15] (C3-2) edge [left] node
-     {\ttfamily\footnotesize\color{red} select-instr.} (x86-2);
+     {\ttfamily\footnotesize select-instr.} (x86-2);
 \path[->,bend right=15] (x86-2) edge [left] node
      {\ttfamily\footnotesize uncover-live} (x86-2-1);
 \path[->,bend right=15] (x86-2-1) edge [below] node