浏览代码

progress on Ch 5

Jeremy Siek 4 年之前
父节点
当前提交
15a2633e7a
共有 2 个文件被更改,包括 177 次插入204 次删除
  1. 173 204
      book.tex
  2. 4 0
      defs.tex

+ 173 - 204
book.tex

@@ -1658,7 +1658,7 @@ each of the compiler passes in Figure~\ref{fig:R1-passes}.
 The output of \key{explicate-control} is similar to the $C$
 The output of \key{explicate-control} is similar to the $C$
 language~\citep{Kernighan:1988nx} in that it has separate syntactic
 language~\citep{Kernighan:1988nx} in that it has separate syntactic
 categories for expressions and statements, so we name it $C_0$.  The
 categories for expressions and statements, so we name it $C_0$.  The
-concrete syntax for $C_0$ is define din
+concrete syntax for $C_0$ is defined in
 Figure~\ref{fig:c0-concrete-syntax} and the abstract syntax for $C_0$
 Figure~\ref{fig:c0-concrete-syntax} and the abstract syntax for $C_0$
 is defined in Figure~\ref{fig:c0-syntax}.
 is defined in Figure~\ref{fig:c0-syntax}.
 %
 %
@@ -2055,25 +2055,6 @@ on the body of the \key{program} and then associate the \code{locals}
 symbol with the resulting list of variables in the $\itm{info}$ field,
 symbol with the resulting list of variables in the $\itm{info}$ field,
 as in the above example.
 as in the above example.
 
 
-%% \section{Uncover Locals}
-%% \label{sec:uncover-locals-r1}
-
-%% The pass \code{uncover-locals} simply collects all of the variables in
-%% the program and places then in the $\itm{info}$ of the program
-%% construct. Here is the output for the example program of the last
-%% section.
-
-%% \begin{minipage}{0.4\textwidth}
-%% \begin{lstlisting}
-%% (program ((locals . (x.1 x.2 y)))
-%%   ((start . 
-%%    (seq (assign x.1 20)
-%%    (seq (assign x.2 22)
-%%    (seq (assign y (+ x.1 x.2))
-%%    (return y)))))))
-%% \end{lstlisting}
-%% \end{minipage}
-
 \section{Select Instructions}
 \section{Select Instructions}
 \label{sec:select-r1}
 \label{sec:select-r1}
 
 
@@ -3750,22 +3731,6 @@ association list.
 \label{fig:type-check-R2}
 \label{fig:type-check-R2}
 \end{figure}
 \end{figure}
 
 
-%% To print the resulting value correctly, the overall type of the
-%% program must be threaded through the remainder of the passes. We can
-%% store the type within the \key{program} form as shown in Figure
-%% \ref{fig:type-check-R2}. Let $R^\dagger_2$ be the name for the
-%% intermediate language produced by the type checker, which we define as
-%% follows: \\[1ex]
-%% \fbox{
-%% \begin{minipage}{0.87\textwidth}
-%% \[
-%% \begin{array}{lcl}
-%%   R^\dagger_2 &::=& (\key{program}\;(\key{type}\;\itm{type})\; \Exp)
-%% \end{array}
-%% \]
-%% \end{minipage}
-%% }
-
 \begin{exercise}\normalfont
 \begin{exercise}\normalfont
 Complete the implementation of \code{type-check-R2} and test it on 10
 Complete the implementation of \code{type-check-R2} and test it on 10
 new example programs in $R_2$ that you choose based on how thoroughly
 new example programs in $R_2$ that you choose based on how thoroughly
@@ -4125,7 +4090,8 @@ new kind of context to deal with: the predicate position of the
 \key{if}. We need another function, \code{explicate-pred}, that takes
 \key{if}. We need another function, \code{explicate-pred}, that takes
 an $R_2$ expression and two pieces of $C_1$ code (two $\Tail$'s) for
 an $R_2$ expression and two pieces of $C_1$ code (two $\Tail$'s) for
 the then-branch and else-branch. The output of \code{explicate-pred}
 the then-branch and else-branch. The output of \code{explicate-pred}
-is a $C_1$ $\Tail$.  However, these three functions also need to
+is a $C_1$ $\Tail$ and a list of formerly \key{let}-bound variables.
+However, these three functions also need to
 construct the control-flow graph, which we recommend they do via
 construct the control-flow graph, which we recommend they do via
 updates to a global variable (be careful!). Next we consider the
 updates to a global variable (be careful!). Next we consider the
 specific additions to the tail and assign functions, and some of cases
 specific additions to the tail and assign functions, and some of cases
@@ -4134,30 +4100,29 @@ for the pred function.
 The \code{explicate-tail} function needs an additional case for
 The \code{explicate-tail} function needs an additional case for
 \key{if}. The branches of the \key{if} inherit the current context, so
 \key{if}. The branches of the \key{if} inherit the current context, so
 they are in tail position.  Let $B_1$ be the result of
 they are in tail position.  Let $B_1$ be the result of
-\code{explicate-tail} on the $\itm{thn}$ branch and $B_2$ be the
-result of apply \code{explicate-tail} to the $\itm{else}$ branch. Then
-the \key{if} as a whole translates to the block $B_3$ which is the
-result of applying \code{explicate-pred} to the predicate $\itm{cnd}$
-and the blocks $B_1$ and $B_2$.
+\code{explicate-tail} on the ``then'' branch of the \key{if} and $B_2$
+be the result of apply \code{explicate-tail} to the ``else''
+branch. Then the \key{if} as a whole translates to the block $B_3$
+which is the result of applying \code{explicate-pred} to the predicate
+$\itm{cnd}$ and the blocks $B_1$ and $B_2$.
 \[
 \[
     (\key{if}\; \itm{cnd}\; \itm{thn}\; \itm{els}) \quad\Rightarrow\quad B_3
     (\key{if}\; \itm{cnd}\; \itm{thn}\; \itm{els}) \quad\Rightarrow\quad B_3
 \]
 \]
 
 
-Next we consider the case for \key{if} in the
-\code{explicate-assign} function. The context of the
-\key{if} is an assignment to some variable $x$ and then the control
-continues to some block $B_1$.  The code that we generate for the
-$\itm{thn}$ and $\itm{els}$ branches needs to continue to
-$B_1$, so we add $B_1$ to the control flow graph with a fresh label
-$\ell_1$.  Again, the branches of the \key{if} inherit the current
-context, so that are in assignment positions.  Let $B_2$ be the result
-of applying \code{explicate-assign} to the $\itm{thn}$ branch,
-variable $x$, and the block \GOTO{$\ell_1$}.  Let $B_3$ be the
-result of applying \code{explicate-assign} to the $\itm{else}$
-branch, variable $x$, and the block \GOTO{$\ell_1$}. The
+Next we consider the case for \key{if} in the \code{explicate-assign}
+function. The context of the \key{if} is an assignment to some
+variable $x$ and then the control continues to some block $B_1$.  The
+code that we generate for the $\itm{thn}$ and $\itm{els}$ branches
+needs to continue to $B_1$, so we add $B_1$ to the control flow graph
+with a fresh label $\ell_1$.  Again, the branches of the \key{if}
+inherit the current context, so that are in assignment positions.  Let
+$B_2$ be the result of applying \code{explicate-assign} to the
+$\itm{thn}$ branch, variable $x$, and the block \GOTO{$\ell_1$}.  Let
+$B_3$ be the result of applying \code{explicate-assign} to the
+$\itm{else}$ branch, variable $x$, and the block \GOTO{$\ell_1$}. The
 \key{if} translates to the block $B_4$ which is the result of applying
 \key{if} translates to the block $B_4$ which is the result of applying
-\code{explicate-pred} to the predicate $\itm{cnd}$ and the
-blocks $B_2$ and $B_3$.
+\code{explicate-pred} to the predicate $\itm{cnd}$ and the blocks
+$B_2$ and $B_3$.
 \[
 \[
 (\key{if}\; \itm{cnd}\; \itm{thn}\; \itm{els}) \quad\Rightarrow\quad B_4
 (\key{if}\; \itm{cnd}\; \itm{thn}\; \itm{els}) \quad\Rightarrow\quad B_4
 \]
 \]
@@ -4166,11 +4131,21 @@ The function \code{explicate-pred} will need a case for every
 expression that can have type \code{Boolean}. We detail a few cases
 expression that can have type \code{Boolean}. We detail a few cases
 here and leave the rest for the reader. The input to this function is
 here and leave the rest for the reader. The input to this function is
 an expression and two blocks, $B_1$ and $B_2$, for the branches of the
 an expression and two blocks, $B_1$ and $B_2$, for the branches of the
-enclosing \key{if}. One of the base cases of this function is when the
+enclosing \key{if}. Suppose the expression is the Boolean \code{\#t}.
+Then we can perform a kind of partial evaluation and translate it to the
+``then'' branch $B_1$. Likewise, we translate
+\code{\#f} to the ``else`` branch $B_2$.
+\[
+\key{\#t} \quad\Rightarrow\quad B_1,
+\qquad\qquad\qquad
+\key{\#f} \quad\Rightarrow\quad B_2
+\]
+Next, suppose the
 expression is a less-than comparison. We translate it to a conditional
 expression is a less-than comparison. We translate it to a conditional
 goto. We need labels for the two branches $B_1$ and $B_2$, so we add
 goto. We need labels for the two branches $B_1$ and $B_2$, so we add
-them to the control flow graph and obtain some labels $\ell_1$ and
-$\ell_2$. The translation of the less-than comparison is as follows.
+those blocks to the control flow graph and obtain some labels $\ell_1$
+and $\ell_2$. The translation of the less-than comparison is as
+follows.
 \[
 \[
 (\key{<}~e_1~e_2) \quad\Rightarrow\quad
 (\key{<}~e_1~e_2) \quad\Rightarrow\quad
 \begin{array}{l}
 \begin{array}{l}
@@ -4201,10 +4176,10 @@ B_5
 \]
 \]
 
 
 \begin{exercise}\normalfont
 \begin{exercise}\normalfont
-  Implement the pass \code{explicate-code} by adding the cases for
+  Implement the pass \code{explicate-control} by adding the cases for
   \key{if} to the functions for tail and assignment contexts, and
   \key{if} to the functions for tail and assignment contexts, and
-  implement the function for predicate contexts. Create test cases
-  that exercise all of the new cases in the code for this pass.
+  implement \code{explicate-pred} for predicate contexts. Create test
+  cases that exercise all of the new cases in the code for this pass.
 \end{exercise}
 \end{exercise}
 
 
 
 
@@ -4383,52 +4358,6 @@ and test your compiler using your previously created programs on the
 \end{exercise}
 \end{exercise}
 
 
 
 
-%% \section{Lower Conditionals (New Pass)}
-%% \label{sec:lower-conditionals}
-
-%% In the \code{select-instructions} pass we decided to procrastinate in
-%% the lowering of the \key{if} statement, thereby making liveness
-%% analysis easier. Now we need to make up for that and turn the \key{if}
-%% statement into the appropriate instruction sequence.  The following
-%% translation gives the general idea. If the condition is true, we need
-%% to execute the $\itm{thns}$ branch and otherwise we need to execute
-%% the $\itm{elss}$ branch. So we use \key{cmpq} and do a conditional
-%% jump to the $\itm{thenlabel}$, choosing the condition code $cc$ that
-%% is appropriate for the comparison operator \itm{cmp}.  If the
-%% condition is false, we fall through to the $\itm{elss}$ branch. At the
-%% end of the $\itm{elss}$ branch we need to take care to not fall
-%% through to the $\itm{thns}$ branch. So we jump to the
-%% $\itm{endlabel}$. All of the labels in the generated code should be
-%% created with \code{gensym}.
-
-%% \begin{tabular}{lll}
-%% \begin{minipage}{0.4\textwidth}
-%% \begin{lstlisting}
-%%  (if (|\itm{cmp}| |$\Arg_1$| |$\Arg_2$|) |$\itm{thns}$| |$\itm{elss}$|)
-%% \end{lstlisting}
-%% \end{minipage}
-%% &
-%% $\Rightarrow$
-%% &
-%% \begin{minipage}{0.4\textwidth}
-%% \begin{lstlisting}
-%%  (cmpq |$\Arg_2$| |$\Arg_1$|)
-%%  (jmp-if |$cc$| |$\itm{thenlabel}$|)
-%%  |$\itm{elss}$|
-%%  (jmp |$\itm{endlabel}$|)
-%%  (label |$\itm{thenlabel}$|)
-%%  |$\itm{thns}$|
-%%  (label |$\itm{endlabel}$|)
-%% \end{lstlisting}
-%% \end{minipage}
-%% \end{tabular}
-
-%% \begin{exercise}\normalfont
-%% Implement the \code{lower-conditionals} pass. Test your compiler using
-%% your previously created programs on the \code{interp-x86} interpreter
-%% (Appendix~\ref{appendix:interp}).
-%% \end{exercise}
-
 \section{Patch Instructions}
 \section{Patch Instructions}
 
 
 The second argument of the \key{cmpq} instruction must not be an
 The second argument of the \key{cmpq} instruction must not be an
@@ -4542,7 +4471,7 @@ conclusion:
 \node (R2-4) at (9,2)  {\large $R_2$};
 \node (R2-4) at (9,2)  {\large $R_2$};
 \node (R2-5) at (12,2)  {\large $R_2$};
 \node (R2-5) at (12,2)  {\large $R_2$};
 \node (C1-1) at (6,0)  {\large $C_1$};
 \node (C1-1) at (6,0)  {\large $C_1$};
-\node (C1-2) at (3,0)  {\large $C_1$};
+%\node (C1-2) at (3,0)  {\large $C_1$};
 
 
 \node (x86-2) at (3,-2)  {\large $\text{x86}^{*}$};
 \node (x86-2) at (3,-2)  {\large $\text{x86}^{*}$};
 \node (x86-3) at (6,-2)  {\large $\text{x86}^{*}$};
 \node (x86-3) at (6,-2)  {\large $\text{x86}^{*}$};
@@ -4557,8 +4486,8 @@ conclusion:
 \path[->,bend left=15] (R2-3) edge [above] node {\ttfamily\footnotesize uniquify} (R2-4);
 \path[->,bend left=15] (R2-3) edge [above] node {\ttfamily\footnotesize uniquify} (R2-4);
 \path[->,bend left=15] (R2-4) edge [above] node {\ttfamily\footnotesize remove-complex.} (R2-5);
 \path[->,bend left=15] (R2-4) edge [above] node {\ttfamily\footnotesize remove-complex.} (R2-5);
 \path[->,bend left=15] (R2-5) edge [right] node {\ttfamily\footnotesize\color{red} explicate-control} (C1-1);
 \path[->,bend left=15] (R2-5) edge [right] node {\ttfamily\footnotesize\color{red} explicate-control} (C1-1);
-\path[->,bend right=15] (C1-1) edge [above] node {\ttfamily\footnotesize uncover-locals} (C1-2);
-\path[->,bend right=15] (C1-2) edge [left] node {\ttfamily\footnotesize\color{red} select-instr.} (x86-2);
+%\path[->,bend right=15] (C1-1) edge [above] node {\ttfamily\footnotesize uncover-locals} (C1-2);
+\path[->,bend right=15] (C1-1) edge [left] node {\ttfamily\footnotesize\color{red} select-instructions} (x86-2);
 \path[->,bend left=15] (x86-2) edge [right] node {\ttfamily\footnotesize\color{red} uncover-live} (x86-2-1);
 \path[->,bend left=15] (x86-2) edge [right] node {\ttfamily\footnotesize\color{red} uncover-live} (x86-2-1);
 \path[->,bend right=15] (x86-2-1) edge [below] node {\ttfamily\footnotesize build-inter.} (x86-2-2);
 \path[->,bend right=15] (x86-2-1) edge [below] node {\ttfamily\footnotesize build-inter.} (x86-2-2);
 \path[->,bend right=15] (x86-2-2) edge [right] node {\ttfamily\footnotesize allocate-reg.} (x86-3);
 \path[->,bend right=15] (x86-2-2) edge [right] node {\ttfamily\footnotesize allocate-reg.} (x86-3);
@@ -4804,9 +4733,10 @@ program in Figure~\ref{fig:vector-eg} shows the usage of tuples in
 Racket. We create a 3-tuple \code{t} and a 1-tuple. The 1-tuple is
 Racket. We create a 3-tuple \code{t} and a 1-tuple. The 1-tuple is
 stored at index $2$ of the 3-tuple, demonstrating that tuples are
 stored at index $2$ of the 3-tuple, demonstrating that tuples are
 first-class values.  The element at index $1$ of \code{t} is
 first-class values.  The element at index $1$ of \code{t} is
-\code{\#t}, so the ``then'' branch is taken.  The element at index $0$
-of \code{t} is $40$, to which we add the $2$, the element at index $0$
-of the 1-tuple.
+\code{\#t}, so the ``then'' branch of the \key{if} is taken.  The
+element at index $0$ of \code{t} is $40$, to which we add $2$, the
+element at index $0$ of the 1-tuple. So the result of the program is
+$42$.
 
 
 \begin{figure}[tbp]
 \begin{figure}[tbp]
 \begin{lstlisting}
 \begin{lstlisting}
@@ -4869,6 +4799,10 @@ of the 1-tuple.
       \mid \NOT{\Exp} } \\
       \mid \NOT{\Exp} } \\
      &\mid& \gray{ \BINOP{\code{'}\itm{cmp}}{\Exp}{\Exp}
      &\mid& \gray{ \BINOP{\code{'}\itm{cmp}}{\Exp}{\Exp}
       \mid \IF{\Exp}{\Exp}{\Exp} } \\
       \mid \IF{\Exp}{\Exp}{\Exp} } \\
+     &\mid& \VECTOR{\Exp} \\
+     &\mid& \VECREF{\Exp}{\Int}\\
+     &\mid& \VECSET{\Exp}{\Int}{\Exp}\\
+      &\mid& \VOID{} \\
   R_3 &::=& \PROGRAM{\key{'()}}{\Exp}
   R_3 &::=& \PROGRAM{\key{'()}}{\Exp}
 \end{array}
 \end{array}
 \]
 \]
@@ -4887,12 +4821,16 @@ be \emph{aliases} for the same thing. Consider the following example
 in which both \code{t1} and \code{t2} refer to the same tuple.  Thus,
 in which both \code{t1} and \code{t2} refer to the same tuple.  Thus,
 the mutation through \code{t2} is visible when referencing the tuple
 the mutation through \code{t2} is visible when referencing the tuple
 from \code{t1}, so the result of this program is \code{42}.
 from \code{t1}, so the result of this program is \code{42}.
+\begin{center}
+\begin{minipage}{0.96\textwidth}
 \begin{lstlisting}
 \begin{lstlisting}
     (let ([t1 (vector 3 7)])
     (let ([t1 (vector 3 7)])
       (let ([t2 t1])
       (let ([t2 t1])
         (let ([_ (vector-set! t2 0 42)])
         (let ([_ (vector-set! t2 0 42)])
           (vector-ref t1 0))))
           (vector-ref t1 0))))
 \end{lstlisting}
 \end{lstlisting}
+\end{minipage}
+\end{center}
 
 
 The next issue concerns the lifetime of tuples. Of course, they are
 The next issue concerns the lifetime of tuples. Of course, they are
 created by the \code{vector} form, but when does their lifetime end?
 created by the \code{vector} form, but when does their lifetime end?
@@ -4901,12 +4839,17 @@ an operation for deleting tuples. Furthermore, the lifetime of a tuple
 is not tied to any notion of static scoping. For example, the
 is not tied to any notion of static scoping. For example, the
 following program returns \code{3} even though the variable \code{t}
 following program returns \code{3} even though the variable \code{t}
 goes out of scope prior to accessing the vector.
 goes out of scope prior to accessing the vector.
+\begin{center}
+\begin{minipage}{0.96\textwidth}
 \begin{lstlisting}
 \begin{lstlisting}
     (vector-ref
     (vector-ref
       (let ([t (vector 3 7)])
       (let ([t (vector 3 7)])
         t)
         t)
       0)
       0)
 \end{lstlisting}
 \end{lstlisting}
+\end{minipage}
+\end{center}
+
 From the perspective of programmer-observable behavior, tuples live
 From the perspective of programmer-observable behavior, tuples live
 forever. Of course, if they really lived forever, then many programs
 forever. Of course, if they really lived forever, then many programs
 would run out of memory.\footnote{The $R_3$ language does not have
 would run out of memory.\footnote{The $R_3$ language does not have
@@ -4926,20 +4869,6 @@ in $R_3$. In contrast, Racket defines the \code{void?} predicate that
 returns \code{\#t} when applied to \code{\#<void>} and \code{\#f}
 returns \code{\#t} when applied to \code{\#<void>} and \code{\#f}
 otherwise.
 otherwise.
 
 
-Figure~\ref{fig:typecheck-R3} shows the type checker for $R_3$ , which
-deserves some explanation. As we shall see in Section~\ref{sec:GC}, we
-need to know which variables are pointers into the heap, that is,
-which variables are vectors. Also, when allocating a vector, we shall
-need to know which elements of the vector are pointers. We can obtain
-this information during type checking and when we uncover local
-variables. The type checker in Figure~\ref{fig:typecheck-R3} not only
-computes the type of an expression, it also wraps every sub-expression
-$e$ with the form $(\key{has-type}\; e\; T)$, where $T$ is $e$'s
-type. Subsequently, in the \code{uncover-locals} pass
-(Section~\ref{sec:uncover-locals-r3}) this type information is
-propagated to all variables (including the temporaries generated by
-\code{remove-complex-opera*}).
-
 \begin{figure}[tbp]
 \begin{figure}[tbp]
 \begin{lstlisting}
 \begin{lstlisting}
     (define primitives (set ... 'vector 'vector-ref 'vector-set!))
     (define primitives (set ... 'vector 'vector-ref 'vector-set!))
@@ -4963,6 +4892,21 @@ propagated to all variables (including the temporaries generated by
 \label{fig:interp-R3}
 \label{fig:interp-R3}
 \end{figure}
 \end{figure}
 
 
+Figure~\ref{fig:typecheck-R3} shows the type checker for $R_3$, which
+deserves some explanation. As we shall see in Section~\ref{sec:GC}, we
+need to know which variables are pointers into the heap, that is,
+which variables are vectors. Also, when allocating a vector, we need
+to know which elements of the vector are pointers. We can obtain this
+information during type checking. The type checker in
+Figure~\ref{fig:typecheck-R3} not only computes the type of an
+expression, it also wraps every sub-expression $e$ with the form
+$(\key{HasType}~e~T)$, where $T$ is $e$'s type.
+% TODO: UPDATE? -Jeremy
+Subsequently, in the \code{uncover-locals} pass
+(Section~\ref{sec:uncover-locals-r3}) this type information is
+propagated to all variables (including the temporaries generated by
+\code{remove-complex-opera*}).
+
 \begin{figure}[tbp]
 \begin{figure}[tbp]
 \begin{lstlisting}
 \begin{lstlisting}
 (define (type-check-exp env)
 (define (type-check-exp env)
@@ -4970,30 +4914,30 @@ propagated to all variables (including the temporaries generated by
     (define recur (type-check-exp env))
     (define recur (type-check-exp env))
     (match e
     (match e
       ...
       ...
-      ['(void) (values '(has-type (void) Void) 'Void)]
-      [`(vector ,es ...)
+      [(Void) (values (HasType (Void) 'Void) 'Void)]
+      [(Prim 'vector es)
        (define-values (e* t*) (for/lists (e* t*) ([e es])
        (define-values (e* t*) (for/lists (e* t*) ([e es])
                                 (recur e)))
                                 (recur e)))
        (let ([t `(Vector ,@t*)])
        (let ([t `(Vector ,@t*)])
-         (debug "vector/type-check-exp finished vector" t)
-         (values `(has-type (vector ,@e*) ,t) t))]
-      [`(vector-ref ,e ,i)
+         (values (HasType (Prim 'vector e*) t) t))]
+      [(Prim 'vector-ref (list e (Int i)))
        (define-values (e^ t) (recur e))
        (define-values (e^ t) (recur e))
        (match t
        (match t
          [`(Vector ,ts ...)
          [`(Vector ,ts ...)
           (unless (and (exact-nonnegative-integer? i) (< i (length ts)))
           (unless (and (exact-nonnegative-integer? i) (< i (length ts)))
             (error 'type-check-exp "invalid index ~a" i))
             (error 'type-check-exp "invalid index ~a" i))
           (let ([t (list-ref ts i)])
           (let ([t (list-ref ts i)])
-            (values `(has-type (vector-ref ,e^ (has-type ,i Integer)) ,t) 
-                    t))]
+            (values
+             (HasType (Prim 'vector-ref (list e^ (HasType (Int i) 'Integer))) t)
+             t))]
          [else (error "expected a vector in vector-ref, not" t)])]
          [else (error "expected a vector in vector-ref, not" t)])]
-      [`(eq? ,arg1 ,arg2)
-       (define-values (e1 t1) (recur arg1))
-       (define-values (e2 t2) (recur arg2))
-       (match* (t1 t2)
-         [(`(Vector ,ts1 ...) `(Vector ,ts2 ...))
-          (values `(has-type (eq? ,e1 ,e2) Boolean) 'Boolean)]
-         [(other wise) ((super type-check-exp env) e)])]
+      [(Prim 'eq? (list e1 e2))
+       (define-values (e1^ T1) (recur e1))
+       (define-values (e2^ T2) (recur e2))
+       (unless (equal? T1 T2)
+         (error "arguments of eq? must have the same type, but are not"
+                (list T1 T2)))
+       (values (HasType (Prim 'eq? (list e1^ e2^)) 'Boolean) 'Boolean)]
       ...
       ...
       )))
       )))
 \end{lstlisting}
 \end{lstlisting}
@@ -5298,7 +5242,7 @@ accesses the element in the inner tuple tuple via two vector
 references.
 references.
 % tests/s2_17.rkt
 % tests/s2_17.rkt
 \begin{lstlisting}
 \begin{lstlisting}
-    (vector-ref (vector-ref (vector (vector 42)) 0) 0))
+(vector-ref (vector-ref (vector (vector 42)) 0) 0))
 \end{lstlisting}
 \end{lstlisting}
 
 
 Next we proceed to discuss the new \code{expose-allocation} pass.
 Next we proceed to discuss the new \code{expose-allocation} pass.
@@ -5365,34 +5309,40 @@ Figure~\ref{fig:expose-alloc-output} shows the output of the
 \code{expose-allocation} pass on our running example.
 \code{expose-allocation} pass on our running example.
 
 
 \begin{figure}[tbp]
 \begin{figure}[tbp]
+% tests/s2_17.rkt
 \begin{lstlisting}
 \begin{lstlisting}
-(program ()
+(vector-ref
  (vector-ref
  (vector-ref
-  (vector-ref
-   (let ((vecinit48
-          (let ((vecinit44 42))
-            (let ((collectret46
-                   (if (<
-                        (+ (global-value free_ptr) 16)
-                        (global-value fromspace_end))
-                     (void)
-                     (collect 16))))
-              (let ((alloc43 (allocate 1 (Vector Integer))))
-                (let ((initret45 (vector-set! alloc43 0 vecinit44)))
-                  alloc43))))))
-     (let ((collectret50
-            (if (< (+ (global-value free_ptr) 16)
-                   (global-value fromspace_end))
-              (void)
-              (collect 16))))
-       (let ((alloc47 (allocate 1 (Vector (Vector Integer)))))
-         (let ((initret49 (vector-set! alloc47 0 vecinit48)))
-           alloc47))))
-   0)
-  0))
+  (let ([vecinit7976
+         (let ([vecinit7972 42])
+           (let ([collectret7974
+                  (if (< (+ free_ptr 16) fromspace_end)
+                      (void)
+                      (collect 16);
+                      )])
+             (let ([alloc7971 (allocate 1 (Vector Integer))])
+               (let ([initret7973 (vector-set! alloc7971 0 vecinit7972)])
+                 alloc7971)
+               )
+             )
+           )
+         ])
+    (let ([collectret7978
+           (if (< (+ free_ptr 16) fromspace_end)
+               (void)
+               (collect 16);
+               )])
+      (let ([alloc7975 (allocate 1 (Vector (Vector Integer)))])
+        (let ([initret7977 (vector-set! alloc7975 0 vecinit7976)])
+          alloc7975)
+        )
+      )
+    )
+  0)
+ 0)
 \end{lstlisting}
 \end{lstlisting}
 \caption{Output of the \code{expose-allocation} pass, minus
 \caption{Output of the \code{expose-allocation} pass, minus
-  all of the \code{has-type} forms.}
+  all of the \code{HasType} forms.}
 \label{fig:expose-alloc-output}
 \label{fig:expose-alloc-output}
 \end{figure}
 \end{figure}
 
 
@@ -5442,47 +5392,66 @@ other forms.
 \section{Uncover Locals}
 \section{Uncover Locals}
 \label{sec:uncover-locals-r3}
 \label{sec:uncover-locals-r3}
 
 
-Recall that the \code{uncover-locals} function collects all of the
+Recall that the \code{explicate-control} function collects all of the
 local variables so that it can store them in the $\itm{info}$ field of
 local variables so that it can store them in the $\itm{info}$ field of
-the \code{program} form. Also recall that we need to know the types of
-all the local variables for purposes of identifying the root set for
-the garbage collector.  Thus, we change \code{uncover-locals} to
-collect not just the variables, but the variables and their types in
-the form of an association list. Thanks to the \code{has-type} forms,
-the types are readily available. Figure~\ref{fig:uncover-locals-r3}
-lists the output of the \code{uncover-locals} pass on the running
-example.
+the \code{Program} structure. Also recall that we need to know the
+types of all the local variables for purposes of identifying the root
+set for the garbage collector.  Thus, we create a pass named
+\code{uncover-locals} to collect not just the variables but the
+variables and their types in the form of an association list. Thanks
+to the \code{HasType} nodes, the types are readily available in the
+AST. Figure~\ref{fig:uncover-locals-r3} lists the output of the
+\code{uncover-locals} pass on the running example.
 
 
 \begin{figure}[tbp]
 \begin{figure}[tbp]
+% tests/s2_17.rkt
 \begin{lstlisting}
 \begin{lstlisting}
-(program
- ((locals . ((tmp54 . Integer) (tmp51 . Integer) (tmp53 . Integer)
-             (alloc43 . (Vector Integer)) (tmp55 . Integer)
-             (initret45 . Void) (alloc47 . (Vector (Vector Integer)))
-             (collectret46 . Void) (vecinit48 . (Vector Integer))
-             (tmp52 . Integer) (tmp57 . (Vector Integer))
-             (vecinit44 . Integer) (tmp56 . Integer) (initret49 . Void)
-             (collectret50 . Void))))
- ((block63 . (seq (collect 16) (goto block61)))
-  (block62 . (seq (assign collectret46 (void)) (goto block61)))
-  (block61 . (seq (assign alloc43 (allocate 1 (Vector Integer)))
-               (seq (assign initret45 (vector-set! alloc43 0 vecinit44))
-               (seq (assign vecinit48 alloc43)
-               (seq (assign tmp54 (global-value free_ptr))
-               (seq (assign tmp55 (+ tmp54 16))
-               (seq (assign tmp56 (global-value fromspace_end))
-               (if (< tmp55 tmp56) (goto block59) (goto block60)))))))))
-  (block60 . (seq (collect 16) (goto block58)))
-  (block59 . (seq (assign collectret50 (void)) (goto block58)))
-  (block58 . (seq (assign alloc47 (allocate 1 (Vector (Vector Integer))))
-               (seq (assign initret49 (vector-set! alloc47 0 vecinit48))
-               (seq (assign tmp57 (vector-ref alloc47 0))
-               (return (vector-ref tmp57 0))))))
-  (start . (seq (assign vecinit44 42)
-           (seq (assign tmp51 (global-value free_ptr))
-           (seq (assign tmp52 (+ tmp51 16))
-           (seq (assign tmp53 (global-value fromspace_end))
-           (if (< tmp52 tmp53) (goto block62) (goto block63)))))))))
+program:
+locals:
+    vecinit7976 : '(Vector Integer), tmp7980 : 'Integer,
+    alloc7975 : '(Vector (Vector Integer)), tmp7983 : 'Integer,
+    collectret7974 : 'Void, initret7977 : 'Void,
+    collectret7978 : 'Void, tmp7985 : '(Vector Integer),
+    tmp7984 : 'Integer, tmp7979 : 'Integer, tmp7982 : 'Integer,
+    alloc7971 : '(Vector Integer), tmp7981 : 'Integer, vecinit7972 : 'Integer,
+    initret7973 : 'Void, 
+block7991:
+    (collect 16);
+    goto block7989;
+block7990:
+    collectret7974 = (void);
+    goto block7989;
+block7989:
+    alloc7971 = (allocate 1 (Vector Integer));
+    initret7973 = (vector-set! alloc7971 0 vecinit7972);
+    vecinit7976 = alloc7971;
+    tmp7982 = free_ptr;
+    tmp7983 = (+ tmp7982 16);
+    tmp7984 = fromspace_end;
+    if (< tmp7983 tmp7984) then
+       goto block7987;
+    else
+       goto block7988;
+block7988:
+    (collect 16);
+    goto block7986;
+block7987:
+    collectret7978 = (void);
+    goto block7986;
+block7986:
+    alloc7975 = (allocate 1 (Vector (Vector Integer)));
+    initret7977 = (vector-set! alloc7975 0 vecinit7976);
+    tmp7985 = (vector-ref alloc7975 0);
+    return (vector-ref tmp7985 0);
+start:
+    vecinit7972 = 42;
+    tmp7979 = free_ptr;
+    tmp7980 = (+ tmp7979 16);
+    tmp7981 = fromspace_end;
+    if (< tmp7980 tmp7981) then
+       goto block7990;
+    else
+       goto block7991;
 \end{lstlisting}
 \end{lstlisting}
 \caption{Output of \code{uncover-locals} for the running example.}
 \caption{Output of \code{uncover-locals} for the running example.}
 \label{fig:uncover-locals-r3}
 \label{fig:uncover-locals-r3}

+ 4 - 0
defs.tex

@@ -33,6 +33,10 @@
 \newcommand{\VAR}[1]{\key{(Var}\;#1\key{)}}
 \newcommand{\VAR}[1]{\key{(Var}\;#1\key{)}}
 \newcommand{\LET}[3]{\key{(Let}~#1~#2~#3\key{)}}
 \newcommand{\LET}[3]{\key{(Let}~#1~#2~#3\key{)}}
 \newcommand{\IF}[3]{\key{(If}\,#1\;#2\;#3\key{)}}
 \newcommand{\IF}[3]{\key{(If}\,#1\;#2\;#3\key{)}}
+\newcommand{\VECTOR}[1]{\key{(Prim}\;\code{'vector}\;\code{(list}\;#1^{*}\code{))}}
+\newcommand{\VECREF}[2]{\key{(Prim}\;\code{'vector-ref}\;\code{(list}\;#1\;#2\code{))}}
+\newcommand{\VECSET}[3]{\key{(Prim}\;\code{'vector-set}\;\code{(list}\;#1\;#2\;#3\code{))}}
+\newcommand{\VOID}[1]{\key{(Void)}}
 
 
 \newcommand{\ASSIGN}[2]{\key{(Assign}~#1\;#2\key{)}}
 \newcommand{\ASSIGN}[2]{\key{(Assign}~#1\;#2\key{)}}
 \newcommand{\RETURN}[1]{\key{(Return}~#1\key{)}}
 \newcommand{\RETURN}[1]{\key{(Return}~#1\key{)}}