|
@@ -134,7 +134,7 @@ showstringspaces=false
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
|
|
\title{\Huge \textbf{Essentials of Compilation} \\
|
|
\title{\Huge \textbf{Essentials of Compilation} \\
|
|
- \huge An Incremental Approach}
|
|
|
|
|
|
+ \huge The Incremental, Nano-Pass Approach}
|
|
|
|
|
|
\author{\textsc{Jeremy G. Siek} \\
|
|
\author{\textsc{Jeremy G. Siek} \\
|
|
%\thanks{\url{http://homes.soic.indiana.edu/jsiek/}} \\
|
|
%\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
|
|
while also including elements of effective real-world compilers. One
|
|
of Friedman's ideas was to split the compiler into many small
|
|
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
|
|
``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
|
|
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
|
|
During that time, another graduate student named Abdulaziz Ghuloum
|
|
observed that the front-to-back organization of the course made it
|
|
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
|
|
teaching the course organized in this way, and even better, many of
|
|
the students learned a lot and got excited about compilers.
|
|
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
|
|
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}
|
|
\section*{Prerequisites}
|
|
|
|
|
|
@@ -289,11 +291,12 @@ is to run a virtual machine with Linux as the guest operating system.
|
|
\section*{Acknowledgments}
|
|
\section*{Acknowledgments}
|
|
|
|
|
|
Many people have contributed to the ideas, techniques, and
|
|
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{}\\
|
|
\mbox{}\\
|
|
\noindent Jeremy G. Siek \\
|
|
\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
|
|
write down and talk about programs. Inside the compiler, we use
|
|
\emph{abstract syntax trees} (ASTs) to represent programs in a way
|
|
\emph{abstract syntax trees} (ASTs) to represent programs in a way
|
|
that efficiently supports the operations that the compiler needs to
|
|
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,
|
|
ASTs can be represented in many different ways inside the compiler,
|
|
depending on the programming language used to write 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
|
|
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}
|
|
\section{Abstract Syntax Trees and Racket Structures}
|
|
\label{sec:ast}
|
|
\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{center}
|
|
\begin{minipage}{0.4\textwidth}
|
|
\begin{minipage}{0.4\textwidth}
|
|
\begin{lstlisting}
|
|
\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.
|
|
The following is the \code{struct} definition for primitives operations.
|
|
\begin{lstlisting}
|
|
\begin{lstlisting}
|
|
-(struct Prim (op arg*))
|
|
|
|
|
|
+(struct Prim (op args))
|
|
\end{lstlisting}
|
|
\end{lstlisting}
|
|
A primitive operation node includes an operator symbol \code{op}
|
|
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))}.
|
|
an AST that negates the number $8$, we write \code{(Prim '- (list eight))}.
|
|
\begin{lstlisting}
|
|
\begin{lstlisting}
|
|
(define neg-eight (Prim '- (list eight)))
|
|
(define neg-eight (Prim '- (list eight)))
|
|
@@ -521,13 +517,12 @@ instance of the \code{Int} structure is an expression:
|
|
\end{equation}
|
|
\end{equation}
|
|
%
|
|
%
|
|
Each rule has a left-hand-side and a right-hand-side. The way to read
|
|
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
|
|
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
|
|
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.
|
|
the rule to be applicable.
|
|
\index{terminal}
|
|
\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{center}
|
|
\begin{minipage}{0.4\textwidth}
|
|
\begin{minipage}{0.4\textwidth}
|
|
\begin{lstlisting}
|
|
\begin{lstlisting}
|
|
@@ -586,8 +580,8 @@ The next grammar rule defines addition expressions:
|
|
\end{equation}
|
|
\end{equation}
|
|
We can now justify that the AST \eqref{eq:arith-prog} is an $\Exp$ in
|
|
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
|
|
$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
|
|
to show that
|
|
\begin{lstlisting}
|
|
\begin{lstlisting}
|
|
(Prim '+ (list (Prim 'read '()) (Prim '- (list (Int 8)))))
|
|
(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}
|
|
\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
|
|
R_0 &::=& \Exp
|
|
\end{array}
|
|
\end{array}
|
|
\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}.)
|
|
for a complete description of \code{match}.)
|
|
%
|
|
%
|
|
The body of a match clause may contain arbitrary Racket code. The
|
|
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
|
|
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{center}
|
|
\begin{minipage}{0.6\textwidth}
|
|
\begin{minipage}{0.6\textwidth}
|
|
\begin{lstlisting}
|
|
\begin{lstlisting}
|
|
@@ -719,8 +714,8 @@ body of the first clause that matches is executed. The output of
|
|
(match arith
|
|
(match arith
|
|
[(Int n) #t]
|
|
[(Int n) #t]
|
|
[(Prim 'read '()) #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 'read '()))
|
|
(leaf? (Prim '- (list (Int 8))))
|
|
(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
|
|
Figure~\ref{fig:r0-syntax}. The $\Exp$ non-terminal has 4
|
|
alternatives, so the \code{match} has 4 clauses. The pattern in each
|
|
alternatives, so the \code{match} has 4 clauses. The pattern in each
|
|
clause corresponds to the right-hand side of a grammar rule. For
|
|
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
|
|
right-hand side $\ADD{\Exp}{\Exp}$. When translating from grammars to
|
|
patterns, replace non-terminals such as $\Exp$ with pattern variables
|
|
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}
|
|
\label{sec:recursion}
|
|
\index{recursive function}
|
|
\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$
|
|
an arbitrary value and determines whether or not it is an $R_0$
|
|
expression.
|
|
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{center}
|
|
\begin{minipage}{0.7\textwidth}
|
|
\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:
|
|
For example, the above function is subtly wrong:
|
|
\lstinline{(R0? (Program '() (Program '() (Int 3))))}
|
|
\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}
|
|
\section{Interpreters}
|
|
\label{sec:interp-R0}
|
|
\label{sec:interp-R0}
|
|
\index{interpreter}
|
|
\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
|
|
specification of the language. For example, the Scheme language is
|
|
defined in the report by \cite{SPERBER:2009aa}. The Racket 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
|
|
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
|
|
input program followed by a call to the \lstinline{interp-exp} helper
|
|
function, which in turn has one match clause per grammar rule for
|
|
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,
|
|
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
|
|
the interpreter for $R_2$ handle all of the new features in that
|
|
language and then have a default case that dispatches to the
|
|
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{center}
|
|
\begin{minipage}{0.45\textwidth}
|
|
\begin{minipage}{0.45\textwidth}
|
|
\begin{lstlisting}
|
|
\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
|
|
always invoke the ``top'' interpreter, even if the recursive call is
|
|
made from interpreters that are lower down. Object-oriented languages
|
|
made from interpreters that are lower down. Object-oriented languages
|
|
provide open recursion in the form of method overriding\index{method
|
|
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
|
|
$R_1$ and $R_2$ using the
|
|
\href{https://docs.racket-lang.org/guide/classes.html}{\code{class}}
|
|
\href{https://docs.racket-lang.org/guide/classes.html}{\code{class}}
|
|
\index{class} feature of Racket. We define one class for each
|
|
\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}
|
|
\begin{lstlisting}
|
|
(send (new interp-R2-class) interp-exp e0)
|
|
(send (new interp-R2-class) interp-exp e0)
|
|
\end{lstlisting}
|
|
\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
|
|
\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-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 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 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-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);
|
|
\path[->,bend left=15] (x86-4) edge [right] node {\ttfamily\footnotesize print-x86} (x86-5);
|
|
\end{tikzpicture}
|
|
\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-1) at (3,-4) {\large $\text{x86}^{*}_1$};
|
|
\node (x86-2-2) at (6,-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-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-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-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 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}
|
|
\end{tikzpicture}
|
|
\caption{Diagram of the passes for $R_2$, a language with conditionals.}
|
|
\caption{Diagram of the passes for $R_2$, a language with conditionals.}
|
|
\label{fig:R2-passes}
|
|
\label{fig:R2-passes}
|
|
@@ -7029,18 +7020,18 @@ conclusion:
|
|
\node (x86-2-1) at (3,-4) {\large $\text{x86}^{*}_2$};
|
|
\node (x86-2-1) at (3,-4) {\large $\text{x86}^{*}_2$};
|
|
\node (x86-2-2) at (6,-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) 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-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=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=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) 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-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}
|
|
\end{tikzpicture}
|
|
\caption{Diagram of the passes for $R_3$, a language with tuples.}
|
|
\caption{Diagram of the passes for $R_3$, a language with tuples.}
|
|
\label{fig:R3-passes}
|
|
\label{fig:R3-passes}
|
|
@@ -8253,8 +8244,8 @@ previously created test programs.
|
|
\begin{figure}[tbp]
|
|
\begin{figure}[tbp]
|
|
\begin{tikzpicture}[baseline=(current bounding box.center)]
|
|
\begin{tikzpicture}[baseline=(current bounding box.center)]
|
|
\node (R4) at (0,2) {\large $R_4$};
|
|
\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-1) at (12,0) {\large $F_1$};
|
|
\node (F1-2) at (9,0) {\large $F_1$};
|
|
\node (F1-2) at (9,0) {\large $F_1$};
|
|
\node (F1-3) at (6,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-1) at (3,-6) {\large $\text{x86}^{*}_3$};
|
|
\node (x86-2-2) at (6,-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
|
|
\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);
|
|
{\ttfamily\footnotesize uniquify} (R4-2);
|
|
\path[->,bend left=15] (R4-2) edge [right] node
|
|
\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
|
|
\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
|
|
\path[->,bend right=15] (F1-2) edge [above] node
|
|
{\ttfamily\footnotesize expose-alloc.} (F1-3);
|
|
{\ttfamily\footnotesize expose-alloc.} (F1-3);
|
|
\path[->,bend right=15] (F1-3) edge [above] node
|
|
\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
|
|
\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
|
|
\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
|
|
\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
|
|
\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
|
|
\path[->,bend right=15] (x86-2-2) edge [left] node
|
|
{\ttfamily\footnotesize allocate-reg.} (x86-3);
|
|
{\ttfamily\footnotesize allocate-reg.} (x86-3);
|
|
\path[->,bend left=15] (x86-3) edge [above] node
|
|
\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}
|
|
\end{tikzpicture}
|
|
\caption{Diagram of the passes for $R_4$, a language with functions.}
|
|
\caption{Diagram of the passes for $R_4$, a language with functions.}
|
|
\label{fig:R4-passes}
|
|
\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
|
|
\path[->,bend left=15] (R4-2) edge [above] node
|
|
{\ttfamily\footnotesize uniquify} (R4-3);
|
|
{\ttfamily\footnotesize uniquify} (R4-3);
|
|
\path[->,bend left=15] (R4-3) edge [right] node
|
|
\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
|
|
\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
|
|
\path[->,bend right=15] (F1-2) edge [above] node
|
|
{\ttfamily\footnotesize limit-fun.} (F1-3);
|
|
{\ttfamily\footnotesize limit-fun.} (F1-3);
|
|
\path[->,bend right=15] (F1-3) edge [above] node
|
|
\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
|
|
\path[->,bend right=15] (F1-4) edge [above] node
|
|
{\ttfamily\footnotesize remove-complex.} (F1-5);
|
|
{\ttfamily\footnotesize remove-complex.} (F1-5);
|
|
\path[->,bend right=15] (F1-5) edge [right] node
|
|
\path[->,bend right=15] (F1-5) edge [right] node
|
|
{\ttfamily\footnotesize explicate-control} (C3-2);
|
|
{\ttfamily\footnotesize explicate-control} (C3-2);
|
|
\path[->,bend left=15] (C3-2) edge [left] node
|
|
\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
|
|
\path[->,bend right=15] (x86-2) edge [left] node
|
|
{\ttfamily\footnotesize uncover-live} (x86-2-1);
|
|
{\ttfamily\footnotesize uncover-live} (x86-2-1);
|
|
\path[->,bend right=15] (x86-2-1) edge [below] node
|
|
\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$};
|
|
\node (x86-2-2) at (6,-6) {\large $\text{x86}^{*}_3$};
|
|
|
|
|
|
%% \path[->,bend left=15] (R4) edge [above] node
|
|
%% \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
|
|
\path[->,bend left=15] (R4) edge [above] node
|
|
{\ttfamily\footnotesize shrink} (R4-2);
|
|
{\ttfamily\footnotesize shrink} (R4-2);
|
|
\path[->,bend left=15] (R4-2) edge [above] node
|
|
\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
|
|
\path[->,bend left=15] (R4-3) edge [above] node
|
|
{\ttfamily\footnotesize reveal-functions} (R4-4);
|
|
{\ttfamily\footnotesize reveal-functions} (R4-4);
|
|
\path[->,bend left=15] (R4-4) edge [right] node
|
|
\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
|
|
\path[->,bend left=15] (F1-1) edge [below] node
|
|
{\ttfamily\footnotesize convert-to-clos.} (F1-2);
|
|
{\ttfamily\footnotesize convert-to-clos.} (F1-2);
|
|
\path[->,bend right=15] (F1-2) edge [above] node
|
|
\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
|
|
\path[->,bend right=15] (F1-3) edge [above] node
|
|
{\ttfamily\footnotesize expose-alloc.} (F1-4);
|
|
{\ttfamily\footnotesize expose-alloc.} (F1-4);
|
|
\path[->,bend right=15] (F1-4) edge [above] node
|
|
\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
|
|
\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
|
|
\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
|
|
\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
|
|
\path[->,bend right=15] (x86-2-1) edge [below] node
|
|
{\ttfamily\footnotesize build-inter.} (x86-2-2);
|
|
{\ttfamily\footnotesize build-inter.} (x86-2-2);
|
|
\path[->,bend right=15] (x86-2-2) edge [left] node
|
|
\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
|
|
\path[->,bend left=15] (R4-3) edge [above] node
|
|
{\ttfamily\footnotesize reveal-functions} (R4-4);
|
|
{\ttfamily\footnotesize reveal-functions} (R4-4);
|
|
\path[->,bend right=15] (R4-4) edge [left] node
|
|
\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
|
|
\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
|
|
\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
|
|
\path[->,bend left=15] (R4-7) edge [below] node
|
|
{\ttfamily\footnotesize convert-to-clos.} (F1-2);
|
|
{\ttfamily\footnotesize convert-to-clos.} (F1-2);
|
|
@@ -11068,7 +11059,7 @@ completion without error.
|
|
\path[->,bend right=15] (F1-5) edge [right] node
|
|
\path[->,bend right=15] (F1-5) edge [right] node
|
|
{\ttfamily\footnotesize explicate-control} (C3-2);
|
|
{\ttfamily\footnotesize explicate-control} (C3-2);
|
|
\path[->,bend left=15] (C3-2) edge [left] node
|
|
\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
|
|
\path[->,bend right=15] (x86-2) edge [left] node
|
|
{\ttfamily\footnotesize uncover-live} (x86-2-1);
|
|
{\ttfamily\footnotesize uncover-live} (x86-2-1);
|
|
\path[->,bend right=15] (x86-2-1) edge [below] node
|
|
\path[->,bend right=15] (x86-2-1) edge [below] node
|