Kaynağa Gözat

lower casts

Jeremy Siek 4 yıl önce
ebeveyn
işleme
f88f2bbd44
2 değiştirilmiş dosya ile 350 ekleme ve 233 silme
  1. 348 232
      book.tex
  2. 2 1
      defs.tex

+ 348 - 232
book.tex

@@ -9039,6 +9039,7 @@ expression may produce a value of a different type each time it is
 executed. Consider the following example with a conditional \code{if}
 executed. Consider the following example with a conditional \code{if}
 expression that may return a Boolean or an integer depending on the
 expression that may return a Boolean or an integer depending on the
 input to the program.
 input to the program.
+% part of  dynamic_test_25.rkt
 \begin{lstlisting}
 \begin{lstlisting}
    (not (if (eq? (read) 1) #f 0))
    (not (if (eq? (read) 1) #f 0))
 \end{lstlisting}
 \end{lstlisting}
@@ -9616,7 +9617,7 @@ result is \code{\#f}).
 &
 &
 $\Rightarrow$
 $\Rightarrow$
 &
 &
-\begin{minipage}{0.6\textwidth}
+\begin{minipage}{0.65\textwidth}
 \begin{lstlisting}
 \begin{lstlisting}
 (inject #t Boolean)
 (inject #t Boolean)
 \end{lstlisting}
 \end{lstlisting}
@@ -9630,7 +9631,7 @@ $\Rightarrow$
 &
 &
 $\Rightarrow$
 $\Rightarrow$
 &
 &
-\begin{minipage}{0.6\textwidth}
+\begin{minipage}{0.65\textwidth}
 \begin{lstlisting}
 \begin{lstlisting}
 (inject
 (inject
    (+ (project |$e'_1$| Integer)
    (+ (project |$e'_1$| Integer)
@@ -9647,7 +9648,7 @@ $\Rightarrow$
 &
 &
 $\Rightarrow$
 $\Rightarrow$
 &
 &
-\begin{minipage}{0.6\textwidth}
+\begin{minipage}{0.65\textwidth}
 \begin{lstlisting}
 \begin{lstlisting}
 (inject
 (inject
    (lambda: ([|$x_1$|:Any]|$\ldots$|[|$x_n$|:Any]):Any |$e'$|)
    (lambda: ([|$x_1$|:Any]|$\ldots$|[|$x_n$|:Any]):Any |$e'$|)
@@ -9663,7 +9664,7 @@ $\Rightarrow$
 &
 &
 $\Rightarrow$
 $\Rightarrow$
 &
 &
-\begin{minipage}{0.6\textwidth}
+\begin{minipage}{0.65\textwidth}
 \begin{lstlisting}
 \begin{lstlisting}
 ((project |$e'_0$| (Any|$\ldots$|Any -> Any)) |$e'_1 \ldots e'_n$|)
 ((project |$e'_0$| (Any|$\ldots$|Any -> Any)) |$e'_1 \ldots e'_n$|)
 \end{lstlisting}
 \end{lstlisting}
@@ -9677,7 +9678,7 @@ $\Rightarrow$
 &
 &
 $\Rightarrow$
 $\Rightarrow$
 &
 &
-\begin{minipage}{0.6\textwidth}
+\begin{minipage}{0.65\textwidth}
 \begin{lstlisting}
 \begin{lstlisting}
 (any-vector-ref |$e_1'$| |$e_2'$|)
 (any-vector-ref |$e_1'$| |$e_2'$|)
 \end{lstlisting}
 \end{lstlisting}
@@ -9691,7 +9692,7 @@ $\Rightarrow$
 &
 &
 $\Rightarrow$
 $\Rightarrow$
 &
 &
-\begin{minipage}{0.6\textwidth}
+\begin{minipage}{0.65\textwidth}
 \begin{lstlisting}
 \begin{lstlisting}
 (if (eq? |$e'_1$| (inject #f Boolean)) |$e'_3$| |$e'_2$|)
 (if (eq? |$e'_1$| (inject #f Boolean)) |$e'_3$| |$e'_2$|)
 \end{lstlisting}
 \end{lstlisting}
@@ -9705,12 +9706,27 @@ $\Rightarrow$
 &
 &
 $\Rightarrow$
 $\Rightarrow$
 &
 &
-\begin{minipage}{0.6\textwidth}
+\begin{minipage}{0.65\textwidth}
 \begin{lstlisting}
 \begin{lstlisting}
 (inject (eq? |$e'_1$| |$e'_2$|) Boolean)
 (inject (eq? |$e'_1$| |$e'_2$|) Boolean)
 \end{lstlisting}
 \end{lstlisting}
 \end{minipage}
 \end{minipage}
 \\[2ex]\hline
 \\[2ex]\hline
+\begin{minipage}{0.27\textwidth}
+\begin{lstlisting}
+(not |$e_1$|)
+\end{lstlisting}
+\end{minipage}
+&
+$\Rightarrow$
+&
+\begin{minipage}{0.65\textwidth}
+\begin{lstlisting}
+(if (eq? |$e'_1$| (inject #f Boolean))
+    (inject #t Boolean) (inject #f Boolean))
+\end{lstlisting}
+\end{minipage}
+\\[2ex]\hline
 \end{tabular} 
 \end{tabular} 
 
 
 \caption{Cast Insertion}
 \caption{Cast Insertion}
@@ -10085,6 +10101,8 @@ for the compilation of $R_7$.
 \chapter{Loops and Assignment}
 \chapter{Loops and Assignment}
 \label{ch:loop}
 \label{ch:loop}
 
 
+% todo: define R'_8
+
 In this chapter we study two features that are the hallmarks of
 In this chapter we study two features that are the hallmarks of
 imperative programming languages: loops and assignments to local
 imperative programming languages: loops and assignments to local
 variables. The following example demonstrates these new features by
 variables. The following example demonstrates these new features by
@@ -10105,14 +10123,12 @@ The \code{while} loop consists of a condition and a body.
 The \code{set!} consists of a variable and a right-hand-side expression.
 The \code{set!} consists of a variable and a right-hand-side expression.
 %
 %
 The primary purpose of both the \code{while} loop and \code{set!}  is
 The primary purpose of both the \code{while} loop and \code{set!}  is
-to cause side effects, so it is convenient to also include in $R_8$ a
+to cause side effects, so it is convenient to also include in a
 language feature for sequencing side effects: the \code{begin}
 language feature for sequencing side effects: the \code{begin}
 expression. It consists of one or more subexpressions that are
 expression. It consists of one or more subexpressions that are
 evaluated left-to-right.
 evaluated left-to-right.
-%
-The concrete syntax of $R_8$ is defined in
-Figure~\ref{fig:r8-concrete-syntax} and its abstract syntax is defined
-in Figure~\ref{fig:r8-syntax}.
+
+\section{The $R_8$ Language}
 
 
 \begin{figure}[tp]
 \begin{figure}[tp]
 \centering
 \centering
@@ -10174,6 +10190,10 @@ in Figure~\ref{fig:r8-syntax}.
 \label{fig:r8-syntax}
 \label{fig:r8-syntax}
 \end{figure}
 \end{figure}
 
 
+The concrete syntax of $R_8$ is defined in
+Figure~\ref{fig:r8-concrete-syntax} and its abstract syntax is defined
+in Figure~\ref{fig:r8-syntax}.
+%
 The definitional interpreter for $R_8$ is shown in
 The definitional interpreter for $R_8$ is shown in
 Figure~\ref{fig:interp-R8}. We add three new cases for \code{SetBang},
 Figure~\ref{fig:interp-R8}. We add three new cases for \code{SetBang},
 \code{WhileLoop}, and \code{Begin} and we make changes to the cases
 \code{WhileLoop}, and \code{Begin} and we make changes to the cases
@@ -11022,7 +11042,8 @@ in Figure~\ref{fig:r9-syntax}. The main syntactic difference between
 $R_8$ and $R_9$ is the additional \itm{param} and \itm{ret}
 $R_8$ and $R_9$ is the additional \itm{param} and \itm{ret}
 non-terminals that make type annotations optional. The return types
 non-terminals that make type annotations optional. The return types
 are not optional in the abstract syntax; the parser fills in
 are not optional in the abstract syntax; the parser fills in
-\code{Any} when the return type is not specified.
+\code{Any} when the return type is not specified in the concrete
+syntax.
 
 
 \begin{figure}[tp]
 \begin{figure}[tp]
 \centering
 \centering
@@ -11097,6 +11118,7 @@ present the example again but this time we leave off the type
 annotations from the \code{add1} function.
 annotations from the \code{add1} function.
 
 
 \begin{figure}[btp]
 \begin{figure}[btp]
+% gradual_test_9.rkt
 \begin{lstlisting}
 \begin{lstlisting}
 (define (map-vec [f : (Integer -> Integer)]
 (define (map-vec [f : (Integer -> Integer)]
                    [v : (Vector Integer Integer)])
                    [v : (Vector Integer Integer)])
@@ -11111,7 +11133,7 @@ annotations from the \code{add1} function.
 \label{fig:gradual-map-vec}
 \label{fig:gradual-map-vec}
 \end{figure}
 \end{figure}
 
 
-\section{Type Checking $R_9$}
+\section{Type Checking $R_9$, Casts, and $R'_9$}
 \label{sec:gradual-type-check}
 \label{sec:gradual-type-check}
 
 
 The type checker for $R_9$ uses the \code{Any} type for missing
 The type checker for $R_9$ uses the \code{Any} type for missing
@@ -11128,7 +11150,7 @@ Figure~\ref{fig:consistent} defines the \code{consistent?} predicate.
 
 
 \begin{figure}[tbp]
 \begin{figure}[tbp]
 \begin{lstlisting}
 \begin{lstlisting}
-(define (consistent? t1 t2)
+(define/public (consistent? t1 t2)
   (match* (t1 t2)
   (match* (t1 t2)
     [('Integer 'Integer) #t]
     [('Integer 'Integer) #t]
     [('Boolean 'Boolean) #t]
     [('Boolean 'Boolean) #t]
@@ -11142,7 +11164,8 @@ Figure~\ref{fig:consistent} defines the \code{consistent?} predicate.
           (consistent? rt1 rt2))]
           (consistent? rt1 rt2))]
     [(other wise) #f]))
     [(other wise) #f]))
 \end{lstlisting}
 \end{lstlisting}
-\caption{The consistency predicate on types.}
+\caption{The consistency predicate on types, a method in
+    \code{type-check-gradual-class}.}
 \label{fig:consistent}
 \label{fig:consistent}
 \end{figure}
 \end{figure}
 
 
@@ -11169,11 +11192,28 @@ error when the \code{maybe-add1} function returns \code{\#t}. $R_9$
 performs checking at runtime to ensure the integrity of the static
 performs checking at runtime to ensure the integrity of the static
 types, such as the \code{(Integer -> Integer)} annotation on parameter
 types, such as the \code{(Integer -> Integer)} annotation on parameter
 \code{f} of \code{map-vec}.  This runtime checking is carried out by a
 \code{f} of \code{map-vec}.  This runtime checking is carried out by a
-new \code{cast} form that is inserted by the type checker.  Thus, the
+new \code{Cast} form that is inserted by the type checker.  Thus, the
 output of the type checker is a program in the $R'_9$ language, which
 output of the type checker is a program in the $R'_9$ language, which
-adds \code{cast} to $R_9$.
+adds \code{Cast} to $R_8$, as shown in
+Figure~\ref{fig:r9-prime-syntax}.
+
+\begin{figure}[tp]
+\centering
+\fbox{
+\begin{minipage}{0.96\textwidth}
+\small
+\[
+\begin{array}{lcl}
+  \Exp &::=& \ldots \mid \CAST{\Exp}{\Type}{\Type} \\
+  R'_9 &::=& \gray{ \PROGRAMDEFSEXP{\code{'()}}{\LP\Def\ldots\RP}{\Exp} }
+\end{array}
+\]
+\end{minipage}
+}
+\caption{The abstract syntax of $R'_9$, extending $R_8$ (Figure~\ref{fig:r8-syntax}).}
+\label{fig:r9-prime-syntax}
+\end{figure}
 
 
-% TODO: grammar for $R'_9$
 
 
 \begin{figure}[tbp]
 \begin{figure}[tbp]
 \begin{lstlisting}
 \begin{lstlisting}
@@ -11192,7 +11232,7 @@ adds \code{cast} to $R_9$.
 \end{figure}
 \end{figure}
 
 
 Figure~\ref{fig:map-vec-cast} shows the output of the type checker for
 Figure~\ref{fig:map-vec-cast} shows the output of the type checker for
-\code{map-vec} and \code{maybe-add1}.  The idea is that \code{cast} is
+\code{map-vec} and \code{maybe-add1}.  The idea is that \code{Cast} is
 inserted every time the type checker sees two types that are
 inserted every time the type checker sees two types that are
 consistent but not equal. In the \code{add1} function, \code{x} is
 consistent but not equal. In the \code{add1} function, \code{x} is
 cast to \code{Integer} and the result of the \code{+} is cast to
 cast to \code{Integer} and the result of the \code{+} is cast to
@@ -11200,9 +11240,8 @@ cast to \code{Integer} and the result of the \code{+} is cast to
 is cast from \code{(Any -> Any)} to \code{(Integer -> Integer)}.
 is cast from \code{(Any -> Any)} to \code{(Integer -> Integer)}.
 
 
 \begin{figure}[btp]
 \begin{figure}[btp]
-\begin{lstlisting}
-(define (map-vec [f : (Integer -> Integer)]
-                   [v : (Vector Integer Integer)])
+\begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
+(define (map-vec [f : (Integer -> Integer)] [v : (Vector Integer Integer)])
                    : (Vector Integer Integer)
                    : (Vector Integer Integer)
   (vector (f (vector-ref v 0)) (f (vector-ref v 1))))
   (vector (f (vector-ref v 0)) (f (vector-ref v 1))))
 (define (add1 [x : Any]) : Any
 (define (add1 [x : Any]) : Any
@@ -11211,12 +11250,10 @@ is cast from \code{(Any -> Any)} to \code{(Integer -> Integer)}.
 (define (maybe-add1 [x : Any]) : Any
 (define (maybe-add1 [x : Any]) : Any
   (if (eq? 0 (read)) (add1 x) (true)))
   (if (eq? 0 (read)) (add1 x) (true)))
 
 
-(vector-ref (map-vec (cast maybe-add1 (Any -> Any)
-                                          (Integer -> Integer))
-                       (vector 0 41))
-              0)
+(vector-ref (map-vec (cast maybe-add1 (Any -> Any) (Integer -> Integer))
+                       (vector 0 41)) 0)
 \end{lstlisting}
 \end{lstlisting}
-\caption{Output from type checking \code{map-vec}
+\caption{Output of type checking \code{map-vec}
   and \code{maybe-add1}.}
   and \code{maybe-add1}.}
 \label{fig:map-vec-cast}
 \label{fig:map-vec-cast}
 \end{figure}
 \end{figure}
@@ -11224,92 +11261,90 @@ is cast from \code{(Any -> Any)} to \code{(Integer -> Integer)}.
 
 
 The type checker for $R_9$ is defined in
 The type checker for $R_9$ is defined in
 Figures~\ref{fig:type-check-R9-1}, \ref{fig:type-check-R9-2},
 Figures~\ref{fig:type-check-R9-1}, \ref{fig:type-check-R9-2},
-\ref{fig:type-check-R9-3}, and \ref{fig:type-check-R9-4}.
+and \ref{fig:type-check-R9-3}.
 
 
 
 
 \begin{figure}[tbp]
 \begin{figure}[tbp]
-\begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
+\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
 (define type-check-gradual-class
 (define type-check-gradual-class
   (class type-check-R8-class
   (class type-check-R8-class
     (super-new)
     (super-new)
-    (inherit check-type-equal? operator-types type-predicates)
-    
-    (define/public (check-consistent? t1 t2 e)
-      (unless (consistent? t1 t2)
-        (error 'type-check "~a is inconsistent with ~a\nin ~v" t1 t2 e)))
+    (inherit operator-types type-predicates)
 
 
-    (define/override (type-check-op op arg-types args e)
-      (match (dict-ref (operator-types) op)
-        [`(,param-types . ,return-type)
-         (for ([at arg-types] [pt param-types]) 
-           (check-consistent? at pt e))
-         (values return-type
-                 (for/list ([e args] [s arg-types] [t param-types])
-                   (make-cast e s t)))]
-        [else (error 'type-check-op "unrecognized ~a" op)]))
-
-    (define explicit-prim-ops
-      (set-union (type-predicates)
-       (set 'procedure-arity 'eq?
-            'vector 'vector-length 'vector-ref 'vector-set!
-            'any-vector-length 'any-vector-ref 'any-vector-set!)))
-    
     (define/override (type-check-exp env)
     (define/override (type-check-exp env)
       (lambda (e)
       (lambda (e)
 	(define recur (type-check-exp env))
 	(define recur (type-check-exp env))
 	(match e
 	(match e
-          [(Prim 'eq? (list e1 e2))
-           (define-values (e1^ t1) (recur e1))
-           (define-values (e2^ t2) (recur e2))
-           (check-consistent? t1 t2 e)
-           (define T (meet t1 t2))
-           (values (Prim 'eq? (list (make-cast e1^ t1 T) (make-cast e2^ t2 T)))
-                   'Boolean)]
 	  [(Prim 'vector-length (list e1))
 	  [(Prim 'vector-length (list e1))
            (define-values (e1^ t) (recur e1))
            (define-values (e1^ t) (recur e1))
 	   (match t
 	   (match t
-             ['Any (values (Prim 'any-vector-length (list e1^)) 'Integer)]
              [`(Vector ,ts ...)
              [`(Vector ,ts ...)
-              (values (Prim 'vector-length (list e1^)) 'Integer)])]
-\end{lstlisting}
-\caption{Type checker for the $R_9$ language, part 1.}
-\label{fig:type-check-R9-1}
-\end{figure}
-
-\begin{figure}[tbp]
-\begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
+              (values (Prim 'vector-length (list e1^)) 'Integer)]
+             ['Any (values (Prim 'any-vector-length (list e1^)) 'Integer)])]
 	  [(Prim 'vector-ref (list e1 e2))
 	  [(Prim 'vector-ref (list e1 e2))
-           (define-values (e1^ t) (recur e1))
-           (define-values (e2^ it) (recur e2))
-           (check-consistent? it 'Integer e)
-	   (match (list t e2^)
-             [(list 'Any ei)
-              (define e2^^ (make-cast e2^ it 'Integer))
+           (define-values (e1^ t1) (recur e1))
+           (define-values (e2^ t2) (recur e2))
+           (check-consistent? t2 'Integer e)
+	   (match t1
+	     [`(Vector ,ts ...)
+              (match e2^
+                [(Int i)
+                 (unless (and (0 . <= . i) (i . < . (length ts)))
+                   (error 'type-check "invalid index ~a in ~a" i e))
+                 (values (Prim 'vector-ref (list e1^ (Int i))) (list-ref ts i))]
+                [else (define e1^^ (make-cast e1^ t1 'Any))
+                      (define e2^^ (make-cast e2^ t2 'Integer))
+                      (values (Prim 'any-vector-ref (list e1^^ e2^^)) 'Any)])]
+             ['Any
+              (define e2^^ (make-cast e2^ t2 'Integer))
               (values (Prim 'any-vector-ref (list e1^ e2^^)) 'Any)]
               (values (Prim 'any-vector-ref (list e1^ e2^^)) 'Any)]
-	     [(list `(Vector ,ts ...) (Int i))
-              (unless (and (0 . <= . i) (i . < . (length ts)))
-                (error 'type-check "invalid index ~a in ~a" i e))
-              (values (Prim 'vector-ref (list e1^ (Int i))) (list-ref ts i))])]
+             [else (error 'type-check "expected vector not ~a\nin ~v" t1 e)])]
 	  [(Prim 'vector-set! (list e1 e2 e3) )
 	  [(Prim 'vector-set! (list e1 e2 e3) )
-           (define-values (e1^ t-vec) (recur e1))
-           (define-values (e2^ it) (recur e2))
-           (define-values (e3^ t-arg) (recur e3))
-           (check-consistent? it 'Integer e)
-	   (match t-vec
+           (define-values (e1^ t1) (recur e1))
+           (define-values (e2^ t2) (recur e2))
+           (define-values (e3^ t3) (recur e3))
+           (check-consistent? t2 'Integer e)
+	   (match t1
 	     [`(Vector ,ts ...)
 	     [`(Vector ,ts ...)
               (match e2^
               (match e2^
                 [(Int i)
                 [(Int i)
                  (unless (and (0 . <= . i) (i . < . (length ts)))
                  (unless (and (0 . <= . i) (i . < . (length ts)))
                    (error 'type-check "invalid index ~a in ~a" i e))
                    (error 'type-check "invalid index ~a in ~a" i e))
-                 (check-consistent? (list-ref ts i) t-arg e)
-                 (define e3^^ (make-cast e3^ t-arg (list-ref ts i)))
-                 (values (Prim 'vector-set! (list e1^ (Int i) e3^^)) 'Void)])]
+                 (check-consistent? (list-ref ts i) t3 e)
+                 (define e3^^ (make-cast e3^ t3 (list-ref ts i)))
+                 (values (Prim 'vector-set! (list e1^ (Int i) e3^^)) 'Void)]
+                [else
+                 (define e1^^ (make-cast e1^ t1 'Any))
+                 (define e2^^ (make-cast e2^ t2 'Integer))
+                 (define e3^^ (make-cast e3^ t3 'Any))
+                 (values (Prim 'any-vector-set! (list e1^^ e2^^ e3^^)) 'Void)])]
              ['Any
              ['Any
-              (define e2^^ (make-cast e2^ it 'Integer))
-              (define e3^^ (make-cast e3^ t-arg 'Any))
+              (define e2^^ (make-cast e2^ t2 'Integer))
+              (define e3^^ (make-cast e3^ t3 'Any))
               (values (Prim 'any-vector-set! (list e1^ e2^^ e3^^)) 'Void)]
               (values (Prim 'any-vector-set! (list e1^ e2^^ e3^^)) 'Void)]
-	     [else
-              (error 'type-check "expected vector not ~a\nin ~v" t-vec e)])]
+	     [else (error 'type-check "expected vector not ~a\nin ~v" t1 e)])]
+\end{lstlisting}
+\caption{Type checker for the $R_9$ language, part 1.}
+\label{fig:type-check-R9-1}
+\end{figure}
+
+\begin{figure}[tbp]
+\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
+          [(Prim 'eq? (list e1 e2))
+           (define-values (e1^ t1) (recur e1))
+           (define-values (e2^ t2) (recur e2))
+           (check-consistent? t1 t2 e)
+           (define T (meet t1 t2))
+           (values (Prim 'eq? (list (make-cast e1^ t1 T) (make-cast e2^ t2 T)))
+                   'Boolean)]
+          [(Prim 'not (list e1))
+           (recur (If (Prim 'eq? (list e1 (Inject (Bool #f) 'Boolean)))
+                      (Bool #t) (Bool #f)))]
+          [(Prim 'and (list e1 e2))
+           (recur (If e1 e2 (Bool #f)))]
+          [(Prim 'or (list e1 e2))
+           (define tmp (gensym 'tmp))
+           (recur (Let tmp e1 (If (Var tmp) (Var tmp) e2)))]
 	  [(Prim op es)
 	  [(Prim op es)
            #:when (not (set-member? explicit-prim-ops op))
            #:when (not (set-member? explicit-prim-ops op))
            (define-values (new-es ts)
            (define-values (new-es ts)
@@ -11317,15 +11352,36 @@ Figures~\ref{fig:type-check-R9-1}, \ref{fig:type-check-R9-2},
                (recur e)))
                (recur e)))
            (define-values (t-ret new-es^) (type-check-op op ts new-es e))
            (define-values (t-ret new-es^) (type-check-op op ts new-es e))
            (values (Prim op new-es^) t-ret)]
            (values (Prim op new-es^) t-ret)]
-          [(If cnd thn els)
-           (define-values (c Tc) (recur cnd))
-	   (define-values (t Tt) (recur thn))
-	   (define-values (e Te) (recur els))
-	   (check-consistent? Tc 'Boolean e)
-	   (check-consistent? Tt Te e)
-           (define Tb (join Tt Te))
-	   (values (If (make-cast c Tc 'Boolean) (make-cast t Tt Tb)
-                       (make-cast e Te Tb)) Tb)]
+          [(If e1 e2 e3)
+           (define-values (e1^ T1) (recur e1))
+	   (define-values (e2^ T2) (recur e2))
+	   (define-values (e3^ T3) (recur e3))
+	   (check-consistent? T2 T3 e)
+           (match T1
+             ['Boolean
+              (define Tif (join T2 T3))
+              (values (If e1^ (make-cast e2^ T2 Tif)
+                          (make-cast e3^ T3 Tif)) Tif)]
+             ['Any
+              (define Tif (meet T2 T3))
+              (values (If (Prim 'eq? (list e1^ (Inject (Bool #f) 'Boolean)))
+                          (make-cast e3^ T3 Tif) (make-cast e2^ T2 Tif))
+                      Tif)]
+             [else (error 'type-check "expected Boolean not ~a\nin ~v" T1 e)])]
+          [(HasType e1 T)
+           (define-values (e1^ T1) (recur e1))
+           (check-consistent? T1 T)
+           (values (make-cast e1^ T1 T) T)]          
+          [(SetBang x e1)
+           (define-values (e1^ T1) (recur e1))
+           (define varT (dict-ref env x))
+           (check-consistent? T1 varT e)
+           (values (SetBang x (make-cast e1^ T1 varT)) 'Void)]
+          [(WhileLoop e1 e2)
+           (define-values (e1^ T1) (recur e1))
+           (check-consistent? T1 'Boolean e)
+           (define-values (e2^ T2) ((type-check-exp env) e2))
+           (values (WhileLoop (make-cast e1^ T1 'Boolean) e2^) 'Void)]
 \end{lstlisting}
 \end{lstlisting}
 \caption{Type checker for the $R_9$ language, part 2.}
 \caption{Type checker for the $R_9$ language, part 2.}
 \label{fig:type-check-R9-2}
 \label{fig:type-check-R9-2}
@@ -11333,50 +11389,34 @@ Figures~\ref{fig:type-check-R9-1}, \ref{fig:type-check-R9-2},
 
 
 
 
 \begin{figure}[tbp]
 \begin{figure}[tbp]
-\begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
-          [(HasType e1 T)
-           (define-values (e1^ T1) (recur e1))
-           (check-consistent? T1 T)
-           (values (make-cast e1^ T1 T) T)]
-	  [(Apply e es)
-	   (define-values (e* ty*) (for/lists (e* ty*) ([e (in-list es)])
-                                     (recur e)))
-	   (define-values (e^ ty) (recur e))
-	   (match ty
-	     [`(,ty^* ... -> ,rt)
-              (for ([arg-ty ty*] [param-ty ty^*])
-                (check-consistent? arg-ty param-ty e))
-              (define new-args (for/list ([e e*] [s ty*] [t ty^*])
-                                 (make-cast e s t)))
-	      (values (Apply e^ new-args) rt)]
+\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
+	  [(Apply e1 e2s)
+	   (define-values (e1^ T1) (recur e1))
+	   (define-values (e2s^ T2s) (for/lists (e* ty*) ([e2 e2s]) (recur e2)))
+	   (match T1
+	     [`(,T1ps ... -> ,T1rt)
+              (for ([T2 T2s] [Tp T1ps])
+                (check-consistent? T2 Tp e))
+              (define e2s^^ (for/list ([e2 e2s^] [src T2s] [tgt T1ps])
+                              (make-cast e2 src tgt)))
+	      (values (Apply e1^ e2s^^) T1rt)]
              [`Any
              [`Any
-              (define new-fun
-                (make-cast e^ 'Any `(,@(for/list ([e es]) 'Any) -> Any)))
-              (define new-args (for/list ([e e*] [s ty*])
-                                 (make-cast e s 'Any)))
-              (values (Apply new-fun new-args) 'Any)]
-	     [else (error 'type-check
-                          "expected a function, not ~a\nin ~v" ty e)])]
-          [(Lambda params rT body)
+              (define e1^^ (make-cast e1^ 'Any
+                                      `(,@(for/list ([e e2s]) 'Any) -> Any)))
+              (define e2s^^ (for/list ([e2 e2s^] [src T2s])
+                              (make-cast e2 src 'Any)))
+              (values (Apply e1^^ e2s^^) 'Any)]
+	     [else (error 'type-check "expected function not ~a\nin ~v" T1 e)])]
+          [(Lambda params Tr e1)
            (define-values (xs Ts) (for/lists (l1 l2) ([p params])
            (define-values (xs Ts) (for/lists (l1 l2) ([p params])
                                     (match p
                                     (match p
                                       [`[,x : ,T] (values x T)]
                                       [`[,x : ,T] (values x T)]
                                       [(? symbol? x) (values x 'Any)])))
                                       [(? symbol? x) (values x 'Any)])))
-           (define-values (new-body bodyT) 
-             ((type-check-exp (append (map cons xs Ts) env)) body))
-           (check-consistent? rT bodyT e)
-           (values (Lambda (for/list ([x xs] [T Ts]) `[,x : ,T]) rT
-                           (make-cast new-body bodyT rT)) `(,@Ts -> ,rT))]
-          [(SetBang x rhs)
-           (define-values (rhs^ rhsT) (recur rhs))
-           (define varT (dict-ref env x))
-           (check-consistent? rhsT varT e)
-           (values (SetBang x (make-cast rhs^ rhsT varT)) 'Void)]
-          [(WhileLoop cnd body)
-           (define-values (cnd^ Tc) (recur cnd))
-           (check-consistent? Tc 'Boolean e)
-           (define-values (body^ Tbody) ((type-check-exp env) body))
-           (values (WhileLoop (make-cast cnd^ Tc 'Boolean) body^) 'Void)]
+           (define-values (e1^ T1) 
+             ((type-check-exp (append (map cons xs Ts) env)) e1))
+           (check-consistent? Tr T1 e)
+           (values (Lambda (for/list ([x xs] [T Ts]) `[,x : ,T]) Tr
+                           (make-cast e1^ T1 Tr)) `(,@Ts -> ,Tr))]
           [else  ((super type-check-exp env) e)]
           [else  ((super type-check-exp env) e)]
           )))
           )))
 \end{lstlisting}
 \end{lstlisting}
@@ -11385,13 +11425,61 @@ Figures~\ref{fig:type-check-R9-1}, \ref{fig:type-check-R9-2},
 \end{figure}
 \end{figure}
 
 
 
 
-
 \begin{figure}[tbp]
 \begin{figure}[tbp]
-\begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
+\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
+    (define/public (join t1 t2)
+      (match* (t1 t2)
+        [('Integer 'Integer) 'Integer]
+        [('Boolean 'Boolean) 'Boolean]
+        [('Void  'Void) 'Void]
+        [('Any t2) t2]
+        [(t1 'Any) t1]
+        [(`(Vector ,ts1 ...) `(Vector ,ts2 ...))
+         `(Vector ,@(for/list ([t1 ts1] [t2 ts2]) (join t1 t2)))]
+        [(`(,ts1 ... -> ,rt1) `(,ts2 ... -> ,rt2))
+         `(,@(for/list ([t1 ts1] [t2 ts2]) (join t1 t2))
+           -> ,(join rt1 rt2))]))
+
+    (define/public (meet t1 t2)
+      (match* (t1 t2)
+        [('Integer 'Integer) 'Integer]
+        [('Boolean  'Boolean) 'Boolean]
+        [('Void 'Void) 'Void]
+        [('Any t2) 'Any]
+        [(t1 'Any) 'Any]
+        [(`(Vector ,ts1 ...) `(Vector ,ts2 ...))
+         `(Vector ,@(for/list ([t1 ts1] [t2 ts2]) (meet t1 t2)))]
+        [(`(,ts1 ... -> ,rt1) `(,ts2 ... -> ,rt2))
+         `(,@(for/list ([t1 ts1] [t2 ts2]) (meet t1 t2))
+           -> ,(meet rt1 rt2))]))
+
+    (define/public (make-cast e src tgt)
+      (cond [(equal? src tgt) e] [else (Cast e src tgt)]))
+
+    (define/public (check-consistent? t1 t2 e)
+      (unless (consistent? t1 t2)
+        (error 'type-check "~a is inconsistent with ~a\nin ~v" t1 t2 e)))
+
+    (define/override (type-check-op op arg-types args e)
+      (match (dict-ref (operator-types) op)
+        [`(,param-types . ,return-type)
+         (for ([at arg-types] [pt param-types]) 
+           (check-consistent? at pt e))
+         (values return-type
+                 (for/list ([e args] [s arg-types] [t param-types])
+                   (make-cast e s t)))]
+        [else (error 'type-check-op "unrecognized ~a" op)]))
+
+    (define explicit-prim-ops
+      (set-union
+       (type-predicates)
+       (set 'procedure-arity 'eq?
+            'vector 'vector-length 'vector-ref 'vector-set!
+            'any-vector-length 'any-vector-ref 'any-vector-set!)))
+
     (define/override (fun-def-type d)
     (define/override (fun-def-type d)
       (match d
       (match d
 	[(Def f params rt info body)
 	[(Def f params rt info body)
-         (debug 'fun-def-type "parameters:" params)
          (define ps
          (define ps
            (for/list ([p params])
            (for/list ([p params])
              (match p
              (match p
@@ -11400,82 +11488,6 @@ Figures~\ref{fig:type-check-R9-1}, \ref{fig:type-check-R9-2},
                [else (error 'fun-def-type "unmatched parameter ~a" p)])))
                [else (error 'fun-def-type "unmatched parameter ~a" p)])))
 	 `(,@ps -> ,rt)]
 	 `(,@ps -> ,rt)]
 	[else (error 'fun-def-type "ill-formed function definition in ~a" d)]))
 	[else (error 'fun-def-type "ill-formed function definition in ~a" d)]))
-
-    (define/override (type-check-def env)
-      (lambda (e)
-	(match e
-	  [(Def f params rt info body)
-           (define-values (xs ps) (for/lists (l1 l2) ([p params])
-                                    (match p
-                                      [`[,x : ,T] (values x T)]
-                                      [(? symbol? x) (values x 'Any)])))
-	   (define new-env (append (map cons xs ps) env))
-	   (define-values (body^ ty^) ((type-check-exp new-env) body))
-	   (check-consistent? ty^ rt e)
-	   (Def f (for/list ([x xs] [T ps]) `[,x : ,T]) rt info
-             (make-cast body^ ty^ rt))]
-	  [else (error 'type-check "ill-formed function definition ~a" e)]
-	  )))
-    
-    (define/override (type-check-program e)
-      (match e
-        [(Program info body)
-         (define-values (body^ ty) ((type-check-exp '()) body))
-         (check-consistent? ty 'Integer e)
-         (ProgramDefsExp info '() (make-cast body^ ty 'Integer))]
-        [(ProgramDefsExp info ds body)
-         (define new-env (for/list ([d ds]) 
-                           (cons (Def-name d) (fun-def-type d))))
-         (define ds^ (for/list ([d ds])
-                       ((type-check-def new-env) d)))
-         (define-values (body^ ty) ((type-check-exp new-env) body))
-         (check-consistent? ty 'Integer e)
-         (ProgramDefsExp info ds^ (make-cast body^ ty 'Integer))]
-        [else (super type-check-program e)]))
-    
-    ))
-
-(define (type-check-gradual p)
-  (send (new type-check-gradual-class) type-check-program p))
-\end{lstlisting}
-\caption{Type checker for the $R_9$ language, part 4.}
-\label{fig:type-check-R9-4}
-\end{figure}
-
-  
-\begin{figure}[tbp]
-\begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
-(define (join t1 t2)
-  (match* (t1 t2)
-    [('Integer 'Integer) 'Integer]
-    [('Boolean 'Boolean) 'Boolean]
-    [('Void  'Void) 'Void]
-    [('Any t2) t2]
-    [(t1 'Any) t1]
-    [(`(Vector ,ts1 ...) `(Vector ,ts2 ...))
-     `(Vector ,@(for/list ([t1 ts1] [t2 ts2]) (join t1 t2)))]
-    [(`(,ts1 ... -> ,rt1) `(,ts2 ... -> ,rt2))
-     `(,@(for/list ([t1 ts1] [t2 ts2]) (join t1 t2))
-       -> ,(join rt1 rt2))]
-    [(other wise) (error 'join "inconsistent types ~a and ~a" t1 t2)]))
-
-(define (meet t1 t2)
-  (match* (t1 t2)
-    [('Integer 'Integer) 'Integer]
-    [('Boolean  'Boolean) 'Boolean]
-    [('Void 'Void) 'Void]
-    [('Any t2) 'Any]
-    [(t1 'Any) 'Any]
-    [(`(Vector ,ts1 ...) `(Vector ,ts2 ...))
-     `(Vector ,@(for/list ([t1 ts1] [t2 ts2]) (meet t1 t2)))]
-    [(`(,ts1 ... -> ,rt1) `(,ts2 ... -> ,rt2))
-     `(,@(for/list ([t1 ts1] [t2 ts2]) (meet t1 t2))
-       -> ,(meet rt1 rt2))]
-    [(other wise) (error 'meet "inconsistent types ~a and ~a" t1 t2)]))
-
-(define (make-cast e src tgt)
-  (cond [(equal? src tgt) e]
-        [else (Cast e src tgt)]))
 \end{lstlisting}
 \end{lstlisting}
 \caption{Auxiliary functions for type checking $R_9$.}
 \caption{Auxiliary functions for type checking $R_9$.}
 \label{fig:type-check-R9-aux}
 \label{fig:type-check-R9-aux}
@@ -11489,10 +11501,10 @@ Figures~\ref{fig:type-check-R9-1}, \ref{fig:type-check-R9-2},
 The runtime behavior of first-order casts is straightforward, that is,
 The runtime behavior of first-order casts is straightforward, that is,
 casts involving simple types such as \code{Integer} and
 casts involving simple types such as \code{Integer} and
 \code{Boolean}.  For example, a cast from \code{Integer} to \code{Any}
 \code{Boolean}.  For example, a cast from \code{Integer} to \code{Any}
-can be accomplished with the \code{inject} operator of $R_6$, which
+can be accomplished with the \code{Inject} operator of $R_6$, which
 puts the integer into a tagged value
 puts the integer into a tagged value
 (Figure~\ref{fig:interp-R6}). Similarly, a cast from \code{Any} to
 (Figure~\ref{fig:interp-R6}). Similarly, a cast from \code{Any} to
-\code{Integer} is accomplished with the \code{project} operator, that
+\code{Integer} is accomplished with the \code{Project} operator, that
 is, by checking the value's tag and either retrieving the underlying
 is, by checking the value's tag and either retrieving the underlying
 integer or signaling an error if it the tag is not the one for
 integer or signaling an error if it the tag is not the one for
 integers (Figure~\ref{fig:apply-project}).
 integers (Figure~\ref{fig:apply-project}).
@@ -11528,6 +11540,7 @@ the updates inside of \code{map-vec!} would happen to the new vector
 and not the original one.
 and not the original one.
 
 
 \begin{figure}[tbp]
 \begin{figure}[tbp]
+  % gradual_test_11.rkt
 \begin{lstlisting}
 \begin{lstlisting}
 (define (map-vec! [f : (Any -> Any)]
 (define (map-vec! [f : (Any -> Any)]
                   [v : (Vector Any Any)]) : Void
                   [v : (Vector Any Any)]) : Void
@@ -11545,7 +11558,7 @@ and not the original one.
 \end{figure}
 \end{figure}
 
 
 Instead the interpreter needs to create a new kind of value, a
 Instead the interpreter needs to create a new kind of value, a
-\emph{vector proxy}, that interposes on every vector operation. On a
+\emph{vector proxy}, that intercepts every vector operation. On a
 read, the proxy reads from the underlying vector and then applies a
 read, the proxy reads from the underlying vector and then applies a
 cast to the resulting value.  On a write, the proxy casts the argument
 cast to the resulting value.  On a write, the proxy casts the argument
 value and then performs the write to the underlying vector. For the
 value and then performs the write to the underlying vector. For the
@@ -11555,16 +11568,16 @@ first \code{(vector-ref v 0)} in \code{map-vec!}, the proxy casts
 to \code{Integer}.
 to \code{Integer}.
 
 
 The final category of cast that we need to consider are casts between
 The final category of cast that we need to consider are casts between
-the \code{Any} type and either a function or a
-vector. Figure~\ref{fig:map-vec-any} shows a variant of
-\code{map-vec!} in which parameter \code{v} does not have a type
-annotation, so it is given type \code{Any}. In the call to
-\code{map-vec!}, the vector has type \code{(Vector Integer Integer)}
-so the type checker inserts a cast from \code{(Vector Integer
-  Integer)} to \code{Any}. A first thought is to use \code{inject},
-but that doesn't work because \code{(Vector Integer Integer)} is not a
-flat type. Instead, we must first cast to \code{(Vector Any Any)}
-(which is flat) and then inject to \code{Any}. 
+the \code{Any} type and either a function or a vector
+type. Figure~\ref{fig:map-vec-any} shows a variant of \code{map-vec!}
+in which parameter \code{v} does not have a type annotation, so it is
+given type \code{Any}. In the call to \code{map-vec!}, the vector has
+type \code{(Vector Integer Integer)} so the type checker inserts a
+cast from \code{(Vector Integer Integer)} to \code{Any}. A first
+thought is to use \code{Inject}, but that doesn't work because
+\code{(Vector Integer Integer)} is not a flat type. Instead, we must
+first cast to \code{(Vector Any Any)} (which is flat) and then inject
+to \code{Any}.
 
 
 \begin{figure}[tbp]
 \begin{figure}[tbp]
 \begin{lstlisting}
 \begin{lstlisting}
@@ -11578,7 +11591,7 @@ flat type. Instead, we must first cast to \code{(Vector Any Any)}
 (let ([v (vector 0 41)])
 (let ([v (vector 0 41)])
   (begin (map-vec! add1 v) (vector-ref v 1)))
   (begin (map-vec! add1 v) (vector-ref v 1)))
 \end{lstlisting}
 \end{lstlisting}
-\caption{}
+\caption{Casting a vector to \code{Any}.}
 \label{fig:map-vec-any}
 \label{fig:map-vec-any}
 \end{figure}
 \end{figure}
 
 
@@ -11640,7 +11653,7 @@ The interpreter for $R'_9$ is defined in
 Figure~\ref{fig:interp-R9-prime}, with the case for \code{Cast}
 Figure~\ref{fig:interp-R9-prime}, with the case for \code{Cast}
 dispatching to \code{apply-cast}. To handle the addition of vector
 dispatching to \code{apply-cast}. To handle the addition of vector
 proxies, we update the vector primitives in \code{interp-op} using the
 proxies, we update the vector primitives in \code{interp-op} using the
-auxiliary functions in Figure~\ref{fig:guarded-vector}.
+functions in Figure~\ref{fig:guarded-vector}.
 
 
 \begin{figure}[tbp]
 \begin{figure}[tbp]
 \begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
 \begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
@@ -11711,22 +11724,125 @@ auxiliary functions in Figure~\ref{fig:guarded-vector}.
 \end{figure}
 \end{figure}
 
 
 
 
-
 \section{Lower Casts}
 \section{Lower Casts}
 \label{sec:lower-casts}
 \label{sec:lower-casts}
 
 
+The next step in the journey towards x86 is the \code{lower-casts}
+pass that translates the casts in $R'_9$ to the lower-level
+\code{Inject} and \code{Project} operators and a new operator for
+creating vector proxies, extending the $R'_8$ language to create
+$R''_8$. We recommend creating an auxiliary function named
+\code{lower-cast} that takes an expression (in $R'_9$), a source type,
+and a target type, and translates it to expression in $R''_8$ that has
+the same behavior as casting the expression from the source to the
+target type in the interpreter.
+
+The \code{lower-cast} function can follow a code structure similar to
+the \code{apply-cast} function (Figure~\ref{fig:apply-cast}) used in
+the interpreter for $R'_9$ because it must handle the same cases as
+\code{apply-cast} and it needs to mimic the behavior of
+\code{apply-cast}. The most interesting cases are those concerning the
+casts between two vector types and between two function types.
+
+As mentioned in Section~\ref{sec:interp-casts}, a cast from one vector
+type to another vector type is accomplished by creating a proxy that
+intercepts the operations on the underlying vector. Here we make the
+creation of the proxy explicit with the \code{vector-proxy} primitive
+operation. It takes three arguments, the first is an expression for
+the vector, the second is a vector of functions for casting an element
+that is being read from the vector, and the third is a vector of
+functions for casting an element that is being written to the vector.
+You can create the functions using \code{Lambda}. Also, as we shall
+see in the next section, we need to differentiate these vectors from
+the user-created ones, so we recommend using a new primitive operator
+named \code{raw-vector} instead of \code{vector} to create these
+vectors of functions. Figure~\ref{fig:map-vec-bang-lower-cast} shows
+the output of \code{lower-casts} on the example in
+Figure~\ref{fig:map-vec-bang} that involved casting a vector of
+integers to a vector of \code{Any}.
+
+\begin{figure}[tbp]
+\begin{lstlisting}
+(define (map-vec! [f : (Any -> Any)] [v : (Vector Any Any)]) : Void
+   (begin 
+      (vector-set! v 0 (f (vector-ref v 0)))
+      (vector-set! v 1 (f (vector-ref v 1)))))
+  
+(define (add1 [x : Any]) : Any
+   (inject (+ (project x Integer) 1) Integer))
+
+(let ([v (vector 0 41)])
+   (begin 
+      (map-vec! add1 (vector-proxy v
+                        (raw-vector (lambda: ([x9 : Integer]) : Any
+                                       (inject x9 Integer))
+                                     (lambda: ([x9 : Integer]) : Any
+                                       (inject x9 Integer)))
+                        (raw-vector (lambda: ([x9 : Any]) : Integer
+                                       (project x9 Integer))
+                                    (lambda: ([x9 : Any]) : Integer
+                                       (project x9 Integer)))))
+      (vector-ref v 1)))
+\end{lstlisting}
+\caption{Output of \code{lower-casts} on the example in
+  Figure~\ref{fig:map-vec-bang}.}
+\label{fig:map-vec-bang-lower-cast}
+\end{figure}
+
+A cast from one function type to another function type is accomplished
+by generating a \code{Lambda} whose parameter and return types match
+the target function type. The body of the \code{Lambda} should cast
+the parameters from the target type to the source type (yes,
+backwards! functions are contravariant\index{contravariant} in the
+parameters), then call the underlying function, and finally cast the
+result from the source return type to the target return type.
+Figure~\ref{fig:map-vec-lower-cast} shows the output of the
+\code{lower-casts} pass on the \code{map-vec} example in
+Figure~\ref{fig:gradual-map-vec}. Note that the \code{add1} argument
+in the call to \code{map-vec} is wrapped in a \code{lambda}.
+
+\begin{figure}[tbp]
+\begin{lstlisting}
+(define (map-vec [f : (Integer -> Integer)]
+                   [v : (Vector Integer Integer)])
+                   : (Vector Integer Integer)
+  (vector (f (vector-ref v 0)) (f (vector-ref v 1))))
+
+(define (add1 [x : Any]) : Any
+  (inject (+ (project x Integer) 1) Integer))
+
+(vector-ref (map-vec (lambda: ([x9 : Integer]) : Integer
+                        (project (add1 (inject x9 Integer)) Integer))
+                      (vector 0 41)) 1)
+\end{lstlisting}
+\caption{Output of \code{lower-casts} on the example in
+  Figure~\ref{fig:gradual-map-vec}.}
+\label{fig:map-vec-lower-cast}
+\end{figure}
 
 
 
 
 \section{Expose Proxies}
 \section{Expose Proxies}
 \label{sec:expose-proxies}
 \label{sec:expose-proxies}
 
 
+UNDER CONSTRUCTION
+
 
 
 \section{Closure Conversion}
 \section{Closure Conversion}
 
 
+UNDER CONSTRUCTION
+
 \section{Explicate Control}
 \section{Explicate Control}
 
 
+UNDER CONSTRUCTION
+
 \section{Select Instructions}
 \section{Select Instructions}
 
 
+UNDER CONSTRUCTION
+
+\section{Further Reading}
+
+UNDER CONSTRUCTION
+
 
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \chapter{Parametric Polymorphism}
 \chapter{Parametric Polymorphism}

+ 2 - 1
defs.tex

@@ -51,11 +51,12 @@
 \newcommand{\CUNIOP}[2]{\LP #1\;#2 \RP}
 \newcommand{\CUNIOP}[2]{\LP #1\;#2 \RP}
 \newcommand{\BINOP}[3]{\key{(Prim}\;#1\;\code{(list}\;#2\;#3\code{))}}
 \newcommand{\BINOP}[3]{\key{(Prim}\;#1\;\code{(list}\;#2\;#3\code{))}}
 \newcommand{\CBINOP}[3]{\LP #1\;#2\;#3\RP}
 \newcommand{\CBINOP}[3]{\LP #1\;#2\;#3\RP}
-\newcommand{\CLET}[3]{\LP\key{let}~\LP\LS\Var~\Exp\RS\RP~\Exp\RP}
+\newcommand{\CLET}[3]{\LP\key{let}~\LP\LS#1~#2\RS\RP~#3\RP}
 \newcommand{\CIF}[3]{\LP\key{if}~#1~#2~#3\RP}
 \newcommand{\CIF}[3]{\LP\key{if}~#1~#2~#3\RP}
 \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{\CAST}[3]{\LP\key{Cast}~#1~#2~#3\RP}
 \newcommand{\VECTOR}[1]{\LP\key{Prim}\;\code{'vector}\;\LP\key{list}\;#1\RP\RP}
 \newcommand{\VECTOR}[1]{\LP\key{Prim}\;\code{'vector}\;\LP\key{list}\;#1\RP\RP}
 \newcommand{\VECREF}[2]{\LP\key{Prim}\;\code{'vector-ref}\;\LP\key{list}\;#1\;#2\RP\RP}
 \newcommand{\VECREF}[2]{\LP\key{Prim}\;\code{'vector-ref}\;\LP\key{list}\;#1\;#2\RP\RP}
 \newcommand{\VECSET}[3]{\LP\key{Prim}\;\code{'vector-set!}\;\LP\key{list}\;#1\;#2\;#3\RP\RP}
 \newcommand{\VECSET}[3]{\LP\key{Prim}\;\code{'vector-set!}\;\LP\key{list}\;#1\;#2\;#3\RP\RP}