Jeremy Siek 3 年 前
コミット
7764b282be
1 ファイル変更58 行追加29 行削除
  1. 58 29
      book.tex

+ 58 - 29
book.tex

@@ -11468,6 +11468,8 @@ tuple, which is 8 for the tag plus \itm{len} times 8.
   of the tuple AST node, which is stored there by running the type
   checker for \LangVec{} immediately before this pass.}
 %
+\begin{center}
+\begin{minipage}{\textwidth}
 {\if\edition\racketEd
 \begin{lstlisting}
   (has-type (vector |$e_0 \ldots e_{n-1}$|) |\itm{type}|)
@@ -11502,6 +11504,8 @@ tuple, which is 8 for the tag plus \itm{len} times 8.
       |$v$|
 \end{lstlisting}
 \fi}
+\end{minipage}
+\end{center}
 %
 \noindent The sequencing of the initializing expressions
 $e_0,\ldots,e_{n-1}$ prior to the \code{allocate} is important, as
@@ -11747,6 +11751,7 @@ the other forms that we've already encoutered.
 %% collect (callq collect)
 %% vector-ref
 %% vector-set!
+%% vector-length
 %% global (postpone)
 
 In this pass we generate x86 code for most of the new operations that
@@ -11819,6 +11824,13 @@ But the above sequence of instructions does not work because we're
 trying to use \code{rax} for two different values ($\itm{tup}'$ and
 $\itm{rhs}'$) at the same time!
 
+The \racket{\code{vector-length}}\python{\code{len}} operation should
+be translated into a sequence of instructions that read the tag of the
+tuple and extract the six bits that represent the tuple length, which
+are the bits starting at index 1 and going up to and including bit 6.
+The x86 instructions \code{andq} (for bitwise-and) and \code{sarq}
+(shift right) can be used to accomplish this.
+
 We compile the \code{allocate} form to operations on the
 \code{free\_ptr}, as shown below. The address in the \code{free\_ptr}
 is the next free address in the FromSpace, so we copy it into
@@ -12171,7 +12183,7 @@ conclusion:
 \node (Lvec-2) at (3,2)  {\large \LangVec{}};
 \node (Lvec-3) at (6,2)  {\large \LangVec{}};
 \node (Lvec-4) at (9,2)  {\large \LangVec{}};
-\node (Lvec-5) at (12,2)  {\large \LangAllocANF{}};
+\node (Lvec-5) at (9,0)  {\large \LangAllocANF{}};
 \node (C2-4) at (3,0)  {\large \LangCVec{}};
 
 \node (x86-2) at (3,-2)  {\large \LangXGlobalVar{}};
@@ -12187,7 +12199,7 @@ conclusion:
 \path[->,bend left=15] (Lvec-2) edge [above] node {\ttfamily\footnotesize uniquify} (Lvec-3);
 \path[->,bend left=15] (Lvec-3) edge [above] node {\ttfamily\footnotesize expose\_alloc.} (Lvec-4);
 \path[->,bend left=15] (Lvec-4) edge [above] node {\ttfamily\footnotesize remove\_complex.} (Lvec-5);
-\path[->,bend left=20] (Lvec-5) edge [left] node {\ttfamily\footnotesize explicate\_control} (C2-4);
+\path[->,bend left=10] (Lvec-5) edge [above] node {\ttfamily\footnotesize explicate\_control} (C2-4);
 \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 build\_inter.} (x86-2-2);
@@ -12742,7 +12754,7 @@ This chapter studies the compilation of functions similar to those
 found in the C language. This corresponds to a subset of \racket{Typed
   Racket} \python{Python} in which only top-level function definitions
 are allowed. This kind of function is an important stepping stone to
-implementing lexically-scoped functions, that is, \key{lambda}
+implementing lexically-scoped functions in the form of \key{lambda}
 abstractions, which is the topic of Chapter~\ref{ch:Rlam}.
 
 \section{The \LangFun{} Language}
@@ -14184,7 +14196,7 @@ function in \LangFun{} to x86. The figure also includes the results of the
 
 \begin{figure}[htbp]
 \begin{tabular}{ll}
-\begin{minipage}{0.5\textwidth}
+\begin{minipage}{0.4\textwidth}
 % s3_2.rkt
 {\if\edition\racketEd
 \begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
@@ -14396,8 +14408,6 @@ mainconclusion:
 \index{subject}{lambda}
 \index{subject}{lexical scoping}
 
-\if\edition\racketEd
-
 This chapter studies lexically scoped functions as they appear in
 functional languages such as Racket. By lexical scoping we mean that a
 function's body may refer to variables whose binding site is outside
@@ -14408,7 +14418,7 @@ Consider the example in Figure~\ref{fig:lexical-scoping} written in
 \key{lambda} form.  The body of the \key{lambda}, refers to three
 variables: \code{x}, \code{y}, and \code{z}. The binding sites for
 \code{x} and \code{y} are outside of the \key{lambda}. Variable
-\code{y} is bound by the enclosing \key{let} and \code{x} is a
+\code{y} is \racket{bound by the enclosing \key{let}}\python{a local variable of function\code{f}} and \code{x} is a
 parameter of function \code{f}. The \key{lambda} is returned from the
 function \code{f}. The main expression of the program includes two
 calls to \code{f} with different arguments for \code{x}, first
@@ -14420,7 +14430,8 @@ functions because they use different values for \code{x}. Applying
 \code{15} produces \code{22}. The result of this program is \code{42}.
 
 \begin{figure}[btp]
-% s4_6.rkt
+{\if\edition\racketEd
+% lambda_test_21.rkt
 \begin{lstlisting}
    (define (f [x : Integer]) : (Integer -> Integer)
       (let ([y 4])
@@ -14431,53 +14442,71 @@ functions because they use different values for \code{x}. Applying
      (let ([h (f 3)])
        (+ (g 11) (h 15))))
 \end{lstlisting}
+\fi}
+{\if\edition\pythonEd
+\begin{lstlisting}
+    def f(x : int) -> Callable[[int], int]:
+        y = 4
+        return lambda z: x + y + z
+
+    g = f(5)
+    h = f(3)
+    print( g(11) + h(15) )
+\end{lstlisting}
+\fi}
 \caption{Example of a lexically scoped function.}
 \label{fig:lexical-scoping}
 \end{figure}
 
 
-The approach that we take for implementing lexically scoped
-functions is to compile them into top-level function definitions,
-translating from \LangLam{} into \LangFun{}.  However, the compiler will need to
-provide special treatment for variable occurrences such as \code{x}
-and \code{y} in the body of the \code{lambda} of
-Figure~\ref{fig:lexical-scoping}. After all, an \LangFun{} function may not
-refer to variables defined outside of it. To identify such variable
-occurrences, we review the standard notion of free variable.
+The approach that we take for implementing lexically scoped functions
+is to compile them into top-level function definitions, translating
+from \LangLam{} into \LangFun{}.  However, the compiler must give
+special treatment to variable occurrences such as \code{x} and
+\code{y} in the body of the \code{lambda} of
+Figure~\ref{fig:lexical-scoping}. After all, an \LangFun{} function
+may not refer to variables defined outside of it. To identify such
+variable occurrences, we review the standard notion of free variable.
 
 \begin{definition}
-A variable is \emph{free in expression} $e$ if the variable occurs
-inside $e$ but does not have an enclosing binding in $e$.\index{subject}{free
-  variable}
+A variable is \textbf{free in expression} $e$ if the variable occurs
+inside $e$ but does not have an enclosing binding that is also in
+$e$.\index{subject}{free variable}
 \end{definition}
 
 For example, in the expression \code{(+ x (+ y z))} the variables
 \code{x}, \code{y}, and \code{z} are all free.  On the other hand,
 only \code{x} and \code{y} are free in the following expression
 because \code{z} is bound by the \code{lambda}.
+{\if\edition\racketEd
 \begin{lstlisting}
    (lambda: ([z : Integer]) : Integer
       (+ x (+ y z)))
 \end{lstlisting}
-
+\fi}
+{\if\edition\pythonEd
+\begin{lstlisting}
+   lambda z: x + y + z
+\end{lstlisting}
+\fi}
 So the free variables of a \code{lambda} are the ones that will need
 special treatment. We need to arrange for some way to transport, at
 runtime, the values of those variables from the point where the
 \code{lambda} was created to the point where the \code{lambda} is
 applied. An efficient solution to the problem, due to
-\citet{Cardelli:1983aa}, is to bundle into a vector the values of the
+\citet{Cardelli:1983aa}, is to bundle into a tuple the values of the
 free variables together with the function pointer for the lambda's
 code, an arrangement called a \emph{flat closure} (which we shorten to
 just ``closure'').  \index{subject}{closure}\index{subject}{flat closure} Fortunately,
 we have all the ingredients to make closures, Chapter~\ref{ch:Lvec}
-gave us vectors and Chapter~\ref{ch:Rfun} gave us function
+gave us tuples and Chapter~\ref{ch:Rfun} gave us function
 pointers. The function pointer resides at index $0$ and the
-values for the free variables will fill in the rest of the vector.
+values for the free variables will fill in the rest of the tuple.
 
 Let us revisit the example in Figure~\ref{fig:lexical-scoping} to see
 how closures work. It's a three-step dance. The program first calls
 function \code{f}, which creates a closure for the \code{lambda}. The
-closure is a vector whose first element is a pointer to the top-level
+closure is a tuple whose first element is a pointer to the top-level
 function that we will generate for the \code{lambda}, the second
 element is the value of \code{x}, which is \code{5}, and the third
 element is \code{4}, the value of \code{y}. The closure does not
@@ -14508,7 +14537,7 @@ in this case \code{11}. This technique for applying a closure is step
 But doesn't this \code{lambda} only take 1 argument, for parameter
 \code{z}? The third and final step of the dance is generating a
 top-level function for a \code{lambda}.  We add an additional
-parameter for the closure and we insert a \code{let} at the beginning
+parameter for the closure and we insert an initialization at the beginning
 of the function for each free variable, to bind those variables to the
 appropriate elements from the closure parameter.
 %
@@ -14521,6 +14550,8 @@ syntax and semantics of \LangLam{} in Section~\ref{sec:r5}.
 \section{The \LangLam{} Language}
 \label{sec:r5}
 
+\python{UNDER CONSTRUCTION}
+
 The concrete and abstract syntax for \LangLam{}, a language with anonymous
 functions and lexical scoping, is defined in
 Figures~\ref{fig:Rlam-concrete-syntax} and ~\ref{fig:Rlam-syntax}. It adds
@@ -14694,9 +14725,6 @@ require the body's type to match the declared return type.
 \section{Assignment and Lexically Scoped Functions}
 \label{sec:assignment-scoping}
 
-[UNDER CONSTRUCTION: This section was just moved into this location
-and may need to be updated. -Jeremy]
-
 The combination of lexically-scoped functions and assignment
 (i.e. \code{set!}) raises a challenge with our approach to
 implementing lexically-scoped functions. Consider the following
@@ -15134,6 +15162,7 @@ operators.
 \fbox{
 \begin{minipage}{0.96\textwidth}
 \small
+{\if\edition\racketEd
 \[
 \begin{array}{lcl}
 \Exp &::= & \ldots
@@ -15148,6 +15177,7 @@ operators.
 \LangCLamM{} & ::= & \gray{ \PROGRAMDEFS{\itm{info}}{\LP\Def\ldots\RP} }
 \end{array}
 \]
+\fi}
 \end{minipage}
 }
 \caption{The abstract syntax of \LangCLam{}, extending \LangCFun{} (Figure~\ref{fig:c3-syntax}).}
@@ -15389,7 +15419,6 @@ closure is proportional to the number of its free variables.  Flat
 closures were reinvented by \citet{Dybvig:1987ab} in his Ph.D. thesis
 and used in Chez Scheme version 1~\citep{Dybvig:2006aa}.
 
-\fi
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \chapter{Dynamic Typing}