Forráskód Böngészése

progress on compilation of R7

Jeremy Siek 9 éve
szülő
commit
912b9f8aa9
1 módosított fájl, 199 hozzáadás és 23 törlés
  1. 199 23
      book.tex

+ 199 - 23
book.tex

@@ -5401,6 +5401,7 @@ auxilliary function.
 \itm{tagof}(\key{Integer}) &= 00 \\
 \itm{tagof}(\key{Boolean}) &= 01 \\
 \itm{tagof}((\key{Vector} \ldots)) &= 10 \\
+\itm{tagof}((\key{Vectorof} \ldots)) &= 10 \\
 \itm{tagof}((\ldots \key{->} \ldots)) &= 11 
 \end{align*}
 This stealing of 2 bits comes at some
@@ -5642,19 +5643,16 @@ $\Rightarrow$
 \paragraph{Project}
 
 
-\marginpar{\scriptsize To do: the inner 'if' is unnecessary because
- we know T at compile time. Also, we need to check function arity. \\ --Jeremy}
-
-The instruction selection for \key{project} is a bit more involved. We
-first check to see if the tag on the tagged value matches the tag of
-the target type $T$. If not, we halt the program by calling the
-\code{exit} function. If we have a match, we need to produce an
-untagged value and have two separate code paths depending on whether
-we're dealing a pointer (to a vector or procedure) or not.  If it's a
-pointer, then we need to zero-out the rightmost 2 bits, which we
-accomplish using \key{andq} and the value $1\ldots 100$.  If the
-tagged value is not a pointer (a Boolean or integer), then we turn it
-into a untagged value by shifting it to the right by 2 bits. \\
+The instruction selection for \key{project} is a bit more involved.
+Like \key{inject}, the instructions are different depending on whether
+the type $T$ is a pointer (vector or procedure) or not (Integer or
+Boolean). The following shows the instruction selection for Integer
+and Boolean.  We first check to see if the tag on the tagged value
+matches the tag of the target type $T$. If not, we halt the program by
+calling the \code{exit} function. If we have a match, we need to
+produce an untagged value by shifting it to the right by 2 bits.
+%
+\\
 \begin{tabular}{lll}
 \begin{minipage}{0.4\textwidth}
 \begin{lstlisting}
@@ -5669,13 +5667,39 @@ $\Rightarrow$
 (movq |$e'$| |\itm{lhs}'|)
 (andq (int 3) |\itm{lhs}'|)
 (if (eq? |\itm{lhs}'| (int |$\itm{tagof}(T)$|))
-    ((andq (int 2) |\itm{lhs}'|)
-     (if (eq? |\itm{lhs}'| (int 2))
-         ((movq (int 3) |\itm{lhs}'|)
-          (notq |\itm{lhs}'|)
-          (andq |$e'$| |\itm{lhs}'|))
-         ((movq |$e'$| |\itm{lhs}'|)
-          (sarq (int 2) |\itm{lhs}'|))))
+    ((movq |$e'$| |\itm{lhs}'|)
+     (sarq (int 2) |\itm{lhs}'|))
+    ((callq exit)))
+\end{lstlisting}
+\end{minipage}
+\end{tabular}  \\
+%
+The case for vectors and procedures begins in a similar way, checking
+that the runtime tag matches the target type $T$ and exiting if there
+is a mismatch. However, the way in which we convert the tagged value
+to a value is different, as there is no need to shift. Instead we need
+to zero-out the rightmost 2 bits. We accomplish this by creating the
+bit pattern $\ldots 0011$, applying \code{notq} to obtain $\ldots
+1100$, and then applying \code{andq} with the tagged value get the
+desired result. \\
+%
+\begin{tabular}{lll}
+\begin{minipage}{0.4\textwidth}
+\begin{lstlisting}
+(assign |\itm{lhs}| (project |$e$| |$T$|))
+\end{lstlisting}
+\end{minipage}
+&
+$\Rightarrow$
+&
+\begin{minipage}{0.5\textwidth}
+\begin{lstlisting}
+(movq |$e'$| |\itm{lhs}'|)
+(andq (int 3) |\itm{lhs}'|)
+(if (eq? |\itm{lhs}'| (int |$\itm{tagof}(T)$|))
+    ((movq (int 3) |\itm{lhs}'|)
+     (notq |\itm{lhs}'|)
+     (andq |$e'$| |\itm{lhs}'|))
     ((callq exit)))
 \end{lstlisting}
 \end{minipage}
@@ -5685,13 +5709,165 @@ $\Rightarrow$
 devise a sequence of instructions to implement the type predicates
 \key{boolean?}, \key{integer?}, \key{vector?}, and \key{procedure?}.
 
-
-
-
 \section{Compiling $R_7$ to $R_6$}
 \label{sec:compile-r7}
 
+Figure~\ref{fig:compile-r7-r6} shows the compilation of many of the
+$R_7$ forms into $R_6$. An important invariant of this pass is that
+given a subexpression $e$ of $R_7$, the pass will produce an
+expression $e'$ of $R_6$ that has type \key{Any}. For example, the
+first row in Figure~\ref{fig:compile-r7-r6} shows the compilation of
+the Boolean \code{\#t}, which must be injected to produce an
+expression of type \key{Any}.
+%
+The second row of Figure~\ref{fig:compile-r7-r6}, the compilation of
+addition, is representative of compilation for many operations: the
+arguments have type \key{Any} and must be projected to \key{Integer}
+before the addition can be performed.
+%
+The compilation of \key{lambda} (third row of
+Figure~\ref{fig:compile-r7-r6}) shows what happens when we need to
+produce type annotations, we simply use \key{Any}.
+%
+The compilation of \code{if}, \code{eq?}, and \code{and} all
+demonstrate how this pass has to account for some differences in
+behavior between $R_7$ and $R_6$. The $R_7$ language is more
+permissive than $R_6$ regarding what kind of values can be used in
+various places. For example, the condition of an \key{if} does not
+have to be a Boolean. Similarly, the arguments of \key{and} do not
+need to be Boolean. For \key{eq?}, the arguments need not be of the
+same type.
 
+\begin{figure}[tbp]
+\centering
+\begin{tabular}{|lll|} \hline
+\begin{minipage}{0.25\textwidth}
+\begin{lstlisting}
+#t
+\end{lstlisting}
+\end{minipage}
+&
+$\Rightarrow$
+&
+\begin{minipage}{0.6\textwidth}
+\begin{lstlisting}
+(inject #t Boolean)
+\end{lstlisting}
+\end{minipage}
+\\[2ex]\hline
+\begin{minipage}{0.25\textwidth}
+\begin{lstlisting}
+(+ |$e_1$| |$e_2$|)
+\end{lstlisting}
+\end{minipage}
+&
+$\Rightarrow$
+&
+\begin{minipage}{0.6\textwidth}
+\begin{lstlisting}
+(inject 
+   (+ (project |$e'_1$| Integer)
+      (project |$e'_2$| Integer))
+   Integer)
+\end{lstlisting}
+\end{minipage}
+\\[2ex]\hline
+\begin{minipage}{0.25\textwidth}
+\begin{lstlisting}
+(lambda (|$x_1 \ldots$|) |$e$|)
+\end{lstlisting}
+\end{minipage}
+&
+$\Rightarrow$
+&
+\begin{minipage}{0.6\textwidth}
+\begin{lstlisting}
+(lambda: ([|$x_1$|:Any]|$\ldots$|):Any |$e'$|)
+\end{lstlisting}
+\end{minipage}
+\\[2ex]\hline
+\begin{minipage}{0.25\textwidth}
+\begin{lstlisting}
+(app |$e_0$| |$e_1 \ldots e_n$|)
+\end{lstlisting}
+\end{minipage}
+&
+$\Rightarrow$
+&
+\begin{minipage}{0.6\textwidth}
+\begin{lstlisting}
+(app (project |$e'_0$| (Any|$\ldots$|Any -> Any))
+   |$e'_1 \ldots e'_n$|)
+\end{lstlisting}
+\end{minipage}
+\\[2ex]\hline
+\begin{minipage}{0.25\textwidth}
+\begin{lstlisting}
+(vector-ref |$e_1$| |$e_2$|)
+\end{lstlisting}
+\end{minipage}
+&
+$\Rightarrow$
+&
+\begin{minipage}{0.6\textwidth}
+\begin{lstlisting}
+(let ([tmp1 (project |$e'_1$| (Vectorof Any))])
+  (let ([tmp2 (project |$e'_2$| Integer)])
+     (vector-ref tmp1 tmp2)))
+\end{lstlisting}
+\end{minipage}
+\\[2ex]\hline
+\begin{minipage}{0.25\textwidth}
+\begin{lstlisting}
+(if |$e_1$| |$e_2$| |$e_3$|)
+\end{lstlisting}
+\end{minipage}
+&
+$\Rightarrow$
+&
+\begin{minipage}{0.6\textwidth}
+\begin{lstlisting}
+(if (eq? |$e'_1$| (inject #f Boolean))
+   |$e'_2$|
+   |$e'_3$|)
+\end{lstlisting}
+\end{minipage}
+\\[2ex]\hline
+\begin{minipage}{0.25\textwidth}
+\begin{lstlisting}
+(eq? |$e_1$| |$e_2$|)
+\end{lstlisting}
+\end{minipage}
+&
+$\Rightarrow$
+&
+\begin{minipage}{0.6\textwidth}
+\begin{lstlisting}
+(eq? |$e'_1$| |$e'_2$|)
+\end{lstlisting}
+\end{minipage}
+\\[2ex]\hline
+\begin{minipage}{0.25\textwidth}
+\begin{lstlisting}
+(and |$e_1$| |$e_2$|)
+\end{lstlisting}
+\end{minipage}
+&
+$\Rightarrow$
+&
+\begin{minipage}{0.6\textwidth}
+\begin{lstlisting}
+(let ([tmp |$e'_1$|])
+   (if (eq? t (inject #f Boolean))
+      tmp
+      |$e'_2$|))
+\end{lstlisting}
+\end{minipage} \\\hline
+\end{tabular}  \\
+
+\caption{Compiling $R_7$ (Untyped Racket) to $R_6$.}
+\label{fig:compile-r7-r6}
+\end{figure}
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \chapter{Gradual Typing}