|
@@ -14140,7 +14140,7 @@ previously created test programs.
|
|
|
\node (Rfun) at (0,2) {\large \LangFun{}};
|
|
|
\node (Rfun-1) at (3,2) {\large \LangFun{}};
|
|
|
\node (Rfun-2) at (6,2) {\large \LangFun{}};
|
|
|
-\node (F1-1) at (12,0) {\large \LangFunRef{}};
|
|
|
+\node (F1-1) at (9,2) {\large \LangFunRef{}};
|
|
|
\node (F1-2) at (9,0) {\large \LangFunRef{}};
|
|
|
\node (F1-3) at (6,0) {\large \LangFunRefAlloc{}};
|
|
|
\node (F1-4) at (3,0) {\large \LangFunANF{}};
|
|
@@ -14158,9 +14158,9 @@ previously created test programs.
|
|
|
{\ttfamily\footnotesize shrink} (Rfun-1);
|
|
|
\path[->,bend left=15] (Rfun-1) edge [above] node
|
|
|
{\ttfamily\footnotesize uniquify} (Rfun-2);
|
|
|
-\path[->,bend left=15] (Rfun-2) edge [right] node
|
|
|
+\path[->,bend left=15] (Rfun-2) edge [above] node
|
|
|
{\ttfamily\footnotesize ~~reveal\_functions} (F1-1);
|
|
|
-\path[->,bend left=15] (F1-1) edge [below] node
|
|
|
+\path[->,bend left=15] (F1-1) edge [right] node
|
|
|
{\ttfamily\footnotesize limit\_functions} (F1-2);
|
|
|
\path[->,bend right=15] (F1-2) edge [above] node
|
|
|
{\ttfamily\footnotesize expose\_alloc.} (F1-3);
|
|
@@ -14199,7 +14199,7 @@ function in \LangFun{} to x86. The figure also includes the results of the
|
|
|
\begin{minipage}{0.4\textwidth}
|
|
|
% s3_2.rkt
|
|
|
{\if\edition\racketEd
|
|
|
-\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
|
|
|
+\begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
|
|
|
(define (add [x : Integer] [y : Integer])
|
|
|
: Integer
|
|
|
(+ x y))
|
|
@@ -14207,7 +14207,7 @@ function in \LangFun{} to x86. The figure also includes the results of the
|
|
|
\end{lstlisting}
|
|
|
\fi}
|
|
|
{\if\edition\pythonEd
|
|
|
-\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
|
|
|
+\begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
|
|
|
def add(x:int, y:int) -> int:
|
|
|
return x + y
|
|
|
|
|
@@ -14216,7 +14216,7 @@ print(add(40, 2))
|
|
|
\fi}
|
|
|
$\Downarrow$
|
|
|
{\if\edition\racketEd
|
|
|
-\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
|
|
|
+\begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
|
|
|
(define (add86 [x87 : Integer]
|
|
|
[y88 : Integer]) : Integer
|
|
|
add86start:
|
|
@@ -14230,7 +14230,7 @@ $\Downarrow$
|
|
|
\end{lstlisting}
|
|
|
\fi}
|
|
|
{\if\edition\pythonEd
|
|
|
-\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
|
|
|
+\begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
|
|
|
def add(x:int, y:int) -> int:
|
|
|
addstart:
|
|
|
return x + y
|
|
@@ -14248,7 +14248,7 @@ def main() -> int:
|
|
|
$\Rightarrow$
|
|
|
\begin{minipage}{0.5\textwidth}
|
|
|
{\if\edition\racketEd
|
|
|
-\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
|
|
|
+\begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
|
|
|
(define (add86) : Integer
|
|
|
add86start:
|
|
|
movq %rdi, x87
|
|
@@ -14267,7 +14267,7 @@ $\Rightarrow$
|
|
|
\end{lstlisting}
|
|
|
\fi}
|
|
|
{\if\edition\pythonEd
|
|
|
-\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
|
|
|
+\begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
|
|
|
def add() -> int:
|
|
|
addstart:
|
|
|
movq %rdi, x
|
|
@@ -14295,7 +14295,7 @@ $\Downarrow$
|
|
|
\begin{tabular}{ll}
|
|
|
\begin{minipage}{0.3\textwidth}
|
|
|
{\if\edition\racketEd
|
|
|
-\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
|
|
|
+\begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
|
|
|
.globl add86
|
|
|
.align 16
|
|
|
add86:
|
|
@@ -14312,7 +14312,7 @@ add86conclusion:
|
|
|
\end{lstlisting}
|
|
|
\fi}
|
|
|
{\if\edition\pythonEd
|
|
|
-\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
|
|
|
+\begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
|
|
|
.align 16
|
|
|
add:
|
|
|
pushq %rbp
|
|
@@ -14336,7 +14336,7 @@ addconclusion:
|
|
|
&
|
|
|
\begin{minipage}{0.5\textwidth}
|
|
|
{\if\edition\racketEd
|
|
|
-\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
|
|
|
+\begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
|
|
|
.globl main
|
|
|
.align 16
|
|
|
main:
|
|
@@ -14360,7 +14360,7 @@ mainconclusion:
|
|
|
\end{lstlisting}
|
|
|
\fi}
|
|
|
{\if\edition\pythonEd
|
|
|
-\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
|
|
|
+\begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
|
|
|
.globl main
|
|
|
.align 16
|
|
|
main:
|
|
@@ -14571,6 +14571,8 @@ syntax for function application.
|
|
|
\end{array}
|
|
|
}
|
|
|
|
|
|
+% include AnnAssign in ASTPython
|
|
|
+
|
|
|
\begin{figure}[tp]
|
|
|
\centering
|
|
|
\fbox{
|
|
@@ -14586,24 +14588,6 @@ syntax for function application.
|
|
|
\gray{\LfunGrammarRacket} \\ \hline
|
|
|
\LlambdaGrammarRacket \\
|
|
|
\begin{array}{lcl}
|
|
|
- %% \Type &::=& \gray{\key{Integer} \MID \key{Boolean}
|
|
|
- %% \MID (\key{Vector}\;\Type\ldots) \MID \key{Void}
|
|
|
- %% \MID (\Type\ldots \; \key{->}\; \Type)} \\
|
|
|
- %% \Exp &::=& \gray{ \Int \MID \CREAD{} \MID \CNEG{\Exp}
|
|
|
- %% \MID \CADD{\Exp}{\Exp} \MID \CSUB{\Exp}{\Exp} } \\
|
|
|
- %% &\MID& \gray{ \Var \MID \CLET{\Var}{\Exp}{\Exp} }\\
|
|
|
- %% &\MID& \gray{\key{\#t} \MID \key{\#f}
|
|
|
- %% \MID (\key{and}\;\Exp\;\Exp)
|
|
|
- %% \MID (\key{or}\;\Exp\;\Exp)
|
|
|
- %% \MID (\key{not}\;\Exp) } \\
|
|
|
- %% &\MID& \gray{ (\key{eq?}\;\Exp\;\Exp) \MID \CIF{\Exp}{\Exp}{\Exp} } \\
|
|
|
- %% &\MID& \gray{ (\key{vector}\;\Exp\ldots) \MID
|
|
|
- %% (\key{vector-ref}\;\Exp\;\Int)} \\
|
|
|
- %% &\MID& \gray{(\key{vector-set!}\;\Exp\;\Int\;\Exp)\MID (\key{void})
|
|
|
- %% \MID (\Exp \; \Exp\ldots) } \\
|
|
|
- %% &\MID& \LP \key{procedure-arity}~\Exp\RP \\
|
|
|
- %% &\MID& \CLAMBDA{\LP\LS\Var \key{:} \Type\RS\ldots\RP}{\Type}{\Exp} \\
|
|
|
- %% \Def &::=& \gray{ \CDEF{\Var}{\LS\Var \key{:} \Type\RS\ldots}{\Type}{\Exp} } \\
|
|
|
\LangLamM{} &::=& \Def\ldots \; \Exp
|
|
|
\end{array}
|
|
|
\end{array}
|
|
@@ -14630,15 +14614,6 @@ syntax for function application.
|
|
|
\gray{\LfunASTRacket} \\ \hline
|
|
|
\LlambdaASTRacket \\
|
|
|
\begin{array}{lcl}
|
|
|
- %% \itm{op} &::=& \ldots \MID \code{procedure-arity} \\
|
|
|
- %% \Exp &::=& \gray{ \INT{\Int} \VAR{\Var} \MID \LET{\Var}{\Exp}{\Exp} } \\
|
|
|
- %% &\MID& \gray{ \PRIM{\itm{op}}{\Exp\ldots} }\\
|
|
|
- %% &\MID& \gray{ \BOOL{\itm{bool}}
|
|
|
- %% \MID \IF{\Exp}{\Exp}{\Exp} } \\
|
|
|
- %% &\MID& \gray{ \VOID{} \MID \LP\key{HasType}~\Exp~\Type \RP
|
|
|
- %% \MID \APPLY{\Exp}{\Exp\ldots} }\\
|
|
|
- %% &\MID& \LAMBDA{\LP\LS\Var\code{:}\Type\RS\ldots\RP}{\Type}{\Exp}\\
|
|
|
- %% \Def &::=& \gray{ \FUNDEF{\Var}{\LP\LS\Var \code{:} \Type\RS\ldots\RP}{\Type}{\code{'()}}{\Exp} }\\
|
|
|
\LangLamM{} &::=& \gray{ \PROGRAMDEFSEXP{\code{'()}}{\LP\Def\ldots\RP}{\Exp} }
|
|
|
\end{array}
|
|
|
\end{array}
|
|
@@ -14725,12 +14700,13 @@ require the body's type to match the declared return type.
|
|
|
\section{Assignment and Lexically Scoped Functions}
|
|
|
\label{sec:assignment-scoping}
|
|
|
|
|
|
-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
|
|
|
-example in which function \code{f} has a free variable \code{x} that
|
|
|
-is changed after \code{f} is created but before the call to \code{f}.
|
|
|
+The combination of lexically-scoped functions and assignment to
|
|
|
+variables raises a challenge with our approach to implementing
|
|
|
+lexically-scoped functions. Consider the following example in which
|
|
|
+function \code{f} has a free variable \code{x} that is changed after
|
|
|
+\code{f} is created but before the call to \code{f}.
|
|
|
% loop_test_11.rkt
|
|
|
+{\if\edition\racketEd
|
|
|
\begin{lstlisting}
|
|
|
(let ([x 0])
|
|
|
(let ([y 0])
|
|
@@ -14741,6 +14717,19 @@ is changed after \code{f} is created but before the call to \code{f}.
|
|
|
(set! y 12)
|
|
|
(f y))))))
|
|
|
\end{lstlisting}
|
|
|
+\fi}
|
|
|
+{\if\edition\pythonEd
|
|
|
+% assign_free.py
|
|
|
+\begin{lstlisting}
|
|
|
+ x = 0
|
|
|
+ y = 0
|
|
|
+ z = 20
|
|
|
+ f : Callable[[int],int] = lambda a: a + x + z
|
|
|
+ x = 10
|
|
|
+ y = 12
|
|
|
+ print( f(y) )
|
|
|
+\end{lstlisting}
|
|
|
+\fi}
|
|
|
The correct output for this example is \code{42} because the call to
|
|
|
\code{f} is required to use the current value of \code{x} (which is
|
|
|
\code{10}). Unfortunately, the closure conversion pass
|
|
@@ -14753,41 +14742,79 @@ A first attempt at solving this problem would be to save a pointer to
|
|
|
\code{x} in the closure and change the occurrences of \code{x} inside
|
|
|
the lambda to dereference the pointer. Of course, this would require
|
|
|
assigning \code{x} to the stack and not to a register. However, the
|
|
|
-problem goes a bit deeper. Consider the following example in which we
|
|
|
-create a counter abstraction by creating a pair of functions that
|
|
|
-share the free variable \code{x}.
|
|
|
+problem goes a bit deeper.
|
|
|
+%% Consider the following example in which we
|
|
|
+%% create a counter abstraction by creating a pair of functions that
|
|
|
+%% share the free variable \code{x}.
|
|
|
+Consider the following example that returns a function that refers to
|
|
|
+a local variable of the enclosing function.
|
|
|
+\begin{center}
|
|
|
+\begin{minipage}{\textwidth}
|
|
|
+{\if\edition\racketEd
|
|
|
% similar to loop_test_10.rkt
|
|
|
+%% \begin{lstlisting}
|
|
|
+%% (define (f [x : Integer]) : (Vector ( -> Integer) ( -> Void))
|
|
|
+%% (vector
|
|
|
+%% (lambda: () : Integer x)
|
|
|
+%% (lambda: () : Void (set! x (+ 1 x)))))
|
|
|
+
|
|
|
+%% (let ([counter (f 0)])
|
|
|
+%% (let ([get (vector-ref counter 0)])
|
|
|
+%% (let ([inc (vector-ref counter 1)])
|
|
|
+%% (begin
|
|
|
+%% (inc)
|
|
|
+%% (get)))))
|
|
|
+%% \end{lstlisting}
|
|
|
\begin{lstlisting}
|
|
|
-(define (f [x : Integer]) : (Vector ( -> Integer) ( -> Void))
|
|
|
- (vector
|
|
|
- (lambda: () : Integer x)
|
|
|
- (lambda: () : Void (set! x (+ 1 x)))))
|
|
|
-
|
|
|
-(let ([counter (f 0)])
|
|
|
- (let ([get (vector-ref counter 0)])
|
|
|
- (let ([inc (vector-ref counter 1)])
|
|
|
+(define (f []) : Integer
|
|
|
+ (let ([x 0])
|
|
|
+ (let ([g (lambda: () : Integer x)])
|
|
|
(begin
|
|
|
- (inc)
|
|
|
- (get)))))
|
|
|
+ (set! x 42)
|
|
|
+ g))))
|
|
|
+((f))
|
|
|
\end{lstlisting}
|
|
|
+\fi}
|
|
|
+{\if\edition\pythonEd
|
|
|
+% counter.py
|
|
|
+\begin{lstlisting}
|
|
|
+def f():
|
|
|
+ x = 0
|
|
|
+ g = lambda: x
|
|
|
+ x = 42
|
|
|
+ return g
|
|
|
+
|
|
|
+print( f()() )
|
|
|
+\end{lstlisting}
|
|
|
+\fi}
|
|
|
+\end{minipage}
|
|
|
+\end{center}
|
|
|
In this example, the lifetime of \code{x} extends beyond the lifetime
|
|
|
of the call to \code{f}. Thus, if we were to store \code{x} on the
|
|
|
stack frame for the call to \code{f}, it would be gone by the time we
|
|
|
-call \code{inc} and \code{get}, leaving us with dangling pointers for
|
|
|
+call \code{g}, leaving us with dangling pointers for
|
|
|
\code{x}. This example demonstrates that when a variable occurs free
|
|
|
-inside a \code{lambda}, its lifetime becomes indefinite. Thus, the
|
|
|
-value of the variable needs to live on the heap. The verb ``box'' is
|
|
|
-often used for allocating a single value on the heap, producing a
|
|
|
-pointer, and ``unbox'' for dereferencing the pointer.
|
|
|
-
|
|
|
-We recommend solving these problems by ``boxing'' the local variables
|
|
|
-that are in the intersection of 1) variables that appear on the
|
|
|
-left-hand-side of a \code{set!} and 2) variables that occur free
|
|
|
-inside a \code{lambda}. We shall introduce a new pass named
|
|
|
-\code{convert-assignments} in Section~\ref{sec:convert-assignments} to
|
|
|
-perform this translation. But before diving into the compiler passes,
|
|
|
-we one more problem to discuss.
|
|
|
+inside a function, its lifetime becomes indefinite. Thus, the value of
|
|
|
+the variable needs to live on the heap. The verb
|
|
|
+\emph{box}\index{subject}{box} is often used for allocating a single
|
|
|
+value on the heap, producing a pointer, and
|
|
|
+\emph{unbox}\index{subject}{unbox} for dereferencing the pointer.
|
|
|
|
|
|
+{\if\edition\racketEd
|
|
|
+We recommend solving these problems by boxing the local variables that
|
|
|
+are in the intersection of 1) variables that appear on the
|
|
|
+left-hand-side of a \code{set!} and 2) variables that occur free
|
|
|
+inside a \code{lambda}.
|
|
|
+\fi}
|
|
|
+{\if\edition\pythonEd
|
|
|
+We recommend solving these problems by boxing the local variables that
|
|
|
+are in the intersection of 1) variables whose values may change and 2)
|
|
|
+variables that occur free inside a \code{lambda}.
|
|
|
+\fi}
|
|
|
+We shall introduce a new pass named
|
|
|
+\code{convert\_assignments} in Section~\ref{sec:convert-assignments}
|
|
|
+to perform this translation. But before diving into the compiler
|
|
|
+passes, we one more problem to discuss.
|
|
|
|
|
|
\section{Reveal Functions and the $F_2$ language}
|
|
|
\label{sec:reveal-functions-r5}
|