浏览代码

edits to ch. 2

Jeremy Siek 3 年之前
父节点
当前提交
8fd5b830fd
共有 1 个文件被更改,包括 103 次插入68 次删除
  1. 103 68
      book.tex

+ 103 - 68
book.tex

@@ -2969,7 +2969,7 @@ print(tmp_1)
 \begin{array}{rcl}
 \begin{array}{rcl}
 \Atm &::=& \INT{\Int} \MID \VAR{\Var} \\  
 \Atm &::=& \INT{\Int} \MID \VAR{\Var} \\  
 \Exp{} &::=& \Atm \MID \READ{} \\
 \Exp{} &::=& \Atm \MID \READ{} \\
-       &\MID& \NEG{\Exp} \MID  \ADD{\Exp}{\Exp} \\
+       &\MID& \NEG{\Atm} \MID  \ADD{\Atm}{\Atm} \\
 \Stmt{} &::=& \PRINT{\Atm} \MID \EXPR{\Exp} \\
 \Stmt{} &::=& \PRINT{\Atm} \MID \EXPR{\Exp} \\
         &\MID& \ASSIGN{\VAR{\Var}}{\Exp}\\
         &\MID& \ASSIGN{\VAR{\Var}}{\Exp}\\
 \LangVarANFM{}  &::=& \PROGRAM{}{\Stmt^{*}}
 \LangVarANFM{}  &::=& \PROGRAM{}{\Stmt^{*}}
@@ -3061,11 +3061,14 @@ tmp_1
 %  
 %  
 \fi}
 \fi}
 
 
-Take special care of programs such as the following that \racket{bind
-  a variable to an atomic expression}\python{assign an atomic
-  expression to a variable}. You should leave such \racket{variable
-  bindings}\python{assignments} unchanged, as shown in the program on
-the right\\
+Take special care of programs such as the following that
+%
+\racket{bind a variable to an atomic expression}
+%
+\python{assign an atomic expression to a variable}.
+%
+You should leave such \racket{variable bindings}\python{assignments}
+unchanged, as shown in the program on the right\\
 %
 %
 {\if\edition\racketEd\color{olive}
 {\if\edition\racketEd\color{olive}
 \begin{transformation}
 \begin{transformation}
@@ -3098,8 +3101,8 @@ print(b)
 \end{lstlisting}
 \end{lstlisting}
 \end{transformation}
 \end{transformation}
 \fi}
 \fi}
-
-A careless implementation might produce the following output with
+%
+\noindent A careless implementation might produce the following output with
 unnecessary temporary variables.
 unnecessary temporary variables.
 \begin{center}
 \begin{center}
 \begin{minipage}{0.4\textwidth}
 \begin{minipage}{0.4\textwidth}
@@ -3146,7 +3149,7 @@ intermediate programs, place \lstinline{(debug-level 1)} before the call to
 \fi}
 \fi}
 %
 %
 {\if\edition\pythonEd
 {\if\edition\pythonEd
-  Implement the \code{remove\_complex\_operands} function in
+  Implement the \code{remove\_complex\_operands} pass in
   \code{compiler.py}, creating auxiliary functions for each
   \code{compiler.py}, creating auxiliary functions for each
   non-terminal in the grammar, i.e., \code{rco\_exp}
   non-terminal in the grammar, i.e., \code{rco\_exp}
   and \code{rco\_stmt}.
   and \code{rco\_stmt}.
@@ -3159,11 +3162,10 @@ intermediate programs, place \lstinline{(debug-level 1)} before the call to
 \label{ex:Lvar}
 \label{ex:Lvar}
 
 
 Create five \LangVar{} programs that exercise the most interesting
 Create five \LangVar{} programs that exercise the most interesting
-parts of the Remove Complex Operands pass.  The five programs should
-be placed in the subdirectory named \key{tests} and the file names
-should start with \code{var\_test\_} followed by a unique integer and
-end with the file extension \key{.py}.
-% TODO: come up with passes infrastructure for Python -Jeremy
+parts of the \code{remove\_complex\_operands} pass.  The five programs
+should be placed in the subdirectory named \key{tests} and the file
+names should start with \code{var\_test\_} followed by a unique
+integer and end with the file extension \key{.py}.
 %% The \key{run-tests.rkt} script in the support code checks whether the
 %% The \key{run-tests.rkt} script in the support code checks whether the
 %% output programs produce the same result as the input programs.  The
 %% output programs produce the same result as the input programs.  The
 %% script uses the \key{interp-tests} function
 %% script uses the \key{interp-tests} function
@@ -3322,61 +3324,63 @@ the same and integer constants change to immediates:
 $\INT{n}$ changes to $\IMM{n}$.}
 $\INT{n}$ changes to $\IMM{n}$.}
 
 
 We consider the cases for the $\Stmt$ non-terminal, starting with
 We consider the cases for the $\Stmt$ non-terminal, starting with
-arithmetic operations. For example, consider the addition
-operation. We can use the \key{addq} instruction, but it performs an
-in-place update.  So we could move $\itm{arg}_1$ into the left-hand
-side \itm{var} and then add $\itm{arg}_2$ to \itm{var}.
+arithmetic operations. For example, consider the addition operation
+below, on the left side. There is an \key{addq} instruction in x86,
+but it performs an in-place update.  So we could move $\Arg_1$
+into the left-hand side \itm{var} and then add $\Arg_2$ to
+\itm{var}, where $\Arg_1$ and $\Arg_2$ are the translations of
+$\Atm_1$ and $\Atm_2$ respectively.
 \begin{transformation}
 \begin{transformation}
 {\if\edition\racketEd\color{olive}    
 {\if\edition\racketEd\color{olive}    
 \begin{lstlisting}
 \begin{lstlisting}
-|$\itm{var}$| = (+ |$\itm{arg}_1$| |$\itm{arg}_2$|);
+|$\itm{var}$| = (+ |$\Atm_1$| |$\Atm_2$|);
 \end{lstlisting}
 \end{lstlisting}
 \fi}
 \fi}
 {\if\edition\pythonEd
 {\if\edition\pythonEd
 \begin{lstlisting}
 \begin{lstlisting}
-|$\itm{var}$| = |$\itm{arg}_1$| + |$\itm{arg}_2$|
+|$\itm{var}$| = |$\Atm_1$| + |$\Atm_2$|
 \end{lstlisting}
 \end{lstlisting}
 \fi}
 \fi}
 \compilesto
 \compilesto
 \begin{lstlisting}
 \begin{lstlisting}
-movq |$\itm{arg}_1$|, |$\itm{var}$|
-addq |$\itm{arg}_2$|, |$\itm{var}$|
+movq |$\Arg_1$|, |$\itm{var}$|
+addq |$\Arg_2$|, |$\itm{var}$|
 \end{lstlisting}
 \end{lstlisting}
 \end{transformation}
 \end{transformation}
 There are also cases that require special care to avoid generating
 There are also cases that require special care to avoid generating
 needlessly complicated code. For example, if one of the arguments of
 needlessly complicated code. For example, if one of the arguments of
 the addition is the same variable as the left-hand side of the
 the addition is the same variable as the left-hand side of the
-assignment, then there is no need for the extra move instruction.  The
-assignment statement can be translated into a single \key{addq}
-instruction as follows.
+assignment, as shown below, then there is no need for the extra move
+instruction.  The assignment statement can be translated into a single
+\key{addq} instruction as follows.
 \begin{transformation}
 \begin{transformation}
 {\if\edition\racketEd\color{olive}
 {\if\edition\racketEd\color{olive}
 \begin{lstlisting}
 \begin{lstlisting}
-|$\itm{var}$| = (+ |$\itm{arg}_1$| |$\itm{var}$|);
+|$\itm{var}$| = (+ |$\Atm_1$| |$\itm{var}$|);
 \end{lstlisting}
 \end{lstlisting}
 \fi}
 \fi}
 {\if\edition\pythonEd
 {\if\edition\pythonEd
 \begin{lstlisting}
 \begin{lstlisting}
-|$\itm{var}$| = |$\itm{arg}_1$| + |$\itm{var}$|
+|$\itm{var}$| = |$\Atm_1$| + |$\itm{var}$|
 \end{lstlisting}
 \end{lstlisting}
 \fi}    
 \fi}    
 \compilesto
 \compilesto
 \begin{lstlisting}
 \begin{lstlisting}
-addq |$\itm{arg}_1$|, |$\itm{var}$|
+addq |$\Arg_1$|, |$\itm{var}$|
 \end{lstlisting}
 \end{lstlisting}
 \end{transformation}
 \end{transformation}
 
 
-The \key{read} operation does not have a direct counterpart in x86
+The \READOP{} operation does not have a direct counterpart in x86
 assembly, so we provide this functionality with the function
 assembly, so we provide this functionality with the function
 \code{read\_int} in the file \code{runtime.c}, written in
 \code{read\_int} in the file \code{runtime.c}, written in
 C~\citep{Kernighan:1988nx}. In general, we refer to all of the
 C~\citep{Kernighan:1988nx}. In general, we refer to all of the
 functionality in this file as the \emph{runtime system}\index{subject}{runtime
 functionality in this file as the \emph{runtime system}\index{subject}{runtime
   system}, or simply the \emph{runtime} for short. When compiling your
   system}, or simply the \emph{runtime} for short. When compiling your
 generated x86 assembly code, you need to compile \code{runtime.c} to
 generated x86 assembly code, you need to compile \code{runtime.c} to
-\code{runtime.o} (an ``object file'', using \code{gcc} option
+\code{runtime.o} (an ``object file'', using \code{gcc} with option
 \code{-c}) and link it into the executable. For our purposes of code
 \code{-c}) and link it into the executable. For our purposes of code
 generation, all you need to do is translate an assignment of
 generation, all you need to do is translate an assignment of
-\key{read} into a call to the \code{read\_int} function followed by a
+\READOP{} into a call to the \code{read\_int} function followed by a
 move from \code{rax} to the left-hand-side variable.  (Recall that the
 move from \code{rax} to the left-hand-side variable.  (Recall that the
 return value of a function goes into \code{rax}.)  
 return value of a function goes into \code{rax}.)  
 \begin{transformation}
 \begin{transformation}
@@ -3397,6 +3401,27 @@ movq %rax, |$\itm{var}$|
 \end{lstlisting}
 \end{lstlisting}
 \end{transformation}
 \end{transformation}
 
 
+{\if\edition\pythonEd
+%
+Similarly, we translate the \code{print} operation, shown below, into
+a call to the \code{print\_int} function defined in \code{runtime.c}.
+In x86, the first six arguments to functions are passed in registers,
+with the first argument passed in register \code{rdi}. So we move the
+$\Arg$ into \code{rdi} and then call \code{print\_int} using the
+\code{callq} instruction.
+\begin{transformation}
+\begin{lstlisting}
+print(|$\Atm$|)    
+\end{lstlisting}
+\compilesto
+\begin{lstlisting}
+movq |$\Arg$|, %rdi
+callq print_int  
+\end{lstlisting}
+\end{transformation}
+%
+\fi}  
+
 {\if\edition\racketEd\color{olive}
 {\if\edition\racketEd\color{olive}
 There are two cases for the $\Tail$ non-terminal: \key{Return} and
 There are two cases for the $\Tail$ non-terminal: \key{Return} and
 \key{Seq}. Regarding \key{Return}, we recommend treating it as an
 \key{Seq}. Regarding \key{Return}, we recommend treating it as an
@@ -3461,37 +3486,34 @@ b = a
 print(b)
 print(b)
 \end{lstlisting}
 \end{lstlisting}
 \fi}
 \fi}
-The output of \code{select\_instructions} is shown on the left and the
-output of \code{assign\_homes} on the right.  In this example, we
-assign variable \code{a} to stack location \code{-8(\%rbp)} and
-variable \code{b} to location \code{-16(\%rbp)}.
+%
+The output of \code{select\_instructions} is shown below, on the left,
+and the output of \code{assign\_homes} is on the right.  In this
+example, we assign variable \code{a} to stack location
+\code{-8(\%rbp)} and variable \code{b} to location \code{-16(\%rbp)}.
 \begin{transformation}
 \begin{transformation}
 \begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
 \begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
-start: 
-    movq $42, a
-    movq a, b
-    movq b, %rax
-    jmp conclusion
+movq $42, a
+movq a, b
+movq b, %rax
 \end{lstlisting}
 \end{lstlisting}
 \compilesto
 \compilesto
 %stack-space: 16
 %stack-space: 16
 \begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
 \begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
-start:
-    movq $42, -8(%rbp)
-    movq -8(%rbp), -16(%rbp)
-    movq -16(%rbp), %rax
-    jmp conclusion
+movq $42, -8(%rbp)
+movq -8(%rbp), -16(%rbp)
+movq -16(%rbp), %rax
 \end{lstlisting}
 \end{lstlisting}
 \end{transformation}
 \end{transformation}
 
 
 \racket{The \code{locals-types} entry in the $\itm{info}$ of the
 \racket{The \code{locals-types} entry in the $\itm{info}$ of the
-\code{X86Program} node is an alist mapping all the variables in the
-program to their types (for now just \code{Integer}).  The
-\code{assign\_homes} pass should replace all uses of those variables
-with stack locations.  As an aside, the \code{locals-types} entry is
-computed by \code{type-check-Cvar} in the support code, which installs
-it in the $\itm{info}$ field of the \code{CProgram} node, which should
-be propagated to the \code{X86Program} node.}
+  \code{X86Program} node is an alist mapping all the variables in the
+  program to their types (for now just \code{Integer}).  The
+  \code{assign\_homes} pass should replace all uses of those variables
+  with stack locations.  As an aside, the \code{locals-types} entry is
+  computed by \code{type-check-Cvar} in the support code, which
+  installs it in the $\itm{info}$ field of the \code{CProgram} node,
+  which should be propagated to the \code{X86Program} node.}
 %
 %
 \python{The \code{assign\_homes} pass should replace all uses of
 \python{The \code{assign\_homes} pass should replace all uses of
   variables with stack locations.}
   variables with stack locations.}
@@ -3511,8 +3533,8 @@ multiple of 16 bytes.\index{subject}{frame}
 \begin{exercise}\normalfont
 \begin{exercise}\normalfont
 Implement the \key{assign\_homes} pass in
 Implement the \key{assign\_homes} pass in
 \racket{\code{compiler.rkt}}\python{\code{compiler.py}}, defining
 \racket{\code{compiler.rkt}}\python{\code{compiler.py}}, defining
-auxiliary functions for the non-terminals \Arg{}, \Instr{}, and
-\Block{}.  We recommend that the auxiliary functions take an extra
+auxiliary functions for each of the non-terminals in the \LangXVar{}
+grammar.  We recommend that the auxiliary functions take an extra
 parameter that maps variable names to homes (stack locations for now).
 parameter that maps variable names to homes (stack locations for now).
 %
 %
 {\if\edition\racketEd\color{olive}
 {\if\edition\racketEd\color{olive}
@@ -3610,14 +3632,21 @@ programs.
 The last step of the compiler from \LangVar{} to x86 is to convert the
 The last step of the compiler from \LangVar{} to x86 is to convert the
 \LangXInt{} AST (defined in Figure~\ref{fig:x86-int-ast}) to the
 \LangXInt{} AST (defined in Figure~\ref{fig:x86-int-ast}) to the
 string representation (defined in
 string representation (defined in
-Figure~\ref{fig:x86-int-concrete}). \racket{The Racket \key{format} and
-\key{string-append} functions are useful in this regard.} The main work
-that this step needs to perform is to create the \key{main} function
-and the standard instructions for its prelude and conclusion, as shown
-in Figure~\ref{fig:p1-x86} of Section~\ref{sec:x86}. You will need to
+Figure~\ref{fig:x86-int-concrete}).
+%
+\racket{The Racket \key{format} and \key{string-append} functions are
+  useful in this regard.}
+%
+This pass creates the \key{main} function and the standard
+instructions for its prelude and conclusion, as shown in
+Figure~\ref{fig:p1-x86} of Section~\ref{sec:x86}. You will need to
 know the amount of space needed for the stack frame, which you can
 know the amount of space needed for the stack frame, which you can
-obtain from the \racket{\code{stack-space} entry in the $\itm{info}$ field}
+obtain from the
+%
+\racket{\code{stack-space} entry in the $\itm{info}$ field}
+%
 \python{\code{stack\_space} field}
 \python{\code{stack\_space} field}
+%
 of the \key{X86Program} node.
 of the \key{X86Program} node.
 
 
 When running on Mac OS X, your compiler should prefix an underscore to
 When running on Mac OS X, your compiler should prefix an underscore to
@@ -3661,7 +3690,7 @@ programs.
 \label{sec:pe-Lvar}
 \label{sec:pe-Lvar}
 \index{subject}{partial evaluation}
 \index{subject}{partial evaluation}
 
 
-This section describes optional challenge exercises that involve
+This section describes two optional challenge exercises that involve
 adapting and improving the partial evaluator for \LangInt{} that was
 adapting and improving the partial evaluator for \LangInt{} that was
 introduced in Section~\ref{sec:partial-evaluation}.
 introduced in Section~\ref{sec:partial-evaluation}.
 
 
@@ -3670,16 +3699,22 @@ introduced in Section~\ref{sec:partial-evaluation}.
   
   
 Adapt the partial evaluator from Section~\ref{sec:partial-evaluation}
 Adapt the partial evaluator from Section~\ref{sec:partial-evaluation}
 (Figure~\ref{fig:pe-arith}) so that it applies to \LangVar{} programs
 (Figure~\ref{fig:pe-arith}) so that it applies to \LangVar{} programs
-instead of \LangInt{} programs. Recall that \LangVar{} adds
+instead of \LangInt{} programs. Recall that \LangVar{} adds variables and
+%
 \racket{\key{let} binding}\python{assignment}
 \racket{\key{let} binding}\python{assignment}
-and variables to the \LangInt{} language, so you will need to add cases for
-them in the \code{pe\_exp} \racket{function}\python{and \code{pe\_stmt functions}}. Once complete, add the partial
-evaluation pass to the front of your compiler and make sure that your
-compiler still passes all of the tests.
+%
+to the \LangInt{} language, so you will need to add cases for them in
+the \code{pe\_exp}
+%
+\racket{function}
+%
+\python{and \code{pe\_stmt} functions}.
+%
+Once complete, add the partial evaluation pass to the front of your
+compiler and make sure that your compiler still passes all of the
+tests.
 \end{exercise}
 \end{exercise}
 
 
-The next exercise builds on Exercise~\ref{ex:pe-Lvar}.
-
 \begin{exercise}
 \begin{exercise}
 \normalfont
 \normalfont