|
@@ -15516,12 +15516,12 @@ print(tail_sum(3, 0) + 36)
|
|
|
\fi}
|
|
|
\end{center}
|
|
|
At a tail call, the frame of the caller is no longer needed, so we can
|
|
|
-pop the caller's frame before making the tail call. With this
|
|
|
-approach, a recursive function that makes only tail calls ends up
|
|
|
-using a constant amount of stack space. Functional languages like
|
|
|
-Racket rely heavily on recursive functions, so the definition of
|
|
|
-Racket \emph{requires} that all tail calls be optimized in this way.
|
|
|
-\index{subject}{frame}
|
|
|
+pop the caller's frame before making the tail
|
|
|
+call. \index{subject}{frame} With this approach, a recursive function
|
|
|
+that makes only tail calls ends up using a constant amount of stack
|
|
|
+space. \racket{Functional languages like Racket rely heavily on
|
|
|
+ recursive functions, so the definition of Racket \emph{requires}
|
|
|
+ that all tail calls be optimized in this way.}
|
|
|
|
|
|
Some care is needed with regard to argument passing in tail calls. As
|
|
|
mentioned, for arguments beyond the sixth, the convention is to use
|
|
@@ -15784,7 +15784,7 @@ and augments programs to include a list of function definitions.
|
|
|
\begin{figure}[tp]
|
|
|
\centering
|
|
|
\begin{tcolorbox}[colback=white]
|
|
|
-\small
|
|
|
+\footnotesize
|
|
|
{\if\edition\racketEd
|
|
|
\[
|
|
|
\begin{array}{l}
|
|
@@ -15905,14 +15905,13 @@ appropriate explicate functions for the various contexts.
|
|
|
\Tail &::= & \TAILCALL{\Atm}{\Atm^{*}} \\
|
|
|
\Params &::=& \LS\LP\Var\key{,}\Type\RP\code{,}\ldots\RS \\
|
|
|
\Block &::=& \itm{label}\key{:} \Stmt^{*}\;\Tail \\
|
|
|
-\Blocks &::=& \LC\Block\code{,}\ldots\RC \\
|
|
|
-\Def &::=& \DEF{\itm{label}}{\Params}{\Blocks}{\key{None}}{\Type}{\key{None}}
|
|
|
+\Def &::=& \DEF{\itm{label}}{\Params}{\LC\Block\code{,}\ldots\RC}{\key{None}}{\Type}{\key{None}}
|
|
|
\end{array}
|
|
|
}
|
|
|
|
|
|
\begin{figure}[tp]
|
|
|
\begin{tcolorbox}[colback=white]
|
|
|
-\small
|
|
|
+\footnotesize
|
|
|
{\if\edition\racketEd
|
|
|
\[
|
|
|
\begin{array}{l}
|
|
@@ -16025,8 +16024,7 @@ this section. \index{subject}{x86}
|
|
|
\MID \TAILJMP{\Arg}{\itm{int}}\\
|
|
|
&\MID& \BININSTR{\scode{leaq}}{\Arg}{\REG{\Reg}}\\
|
|
|
\Block &::=&\itm{label}\key{:}\,\Instr^{*} \\
|
|
|
- \Blocks &::= & \LC\Block\code{,}\ldots\RC\\
|
|
|
- \Def &::= & \DEF{\itm{label}}{\LS\RS}{\Blocks}{\_}{\Type}{\_} \\
|
|
|
+ \Def &::= & \DEF{\itm{label}}{\LS\RS}{\LC\Block\code{,}\ldots\RC}{\_}{\Type}{\_} \\
|
|
|
\LangXIndCallM{} &::= & \XPROGRAMDEFS{\LS\Def\code{,}\ldots\RS}
|
|
|
\end{array}
|
|
|
\]
|
|
@@ -16160,7 +16158,7 @@ $\itm{arg}_0$. So, we translate the call into an indirect function
|
|
|
call. The return value from the function is stored in \code{rax}, so
|
|
|
it needs to be moved into the \itm{lhs}.
|
|
|
\begin{lstlisting}
|
|
|
- |\itm{lhs}| = |$\CALL{\itm{arg}_0}{\itm{arg}_1~\itm{arg}_2 \ldots}$|
|
|
|
+ |\itm{lhs}| = |$\CALL{\itm{arg}_0}{\python{\LS}\itm{arg}_1~\itm{arg}_2 \ldots\python{\RS}}$|
|
|
|
|$\Rightarrow$|
|
|
|
movq |$\itm{arg}_1$|, %rdi
|
|
|
movq |$\itm{arg}_2$|, %rsi
|
|
@@ -16302,11 +16300,19 @@ The conclusion of every function should do the following:
|
|
|
|
|
|
The output of this pass is \LangXIndCallFlat{}, which differs from
|
|
|
\LangXIndCall{} in that there is no longer an AST node for function
|
|
|
-definitions. Instead, a program is just an association list of basic
|
|
|
-blocks, as in \LangXGlobal{}. So we have the following grammar rule:
|
|
|
+definitions. Instead, a program is just
|
|
|
+\racket{an association list}\python{dictionary}
|
|
|
+of basic blocks, as in \LangXGlobal{}. So we have the following grammar rule:
|
|
|
+{\if\edition\racketEd
|
|
|
\[
|
|
|
\LangXIndCallFlatM{} ::= \XPROGRAM{\itm{info}}{\LP\LP\itm{label} \,\key{.}\, \Block \RP\ldots\RP}
|
|
|
\]
|
|
|
+\fi}
|
|
|
+{\if\edition\pythonEd
|
|
|
+\[
|
|
|
+\LangXIndCallFlatM{} ::= \XPROGRAM{\itm{info}}{\LC\itm{label}\key{:}\,\Instr^{*}\code{,}\ldots\RC}
|
|
|
+\]
|
|
|
+\fi}
|
|
|
|
|
|
Figure~\ref{fig:Lfun-passes} gives an overview of the passes for
|
|
|
compiling \LangFun{} to x86.
|
|
@@ -16315,7 +16321,7 @@ compiling \LangFun{} to x86.
|
|
|
Expand your compiler to handle \LangFun{} as outlined in this chapter.
|
|
|
Create eight new programs that use functions including examples that
|
|
|
pass functions and return functions from other functions, recursive
|
|
|
-functions, functions that create vectors, and functions that make tail
|
|
|
+functions, functions that create tuples, and functions that make tail
|
|
|
calls. Test your compiler on these new programs and all your
|
|
|
previously created test programs.
|
|
|
\end{exercise}
|