Selaa lähdekoodia

python chapter 1

Jeremy Siek 3 vuotta sitten
vanhempi
commit
2a3c7da61c
1 muutettua tiedostoa jossa 90 lisäystä ja 26 poistoa
  1. 90 26
      book.tex

+ 90 - 26
book.tex

@@ -23,7 +23,7 @@
 
 \def\racketEd{0}
 \def\pythonEd{1}
-\def\edition{1}
+\def\edition{0}
 
 % material that is specific to the Racket edition of the book
 \newcommand{\racket}[1]{{\if\edition\racketEd\color{olive}{#1}\fi}}
@@ -1454,73 +1454,137 @@ program that do not depend on any inputs, a process known as
 \emph{partial evaluation}~\citep{Jones:1993uq}.
 \index{subject}{partial evaluation}
 For example, given the following program
+{\if\edition\racketEd\color{olive}
 \begin{lstlisting}
 (+ (read) (- (+ 5 3)))
 \end{lstlisting}
-our compiler will translate it into the program
+\fi}
+{\if\edition\pythonEd\color{purple}
+\begin{lstlisting}
+print input_int() + -(5 + 3)    
+\end{lstlisting}
+\fi}
+\noindent our compiler translates it into the program
+{\if\edition\racketEd\color{olive}
 \begin{lstlisting}
 (+ (read) -8)
 \end{lstlisting}
+\fi}
+{\if\edition\pythonEd\color{purple}
+\begin{lstlisting}
+print input_int() + -8
+\end{lstlisting}
+\fi}
 
 Figure~\ref{fig:pe-arith} gives the code for a simple partial
 evaluator for the \LangInt{} language. The output of the partial evaluator
 is an \LangInt{} program. In Figure~\ref{fig:pe-arith}, the structural
-recursion over $\Exp$ is captured in the \code{pe-exp} function
+recursion over $\Exp$ is captured in the \code{pe\_exp} function
 whereas the code for partially evaluating the negation and addition
 operations is factored into two separate helper functions:
-\code{pe-neg} and \code{pe-add}. The input to these helper
+\code{pe\_neg} and \code{pe\_add}. The input to these helper
 functions is the output of partially evaluating the children.
+The \code{pe\_neg} and \code{pe\_add} functions check whether their
+arguments are integers and if they are, perform the appropriate
+arithmetic.  Otherwise, they create an AST node for the arithmetic
+operation.
 
 \begin{figure}[tp]
+{\if\edition\racketEd\color{olive}
 \begin{lstlisting}
-(define (pe-neg r)
+(define (pe_neg r)
   (match r
     [(Int n) (Int (fx- 0 n))]
     [else (Prim '- (list r))]))
 
-(define (pe-add r1 r2)
+(define (pe_add r1 r2)
   (match* (r1 r2)
     [((Int n1) (Int n2)) (Int (fx+ n1 n2))]
     [(_ _) (Prim '+ (list r1 r2))]))
 
-(define (pe-exp e)
+(define (pe_exp e)
   (match e
     [(Int n) (Int n)]
     [(Prim 'read '()) (Prim 'read '())]
-    [(Prim '- (list e1)) (pe-neg (pe-exp e1))]
-    [(Prim '+ (list e1 e2)) (pe-add (pe-exp e1) (pe-exp e2))]))
+    [(Prim '- (list e1)) (pe_neg (pe_exp e1))]
+    [(Prim '+ (list e1 e2)) (pe_add (pe_exp e1) (pe_exp e2))]))
 
-(define (pe-Rint p)
+(define (pe_Rint p)
   (match p
-    [(Program '() e) (Program '() (pe-exp e))]))
+    [(Program '() e) (Program '() (pe_exp e))]))
 \end{lstlisting}
+\fi}
+{\if\edition\pythonEd\color{purple}
+\begin{lstlisting}
+def pe_neg(r):
+  match r:
+    case Constant(n):
+      return Constant(-n)
+    case _:
+      return UnaryOp(USub(), r)
+  
+def pe_add(r1, r2):
+  match (r1, r2):
+    case (Constant(n1), Constant(n2)):
+      return Constant(n1 + n2)
+    case _:
+      return BinOp(r1, Add(), r2)
+
+def pe_exp(e):
+  match e:
+    case BinOp(left, Add(), right):
+      l = pe_exp(left)
+      r = pe_exp(right)
+      return pe_add(l, r)
+    case UnaryOp(USub(), v):
+      return pe_neg(pe_exp(v))
+    case Constant(value):
+      return e
+    case Call(Name('input_int'), []):
+      return e            
+
+def pe_stmt(s):
+  match s:
+    case Expr(Call(Name('print'), [arg])):
+      return Expr(Call(Name('print'), [pe_exp(arg)]))
+    case Expr(value):
+      return Expr(pe_exp(value))
+
+def pe_Pint(p):
+  match p:
+    case Module(body):
+      new_body = [pe_stmt(s) for s in body]
+      return Module(new_body)
+\end{lstlisting}
+\fi}
 \caption{A partial evaluator for \LangInt{}.}
 \label{fig:pe-arith}
 \end{figure}
 
-The \texttt{pe-neg} and \texttt{pe-add} functions check whether their
-arguments are integers and if they are, perform the appropriate
-arithmetic.  Otherwise, they create an AST node for the arithmetic
-operation.
 
 To gain some confidence that the partial evaluator is correct, we can
 test whether it produces programs that get the same result as the
 input programs. That is, we can test whether it satisfies Diagram
-\ref{eq:compile-correct}. The following code runs the partial
-evaluator on several examples and tests the output program.  The
-\texttt{parse-program} and \texttt{assert} functions are defined in
+\ref{eq:compile-correct}.
+%
+{\if\edition\racketEd\color{olive}
+The following code runs the partial evaluator on several examples and
+tests the output program.  The \texttt{parse-program} and
+\texttt{assert} functions are defined in
 Appendix~\ref{appendix:utilities}.\\
 \begin{minipage}{1.0\textwidth}
 \begin{lstlisting}
-(define (test-pe p)
-  (assert "testing pe-Rint"
-     (equal? (interp_Rint p) (interp_Rint (pe-Rint p)))))
+(define (test_pe p)
+  (assert "testing pe_Rint"
+     (equal? (interp_Rint p) (interp_Rint (pe_Rint p)))))
 
-(test-pe (parse-program `(program () (+ 10 (- (+ 5 3))))))
-(test-pe (parse-program `(program () (+ 1 (+ 3 1)))))
-(test-pe (parse-program `(program () (- (+ 3 (- 5))))))
+(test_pe (parse-program `(program () (+ 10 (- (+ 5 3))))))
+(test_pe (parse-program `(program () (+ 1 (+ 3 1)))))
+(test_pe (parse-program `(program () (- (+ 3 (- 5))))))
 \end{lstlisting}
 \end{minipage}
+\fi}
+% TODO: python version of testing the PE
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \chapter{Integers and Variables}
@@ -3007,7 +3071,7 @@ Adapt the partial evaluator from Section~\ref{sec:partial-evaluation}
 (Figure~\ref{fig:pe-arith}) so that it applies to \LangVar{} programs
 instead of \LangInt{} programs. Recall that \LangVar{} adds \key{let} binding
 and variables to the \LangInt{} language, so you will need to add cases for
-them in the \code{pe-exp} function. Once complete, add the partial
+them in the \code{pe\_exp} function. Once complete, add the partial
 evaluation pass to the front of your compiler and make sure that your
 compiler still passes all of the tests.
 \end{exercise}
@@ -3024,7 +3088,7 @@ arithmetic. For example, your partial evaluator should translate
 \code{(+ 1 (+ (read) 1))} \qquad \text{into} \qquad
 \code{(+ 2 (read))}
 \]
-To accomplish this, the \code{pe-exp} function should produce output
+To accomplish this, the \code{pe\_exp} function should produce output
 in the form of the $\itm{residual}$ non-terminal of the following
 grammar. The idea is that when processing an addition expression, we
 can always produce either 1) an integer constant, 2) an addition