Jeremy Siek 3 роки тому
батько
коміт
a846f4f063
1 змінених файлів з 70 додано та 47 видалено
  1. 70 47
      book.tex

+ 70 - 47
book.tex

@@ -22,7 +22,7 @@
 
 \def\racketEd{0}
 \def\pythonEd{1}
-\def\edition{0}
+\def\edition{1}
 
 % material that is specific to the Racket edition of the book
 \newcommand{\racket}[1]{{\if\edition\racketEd{#1}\fi}}
@@ -1850,26 +1850,21 @@ the cases. The following code sketches this idea. (We explain the
 {\if\edition\pythonEd
 \begin{minipage}{0.45\textwidth}
 \begin{lstlisting}
-def interp_Lint(e):
+def interp_Lint(e, env):
   match e:
     case UnaryOp(USub(), e1):
-       return - interp_Lint(e1)
+       return - interp_Lint(e1, env)
     ...
 \end{lstlisting}
 \end{minipage}
 \begin{minipage}{0.45\textwidth}
 \begin{lstlisting}
-def interp_Lvar(e):
+def interp_Lvar(e, env):
   match e:
-    case IfExp(cnd, thn, els):
-      match interp_Lvar(cnd):
-        case True:
-          return interp_Lvar(thn)
-        case False:
-          return interp_Lvar(els)
-    ...
+    case Name(id):
+      return env[id]
     case _:
-      return interp_Lint(e)
+      return interp_Lint(e, env)
 \end{lstlisting}
 \end{minipage}
 \fi}
@@ -1920,6 +1915,7 @@ inherits from the class for \LangInt{} and the method
 \LangVar{} inherits from \LangInt{}, that dispatches to the
 \code{interp\_exp} in \LangInt{}.
 \begin{center}
+  \hspace{-20pt}
 {\if\edition\racketEd  
 \begin{minipage}{0.45\textwidth}
 \begin{lstlisting}
@@ -1945,7 +1941,8 @@ inherits from the class for \LangInt{} and the method
          (define v ((interp_exp env) e))
          (define env^ (dict-set env x v))
          ((interp_exp env^) body)]
-        [else (super (interp_exp env) e)]))
+        [else
+         (super (interp_exp env) e)]))
     ...
   ))
 \end{lstlisting}
@@ -1965,16 +1962,11 @@ class InterpLint:
 \end{minipage}
 \begin{minipage}{0.45\textwidth}
   \begin{lstlisting}
-def InterpLvar(InterpRVar):
+def InterpLvar(InterpLint):
   def interp_exp(e):
     match e:
-      case IfExp(cnd, thn, els):
-        match self.interp_exp(cnd):
-          case True:
-            return self.interp_exp(thn)
-          case False:
-            return self.interp_exp(els)
-      ...
+      case Name(id):
+        return env[id]
       case _:
         return super().interp_exp(e)
   ...
@@ -1985,7 +1977,7 @@ def InterpLvar(InterpRVar):
 Getting back to the troublesome example, repeated here:
 {\if\edition\racketEd  
 \begin{lstlisting}
-(define e0 (Let 'y (Int 10) (Prim '- (Var 'y))))
+(Let 'y (Int 10) (Prim '- (Var 'y)))
 \end{lstlisting}
 \fi}
 {\if\edition\pythonEd
@@ -2059,24 +2051,22 @@ extensible way.
 \fi}
 
 Having justified the use of classes and methods to implement
-interpreters, we turn to the definitional interpreter for \LangVar{}
-in Figure~\ref{fig:interp-Lvar}. It is similar to the interpreter for
-\LangInt{} but adds two new \key{match} cases for variables and
-\racket{\key{let}}\python{assignment}. For
+interpreters, we revisit the definitional interpreter for \LangInt{}
+in Figure~\ref{fig:interp-Lint-class} and then extend it to create an
+interpreter for \LangVar{} in Figure~\ref{fig:interp-Lvar}.  The
+interpreter for \LangVar{} adds two new \key{match} cases for
+variables and \racket{\key{let}}\python{assignment}. For
 \racket{\key{let}}\python{assignment} we need a way to communicate the
 value bound to a variable to all the uses of the variable. To
-accomplish this, we maintain a mapping from variables to
-values. Throughout the compiler we often need to map variables to
-information about them. We refer to these mappings as
-\emph{environments}\index{subject}{environment}.\footnote{Another
-common term for environment in the compiler literature is \emph{symbol
-table}\index{subject}{symbol table}.}
+accomplish this, we maintain a mapping from variables to values,
+called an \emph{environment}\index{subject}{environment}.
 %
 We use%
 %
 \racket{an association list (alist)}
 %
 \python{a Python \href{https://docs.python.org/3.10/library/stdtypes.html\#mapping-types-dict}{dictionary}}
+%
 to represent the environment.
 %
 \racket{Figure~\ref{fig:alist} gives a brief introduction to alists
@@ -2098,7 +2088,7 @@ variable, it looks up the corresponding value in the dictionary.
 \begin{figure}[tp]
 {\if\edition\racketEd
 \begin{lstlisting}
-(define interp_Lvar_class
+(define interp_Lint_class
   (class object%
     (super-new)
     
@@ -2111,32 +2101,23 @@ variable, it looks up the corresponding value in the dictionary.
                [else (error 'interp_exp "expected an integer" r)])]
         [(Prim '- (list e)) (fx- 0 ((interp_exp env) e))]
         [(Prim '+ (list e1 e2))
-         (fx+ ((interp_exp env) e1) ((interp_exp env) e2))]
-        [(Var x) (dict-ref env x)]
-        [(Let x e body)
-         (define new-env (dict-set env x ((interp_exp env) e)))
-         ((interp_exp new-env) body)]))
+         (fx+ ((interp_exp env) e1) ((interp_exp env) e2))]))
 
     (define/public (interp_program p)
       (match p
         [(Program '() e) ((interp_exp '()) e)]))
     ))
-
-(define (interp_Lvar p)
-  (send (new interp_Lvar_class) interp_program p))
 \end{lstlisting}
 \fi}
 {\if\edition\pythonEd
 \begin{lstlisting}
-class InterpLvar:
+class InterpLint:
   def interp_exp(self, e, env):
     match e:
       case BinOp(left, Add(), right):
         return self.interp_exp(left, env) + self.interp_exp(right, env)
       case UnaryOp(USub(), v):
         return - self.interp_exp(v, env)
-      case Name(id):
-        return env[id]
       case Constant(value):
         return value
       case Call(Name('input_int'), []):
@@ -2146,9 +2127,6 @@ class InterpLvar:
     if len(ss) == 0:
       return
     match ss[0]:
-      case Assign([lhs], value):
-        env[lhs.id] = self.interp_exp(value, env)
-        return self.interp_stmts(ss[1:], env)
       case Expr(Call(Name('print'), [arg])):
         print(self.interp_exp(arg, env), end='')
         return self.interp_stmts(ss[1:], env)
@@ -2162,6 +2140,51 @@ class InterpLvar:
         self.interp_stmts(body, {})
 \end{lstlisting}
 \fi}
+\caption{Interpreter for \LangInt{} as a class.}
+\label{fig:interp-Lint-class}
+\end{figure}
+
+\begin{figure}[tp]
+{\if\edition\racketEd
+\begin{lstlisting}
+(define interp_Lvar_class
+  (class interp_Lint_class
+    (super-new)
+    
+    (define/override ((interp_exp env) e)
+      (match e
+        [(Var x) (dict-ref env x)]
+        [(Let x e body)
+         (define new-env (dict-set env x ((interp_exp env) e)))
+          ((interp_exp new-env) body)]
+        [else ((super interp-exp env) e)]))
+    ))
+
+(define (interp_Lvar p)
+  (send (new interp_Lvar_class) interp_program p))
+\end{lstlisting}
+\fi}
+{\if\edition\pythonEd
+\begin{lstlisting}
+class InterpLvar(InterpLint):
+  def interp_exp(self, e, env):
+    match e:
+      case Name(id):
+        return env[id]
+      case _:
+        return super().interp_exp(e, env)
+
+  def interp_stmts(self, ss, env):
+    if len(ss) == 0:
+      return
+    match ss[0]:
+      case Assign([lhs], value):
+        env[lhs.id] = self.interp_exp(value, env)
+        return self.interp_stmts(ss[1:], env)
+      case _:
+        return super().interp_stmts(ss, env)
+\end{lstlisting}
+\fi}
 \caption{Interpreter for the \LangVar{} language.}
 \label{fig:interp-Lvar}
 \end{figure}