浏览代码

4.8 explicate control

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

+ 66 - 46
book.tex

@@ -8187,7 +8187,9 @@ def explicate_control(p):
 
 
 
 
 {\if\edition\racketEd
 {\if\edition\racketEd
-%
+
+\subsection{Explicate Tail and Assign}
+  
 The \code{explicate\_tail} and \code{explicate\_assign} functions need
 The \code{explicate\_tail} and \code{explicate\_assign} functions need
 additional cases for Boolean constants and \key{if}.  The cases for
 additional cases for Boolean constants and \key{if}.  The cases for
 \code{if} should recursively compile the two branches using either
 \code{if} should recursively compile the two branches using either
@@ -8196,13 +8198,15 @@ cases should then invoke \code{explicate\_pred} on the condition
 expression, passing in the generated code for the two branches.  For
 expression, passing in the generated code for the two branches.  For
 example, consider the following program with an \code{if} in tail
 example, consider the following program with an \code{if} in tail
 position.
 position.
+% cond_test_6.rkt
 \begin{lstlisting}
 \begin{lstlisting}
 (let ([x (read)])
 (let ([x (read)])
   (if (eq? x 0) 42 777))
   (if (eq? x 0) 42 777))
 \end{lstlisting}
 \end{lstlisting}
-The two branches are recursively compiled to \code{return 42;} and
-\code{return 777;}. We then delegate to \code{explicate\_pred},
-passing the condition \code{(eq? x 0)} and the two return statements.
+The two branches are recursively compiled to return statements.  We
+then delegate to \code{explicate\_pred}, passing the condition
+\code{(eq? x 0)} and the two return statements.  We return to this
+example shortly when we discuss \code{explicate\_pred}.
 
 
 Next let us consider a program with an \code{if} on the right-hand
 Next let us consider a program with an \code{if} on the right-hand
 side of a \code{let}.
 side of a \code{let}.
@@ -8216,28 +8220,60 @@ compiled to \code{return (+ x 2);} and passed as the \code{cont}
 parameter of \code{explicate\_assign}. We'll need to use \code{cont}
 parameter of \code{explicate\_assign}. We'll need to use \code{cont}
 to recursively process both branches of the \code{if}, and we do not
 to recursively process both branches of the \code{if}, and we do not
 want to duplicate code, so we generate the following block using an
 want to duplicate code, so we generate the following block using an
-auxiliary function named \code{create\_block}.
+auxiliary function named \code{create\_block} that we discuss below.
 \begin{lstlisting}
 \begin{lstlisting}
 block_6:
 block_6:
   return (+ x 2)
   return (+ x 2)
 \end{lstlisting}
 \end{lstlisting}
 We then use \code{goto block\_6;} as the \code{cont} argument for
 We then use \code{goto block\_6;} as the \code{cont} argument for
 compiling the branches. So the two branches compile to
 compiling the branches. So the two branches compile to
+\begin{center}
+\begin{minipage}{0.2\textwidth}
 \begin{lstlisting}
 \begin{lstlisting}
 x = 40;
 x = 40;
 goto block_6;
 goto block_6;
 \end{lstlisting}
 \end{lstlisting}
-and
+\end{minipage}
+\hspace{0.5in} and \hspace{0.5in}
+\begin{minipage}{0.2\textwidth}
 \begin{lstlisting}
 \begin{lstlisting}
 x = 777;
 x = 777;
 goto block_6;
 goto block_6;
 \end{lstlisting}
 \end{lstlisting}
+\end{minipage}
+\end{center}
 Finally, we delegate to \code{explicate\_pred}, passing the condition
 Finally, we delegate to \code{explicate\_pred}, passing the condition
 \code{(eq? y 0)} and the above code for the branches.
 \code{(eq? y 0)} and the above code for the branches.
 
 
+\subsection{Create Block}
+
+We recommend implementing the \code{create\_block} auxiliary function
+as follows, using a global variable \code{basic-blocks} to store a
+dictionary that maps labels to $\Tail$ expressions. The main idea is
+that \code{create\_block} generates a new label and then associates
+the given \code{tail} with the new label in the \code{basic-blocks}
+dictionary. The result of \code{create\_block} is a \code{Goto} to the
+new label. However, if the given \code{tail} is already a \code{Goto},
+then there is no need to generate a new label and entry in
+\code{basic-blocks}; we can simply return that \code{Goto}.
+%
+\begin{lstlisting}
+(define (create_block tail)
+  (match tail
+    [(Goto label) (Goto label)]
+    [else
+      (let ([label (gensym 'block)])
+        (set! basic-blocks (cons (cons label tail) basic-blocks))
+        (Goto label))]))
+\end{lstlisting}
+
+
 \fi}
 \fi}
 
 
-{\if\edition\racketEd        
+{\if\edition\racketEd
+
+\subsection{Explicate Predicate}
+  
 \begin{figure}[tbp]
 \begin{figure}[tbp]
 \begin{lstlisting}
 \begin{lstlisting}
 (define (explicate_pred cnd thn els)
 (define (explicate_pred cnd thn els)
@@ -8277,26 +8313,29 @@ Consider the case for comparison operators. We translate the
 comparison to an \code{if} statement whose branches are \code{goto}
 comparison to an \code{if} statement whose branches are \code{goto}
 statements created by applying \code{create\_block} to the code
 statements created by applying \code{create\_block} to the code
 generated for the \code{thn} and \code{els} branches. Let us
 generated for the \code{thn} and \code{els} branches. Let us
-illustrate this translation with an example.  Returning
-to the program with an \code{if} expression in tail position,
-we invoke \code{explicate\_pred} on its condition
-\racket{\code{(eq? x 0)}}
-\python{\code{x == 0}}
-which happens to be a comparison operator.
+illustrate this translation by returning to the program with an
+\code{if} expression in tail position, shown again below. We invoke
+\code{explicate\_pred} on its condition \racket{\code{(eq? x 0)}}
+\python{\code{x == 0}}.
+%
 {\if\edition\racketEd
 {\if\edition\racketEd
 \begin{lstlisting}
 \begin{lstlisting}
 (let ([x (read)])
 (let ([x (read)])
   (if (eq? x 0) 42 777))
   (if (eq? x 0) 42 777))
 \end{lstlisting}
 \end{lstlisting}
-  \fi}
+\fi}
+%
 {\if\edition\pythonEd
 {\if\edition\pythonEd
 \begin{lstlisting}
 \begin{lstlisting}
 x = input_int()
 x = input_int()
 42 if x == 0 else 777
 42 if x == 0 else 777
 \end{lstlisting}
 \end{lstlisting}
-  \fi}
-The two branches \code{42} and \code{777} were already compiled to \code{return}
-statements, from which we now create the following blocks.
+\fi}
+%
+\noindent The two branches \code{42} and \code{777} were already
+compiled to \code{return} statements, from which we now create the
+following blocks.
+%
 \begin{center}
 \begin{center}
 \begin{minipage}{\textwidth}
 \begin{minipage}{\textwidth}
 \begin{lstlisting}
 \begin{lstlisting}
@@ -8308,7 +8347,7 @@ block_2:
   \end{minipage}
   \end{minipage}
 \end{center}
 \end{center}
 %
 %
-So \code{explicate\_pred} compiles the comparison
+After that, \code{explicate\_pred} compiles the comparison
 \racket{\code{(eq? x 0)}}
 \racket{\code{(eq? x 0)}}
 \python{\code{x == 0}}
 \python{\code{x == 0}}
 to the following \code{if} statement.
 to the following \code{if} statement.
@@ -8343,38 +8382,23 @@ either the \code{thn} or \code{els} branch depending on whether the
 constant is \TRUE{} or \FALSE{}. Let us illustrate this with the
 constant is \TRUE{} or \FALSE{}. Let us illustrate this with the
 following program.
 following program.
 {\if\edition\racketEd
 {\if\edition\racketEd
-\begin{center}
-\begin{minipage}{\textwidth}
 \begin{lstlisting}
 \begin{lstlisting}
 (if #t 42 777)
 (if #t 42 777)
 \end{lstlisting}
 \end{lstlisting}
-\end{minipage}
-\end{center}
 \fi}
 \fi}
 {\if\edition\pythonEd
 {\if\edition\pythonEd
-\begin{center}
-\begin{minipage}{\textwidth}
 \begin{lstlisting}
 \begin{lstlisting}
 42 if True else 777
 42 if True else 777
 \end{lstlisting}
 \end{lstlisting}
-\end{minipage}
-\end{center}
 \fi}
 \fi}
 %
 %
-Again, the two branches \code{42} and \code{777} were compiled to
-\code{return} statements, so \code{explicate\_pred} compiles the
-constant
-\racket{\code{\#t}}
-\python{\code{True}}
-to the code for the ``then'' branch.
-\begin{center}
-\begin{minipage}{\textwidth}
+\noindent Again, the two branches \code{42} and \code{777} were
+compiled to \code{return} statements, so \code{explicate\_pred}
+compiles the constant \racket{\code{\#t}} \python{\code{True}} to the
+code for the ``then'' branch.
 \begin{lstlisting}
 \begin{lstlisting}
 return 42;
 return 42;
 \end{lstlisting}
 \end{lstlisting}
-\end{minipage}
-\end{center}
-%
 This case demonstrates that we sometimes discard the \code{thn} or
 This case demonstrates that we sometimes discard the \code{thn} or
 \code{els} blocks that are input to \code{explicate\_pred}.
 \code{els} blocks that are input to \code{explicate\_pred}.
 
 
@@ -8498,15 +8522,8 @@ and
 respectively.  In particular, we start \code{block\_4} with the
 respectively.  In particular, we start \code{block\_4} with the
 comparison
 comparison
 \racket{\code{(eq? x 0)}}\python{\code{x == 0}}
 \racket{\code{(eq? x 0)}}\python{\code{x == 0}}
-and then branch to \code{block\_4} or \code{block\_5}.
-Here was see that our algorithm sometimes inserts unnecessary blocks:
-\code{block\_4} is just a \code{goto} to \code{block\_2}
-and \code{block\_5} is just a \code{goto} to \code{block\_3}.
-It would be better to skip blocks \code{block\_4} and \code{block\_5}
-and go directly to \code{block\_2} and \code{block\_3},
-which we investigate in Section~\ref{sec:opt-jumps}.
-Getting back to the example, \code{block\_2} and \code{block\_3},
-corresponds to the two branches of the outer \key{if}, i.e.,
+and then branch to \code{block\_2} or \code{block\_3},
+which correspond to the two branches of the outer \key{if}, i.e.,
 \racket{\code{(+ y 2)}}\python{\code{y + 2}} and
 \racket{\code{(+ y 2)}}\python{\code{y + 2}} and
 \racket{\code{(+ y 10)}}\python{\code{y + 10}}.
 \racket{\code{(+ y 10)}}\python{\code{y + 10}}.
 %
 %
@@ -8517,6 +8534,9 @@ The story for \code{block\_5} is similar to that of \code{block\_4}.
 
 
 
 
 {\if\edition\racketEd
 {\if\edition\racketEd
+
+\subsection{Interactions between Explicate and Shrink}
+  
 The way in which the \code{shrink} pass transforms logical operations
 The way in which the \code{shrink} pass transforms logical operations
 such as \code{and} and \code{or} can impact the quality of code
 such as \code{and} and \code{or} can impact the quality of code
 generated by \code{explicate\_control}. For example, consider the
 generated by \code{explicate\_control}. For example, consider the