|
@@ -8267,50 +8267,46 @@ an extra closure parameter.
|
|
|
\section{An Example Translation}
|
|
|
\label{sec:example-lambda}
|
|
|
|
|
|
-Figure~\ref{fig:lexical-functions-example} shows the result of closure
|
|
|
-conversion for the example program demonstrating lexical scoping that
|
|
|
-we discussed at the beginning of this chapter.
|
|
|
+Figure~\ref{fig:lexical-functions-example} shows the result of
|
|
|
+\code{reveal-functions} and then \code{convert-to-closures} for the
|
|
|
+example program demonstrating lexical scoping that we discussed at the
|
|
|
+beginning of this chapter.
|
|
|
|
|
|
|
|
|
\begin{figure}[h]
|
|
|
-\begin{minipage}{0.8\textwidth}
|
|
|
+ \begin{minipage}{0.8\textwidth}
|
|
|
+% tests/s4_6.rkt
|
|
|
\begin{lstlisting}%[basicstyle=\ttfamily\footnotesize]
|
|
|
-(program
|
|
|
- (define (f [x : Integer]) : (Integer -> Integer)
|
|
|
- (let ([y 4])
|
|
|
- (lambda: ([z : Integer]) : Integer
|
|
|
- (+ x (+ y z)))))
|
|
|
- (let ([g (f 5)])
|
|
|
- (let ([h (f 3)])
|
|
|
- (+ (g 11) (h 15)))))
|
|
|
-\end{lstlisting}
|
|
|
-$\Downarrow$
|
|
|
-\begin{lstlisting}%[basicstyle=\ttfamily\footnotesize]
|
|
|
-(program (type Integer)
|
|
|
- (define (f (x : Integer)) : (Integer -> Integer)
|
|
|
- (let ((y 4))
|
|
|
- (lambda: ((z : Integer)) : Integer
|
|
|
- (+ x (+ y z)))))
|
|
|
- (let ((g (app (fun-ref f) 5)))
|
|
|
- (let ((h (app (fun-ref f) 3)))
|
|
|
- (+ (app g 11) (app h 15)))))
|
|
|
+(define (f74 [x75 : Integer]) : (Integer -> Integer)
|
|
|
+ (let ([y76 4])
|
|
|
+ (lambda: ( [z77 : Integer]) : Integer
|
|
|
+ (+ x75 (+ y76 z77)))))
|
|
|
+
|
|
|
+(define (main) : Integer
|
|
|
+ (let ([g78 ((fun-ref f74) 5)])
|
|
|
+ (let ([h79 ((fun-ref f74) 3)])
|
|
|
+ (+ (g78 11) (h79 15)))))
|
|
|
\end{lstlisting}
|
|
|
$\Downarrow$
|
|
|
\begin{lstlisting}%[basicstyle=\ttfamily\footnotesize]
|
|
|
-(program (type Integer)
|
|
|
- (define (f (clos.1 : _) (x : Integer)) : (Integer -> Integer)
|
|
|
- (let ((y 4))
|
|
|
- (vector (fun-ref lam.1) x y)))
|
|
|
- (define (lam.1 (clos.2 : _) (z : Integer)) : Integer
|
|
|
- (let ((x (vector-ref clos.2 1)))
|
|
|
- (let ((y (vector-ref clos.2 2)))
|
|
|
- (+ x (+ y z)))))
|
|
|
- (let ((g (let ((t.1 (vector (fun-ref f))))
|
|
|
- (app (vector-ref t.1 0) t.1 5))))
|
|
|
- (let ((h (let ((t.2 (vector (fun-ref f))))
|
|
|
- (app (vector-ref t.2 0) t.2 3))))
|
|
|
- (+ (let ((t.3 g)) (app (vector-ref t.3 0) t.3 11))
|
|
|
- (let ((t.4 h)) (app (vector-ref t.4 0) t.4 15))))))
|
|
|
+(define (f74 [fvs82 : _] [x75 : Integer]) : (Vector ((Vector _) Integer -> Integer))
|
|
|
+ (let ([y76 4])
|
|
|
+ (vector (fun-ref lambda80) x75 y76)))
|
|
|
+
|
|
|
+(define (lambda80 [fvs81 : (Vector _ Integer Integer)] [z77 : Integer]) : Integer
|
|
|
+ (let ([x75 (vector-ref fvs81 1)])
|
|
|
+ (let ([y76 (vector-ref fvs81 2)])
|
|
|
+ (+ x75 (+ y76 z77)))))
|
|
|
+
|
|
|
+(define (main) : Integer
|
|
|
+ (let ([g78 (let ([app83 (vector (fun-ref f74))])
|
|
|
+ ((vector-ref app83 0) app83 5))])
|
|
|
+ (let ([h79 (let ([app84 (vector (fun-ref f74))])
|
|
|
+ ((vector-ref app84 0) app84 3))])
|
|
|
+ (+ (let ([app85 g78])
|
|
|
+ ((vector-ref app85 0) app85 11))
|
|
|
+ (let ([app86 h79])
|
|
|
+ ((vector-ref app86 0) app86 15))))))
|
|
|
\end{lstlisting}
|
|
|
\end{minipage}
|
|
|
|
|
@@ -8392,23 +8388,24 @@ your previously created test programs.
|
|
|
\label{ch:type-dynamic}
|
|
|
\index{dynamic typing}
|
|
|
|
|
|
-In this chapter we discuss the compilation of a dynamically typed
|
|
|
-language, named $R_7$, that is a subset of the Racket
|
|
|
-language. (Recall that in the previous chapters we have studied
|
|
|
-subsets of the \emph{Typed} Racket language.) In dynamically typed
|
|
|
-languages, an expression may produce values of differing
|
|
|
-type. Consider the following example with a conditional expression
|
|
|
-that may return a Boolean or an integer depending on the input to the
|
|
|
-program.
|
|
|
+In this chapter we discuss the compilation $R_7$, a dynamically typed
|
|
|
+language and a subset of the Racket language. Recall that in the
|
|
|
+previous chapters we have compiled subsets of the \emph{Typed} Racket
|
|
|
+language. In dynamically typed languages, each evaluation of an
|
|
|
+expression may produce a value of a different type. Consider the
|
|
|
+following example with a conditional expression that may return a
|
|
|
+Boolean or an integer depending on the input to the program.
|
|
|
\begin{lstlisting}
|
|
|
(not (if (eq? (read) 1) #f 0))
|
|
|
\end{lstlisting}
|
|
|
Languages that allow expressions to produce different kinds of values
|
|
|
-are called \emph{polymorphic}. There are many kinds of polymorphism,
|
|
|
-such as subtype polymorphism and parametric
|
|
|
-polymorphism~\citep{Cardelli:1985kx}. The kind of polymorphism we are
|
|
|
-talking about here does not have a special name, but it is the usual
|
|
|
-kind that arises in dynamically typed languages.
|
|
|
+are called \emph{polymorphic}, a word composed of the Greek roots
|
|
|
+``poly'', meaning ``many'', and ``morph'', meaning ``shape''. There
|
|
|
+are several kinds of polymorphism in programming languages, such as
|
|
|
+subtype polymorphism and parametric
|
|
|
+polymorphism~\citep{Cardelli:1985kx}. The kind of polymorphism we
|
|
|
+study in this chapter does not have a special name but it is the kind
|
|
|
+that arises in dynamically typed languages.
|
|
|
|
|
|
Another characteristic of dynamically typed languages is that
|
|
|
primitive operations, such as \code{not}, are often defined to operate
|
|
@@ -8418,7 +8415,8 @@ returns \code{\#t} and given anything else it returns \code{\#f}.
|
|
|
Furthermore, even when primitive operations restrict their inputs to
|
|
|
values of a certain type, this restriction is enforced at runtime
|
|
|
instead of during compilation. For example, the following vector
|
|
|
-reference results in a run-time contract violation.
|
|
|
+reference results in a run-time contract violation because the index
|
|
|
+must be in integer, not a Boolean such as \code{\#t}.
|
|
|
\begin{lstlisting}
|
|
|
(vector-ref (vector 42) #t)
|
|
|
\end{lstlisting}
|
|
@@ -8457,64 +8455,62 @@ R_7 &::=& (\key{program} \; \Def\ldots\; \Exp)
|
|
|
The syntax of $R_7$, our subset of Racket, is defined in
|
|
|
Figure~\ref{fig:r7-syntax}.
|
|
|
%
|
|
|
-The definitional interpreter for $R_7$ is given in
|
|
|
+There is no type checker for $R_7$ because it is not a statically
|
|
|
+typed language (it's dynamically typed!).
|
|
|
+%
|
|
|
+The definitional interpreter for $R_7$ is presented in
|
|
|
Figure~\ref{fig:interp-R7}.
|
|
|
|
|
|
\begin{figure}[tbp]
|
|
|
\begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
|
|
|
-(define (get-tagged-type v) (match v [`(tagged ,v1 ,ty) ty]))
|
|
|
-
|
|
|
-(define (valid-op? op) (member op '(+ - and or not)))
|
|
|
-
|
|
|
-(define (interp-r7 env)
|
|
|
+(define (interp-R7-exp env)
|
|
|
(lambda (ast)
|
|
|
- (define recur (interp-r7 env))
|
|
|
+ (define recur (interp-R7-exp env))
|
|
|
(match ast
|
|
|
- [(? symbol?) (lookup ast env)]
|
|
|
- [(? integer?) `(inject ,ast Integer)]
|
|
|
- [#t `(inject #t Boolean)]
|
|
|
- [#f `(inject #f Boolean)]
|
|
|
- [`(read) `(inject ,(read-fixnum) Integer)]
|
|
|
- [`(lambda (,xs ...) ,body)
|
|
|
- `(inject (lambda ,xs ,body ,env) (,@(map (lambda (x) 'Any) xs) -> Any))]
|
|
|
- [`(define (,f ,xs ...) ,body)
|
|
|
- (mcons f `(lambda ,xs ,body))]
|
|
|
- [`(program ,ds ... ,body)
|
|
|
- (let ([top-level (for/list ([d ds]) ((interp-r7 '()) d))])
|
|
|
- (for/list ([b top-level])
|
|
|
- (set-mcdr! b (match (mcdr b)
|
|
|
- [`(lambda ,xs ,body)
|
|
|
- `(inject (lambda ,xs ,body ,top-level)
|
|
|
- (,@(map (lambda (x) 'Any) xs) -> Any))])))
|
|
|
- ((interp-r7 top-level) body))]
|
|
|
- [`(vector ,(app recur elts) ...)
|
|
|
- (define tys (map get-tagged-type elts))
|
|
|
- `(inject ,(apply vector elts) (Vector ,@tys))]
|
|
|
- [`(vector-set! ,(app recur v1) ,n ,(app recur v2))
|
|
|
- (match v1
|
|
|
- [`(inject ,vec ,ty)
|
|
|
- (vector-set! vec n v2)
|
|
|
- `(inject (void) Void)])]
|
|
|
- [`(vector-ref ,(app recur v) ,n)
|
|
|
- (match v [`(inject ,vec ,ty) (vector-ref vec n)])]
|
|
|
- [`(let ([,x ,(app recur v)]) ,body)
|
|
|
- ((interp-r7 (cons (cons x v) env)) body)]
|
|
|
- [`(,op ,es ...) #:when (valid-op? op)
|
|
|
- (interp-r7-op op (for/list ([e es]) (recur e)))]
|
|
|
- [`(eq? ,(app recur l) ,(app recur r))
|
|
|
- `(inject ,(equal? l r) Boolean)]
|
|
|
- [`(if ,(app recur q) ,t ,f)
|
|
|
- (match q
|
|
|
- [`(inject #f Boolean) (recur f)]
|
|
|
- [else (recur t)])]
|
|
|
- [`(,(app recur f-val) ,(app recur vs) ...)
|
|
|
- (match f-val
|
|
|
- [`(inject (lambda (,xs ...) ,body ,lam-env) ,ty)
|
|
|
- (define new-env (append (map cons xs vs) lam-env))
|
|
|
- ((interp-r7 new-env) body)]
|
|
|
- [else (error "interp-r7, expected function, not" f-val)])])))
|
|
|
-\end{lstlisting}
|
|
|
-\caption{Interpreter for the $R_7$ language. UPDATE ME -Jeremy}
|
|
|
+ [(Var x) (lookup x env)]
|
|
|
+ [(Int n) `(tagged ,n Integer)]
|
|
|
+ [(Bool b) `(tagged ,b Boolean)]
|
|
|
+ [(Prim 'read '()) `(tagged ,(read-fixnum) Integer)]
|
|
|
+ [(Lambda xs rt body)
|
|
|
+ `(tagged (lambda ,xs ,body ,env) (,@(for/list ([x xs]) 'Any) -> Any))]
|
|
|
+ [(Prim 'vector es)
|
|
|
+ `(tagged ,(apply vector (for/list ([e es]) (recur e)))
|
|
|
+ (Vector ,@(for/list ([e es]) 'Any)))]
|
|
|
+ [(Prim 'vector-set! (list e1 n e2))
|
|
|
+ (define vec (value-of-any (recur e1)))
|
|
|
+ (define i (value-of-any (recur n)))
|
|
|
+ (vector-set! vec i (recur e2))
|
|
|
+ `(tagged ,(void) Void)]
|
|
|
+ [(Prim 'vector-ref (list e1 n))
|
|
|
+ (define vec (value-of-any (recur e1)))
|
|
|
+ (define i (value-of-any (recur n)))
|
|
|
+ (vector-ref vec i)]
|
|
|
+ [(Let x e body)
|
|
|
+ (define v (recur e))
|
|
|
+ ((interp-R7-exp (cons (cons x v) env)) body)]
|
|
|
+ [(Prim 'and (list e1 e2))
|
|
|
+ (recur (If e1 e2 (Bool #f)))]
|
|
|
+ [(Prim 'or (list e1 e2))
|
|
|
+ (define v1 (recur e1))
|
|
|
+ (match (value-of-any v1) [#f (recur e2)] [else v1])]
|
|
|
+ [(Prim 'eq? (list l r))
|
|
|
+ `(tagged ,(equal? (recur l) (recur r)) Boolean)]
|
|
|
+ [(If q t f)
|
|
|
+ (match (value-of-any (recur q)) [#f (recur f)] [else (recur t)])]
|
|
|
+ [(Prim op es)
|
|
|
+ (tag-value
|
|
|
+ (apply (interp-op op) (for/list ([e es]) (value-of-any (recur e)))))]
|
|
|
+ [(Apply f es)
|
|
|
+ (define new-args (map recur es))
|
|
|
+ (let ([f-val (value-of-any (recur f))])
|
|
|
+ (match f-val
|
|
|
+ [`(lambda (,xs ...) ,body ,lam-env)
|
|
|
+ (define new-env (append (map cons xs new-args) lam-env))
|
|
|
+ ((interp-R7-exp new-env) body)]
|
|
|
+ [else (error "interp-R7-exp, expected function, not" f-val)]))]
|
|
|
+ )))
|
|
|
+\end{lstlisting}
|
|
|
+\caption{Interpreter for the $R_7$ language.}
|
|
|
\label{fig:interp-R7}
|
|
|
\end{figure}
|
|
|
|