%%% This is the scribe notes template for CS611
%%% There are several comments preceded by CS611: and boxed in %%%%'s
%%% which indicate where macros should be altered to set up the header
%%% for the paper.  Your Notes should go at the comment SCRIBE NOTES GO HERE!.

%%% In the various .sty files that accompany this .tex file you will
%%% find LaTeX macros that make it easier to typeset inference rules
%%% and programming language constructs.  You must make sure that the
%%% file proof.sty is in a path searched by LaTeX when you try to
%%% use this file.  Take a look to see what macros are available--it
%%% will save you time and make the notes look better.  Feel free to
%%% extend the set of macros--post them to the newsgroup and contact
%%% the course staff if you come up with some good ones so they can be
%%% added to the template.

%%% This template includes examples of how to use some of the macros
%%% to give you an idea of how they work.  (Delete the examples when
%%% you do your scribing.)

\documentclass{article}
\usepackage{611-lecture}

\newcommand\bigcdot{\mathrel{\raisebox{1pt}{$\scriptscriptstyle\bullet$}}}
\newcommand\holed[1]{[\,#1\,]}
\newcommand\hole{\holed\bigcdot}
\newcommand\context[1]{E\kern1pt\holed{#1}}
\newcommand\contextHole{\context\bigcdot}
\newcommand\goesto[2]{\underset{#2}{\overset{#1}\longrightarrow}}
\newcommand\ifthenelse[3]{\mathbf{if\ }#1\mathbf{\ then\ }#2\mathbf{\ else\ }#3}
\newcommand\letin[3]{\mathbf{let\ }#1 = #2\mathbf{\ in\ }#3}
\newcommand\letrec[5]{\mathbf{letrec\ }#1 = #2\mathbf{\ and\ \ldots\ and\ }#3 = #4\mathbf{\ in\ }#5}
\newcommand\letrecone[3]{\mathbf{letrec\ }#1 = #2\mathbf{\ in\ }#3}
\newcommand\true{\ensuremath{\mathbf{true}}}
\newcommand\false{\ensuremath{\mathbf{false}}}
\newcommand\error{\ensuremath{\mathbf{error}}}

\newcommand\LIST{\nm{LIST}}
\newcommand\HEAD{\nm{HEAD}}
\newcommand\TAIL{\nm{TAIL}}
\newcommand\NULL{\nm{NULL}}
\newcommand\EMPTY{\nm{EMPTY}}
\renewcommand\FALSE{\nm{FALSE}}
\renewcommand\TRUE{\nm{TRUE}}
\renewcommand\IF{\nm{IF}}
\newcommand\PAIR{\nm{PAIR}}
\newcommand\FIRST{\nm{FIRST}}
\newcommand\SECOND{\nm{SECOND}}
\newcommand\EQ{\nm{EQ}}
\newcommand\ERROR{\nm{ERROR}}
\newcommand\ID{\nm{ID}}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% CS611: Please fill in these macros as appropriate:
\lecture{10}                  %% Lecture number
\title{Types and Scope Rules}   %% Title of lecture
%\author{Nam Nguyen, Lukas Kroc}       %% name of scribe
\date{20 September 2006}     %% Date of lecture, e.g., 1 January 2001
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% See 611.sty for a variety of macros that will be helpful in
% typesetting the lecture. Here are a few of particular interest:
%
% "x"       x in keyword font (e.g., "if", "#t")
% _x_       x in italics
% \nm{n}    n in slanted font (used for abbreviations)
% <e>       e in angle brackets
% \lt       less-than sign
% \gt       greater-than sign
% \SB{x}    x in semantic brackets
% \Tr x{y}  x[[y]] with x in calligraphic font
%           (if x is more than a single character, use \Tr{x}{y})

\begin{document}

\maketitle

\section{Overview}

Last time we saw a new language, an extension of the $\lambda$-calculus called uML. We also saw its 
reduction rules and evaluation contexts, and began to define a translation from uML to the $\lambda$-calculus with 
call by value semantics ($\lambda$-CBV). Today, we will consider the translation of the tuple, let and letrec constructs 
of uML, relating them to the broader topics of recursion, error checking, and strong typing. Finally, we will 
introduce the topic of variable scope in the context of the lambda calculus, and define translations to $\lambda$-CBV 
for the two most common scoping rules, \emph{static} and \emph{dynamic} scoping. 

\section{Translation from uML to $\lambda$-CBV (continued)}

Let us consider the translation of tuples. We have already seen how to represent lists in the $\lambda$-calculus using the functions \LIST, \HEAD, \TAIL, \NULL, and \EMPTY\ with the following properties:
\begin{eqnarray*}
\HEAD~(\LIST~e_1~e_2) &=& e_1\\
\TAIL~(\LIST~e_1~e_2) &=& e_2\\
\EMPTY~(\LIST~e_1~e_2) &=& \FALSE\\
\EMPTY~\NULL &=& \TRUE.
\end{eqnarray*}
Using these constructs, we can define the translation from tuples to $\lambda$-CBV as follows: 
\begin{eqnarray*}
\SB{(\,)} &\definedas& \NULL\\ 
\SB{(e_1,e_2,\ldots,e_n)} &\definedas& \LIST~\SB{e_1}~\SB{(e_2,\ldots,e_n)}\\
\SB{\#n~e} &\definedas& \HEAD~(\TAIL^n~\SB e).
\end{eqnarray*}
As in the last lecture, this translation is not sound, because there are stuck uML expressions whose translations are not stuck; for example, $\#1~(\,)$.

For \textbf{let} expressions, we define 
\begin{eqnarray*}
\SB{\letin x{e_1}{e_2}} &\definedas& (\lam x{\SB{e_2}})~\SB{e_1}. 
\end{eqnarray*}

Now comes the last of our uML constructs, \textbf{letrec}:
\[
\letrec{f_1}{\lam{x_1}{e_1}}{f_n}{\lam{x_n}{e_n}}e .
\]
This construct allows us to define mutually recursive functions, each of which is able to call itself and other functions defined in the same \textbf{letrec} block.  We will consider only the case $n=1$.  Recall that, using the $Y$-combinator, we can produce a fixpoint $Y(\lam f{\lam xe})$ of $\lam f{\lam xe}$.  We can think of $Y(\lam f{\lam xe})$ as a recursively-defined function $f$ such that $f=\lam xe$, where the body $e$ can refer to $f$.  Then we define
\begin{eqnarray*}
\SB{\letrecone f{\lam x{e_1}}{e_2}} &\definedas& (\lam f{\SB{e_2}})~(Y(\lam f{\SB{\lam x{e_1}}})) .
\end{eqnarray*}

\section{Soundness of the Translation}

We have defined the translation from uML to $\lambda$-CBV.  As observed, the translation is not sound, because there are some nonsensical expressions that get stuck in the uML semantics, yet their translations converge to a $\lambda$-CBV value.

There are several ways of dealing with this issue.  One approach is to ignore it entirely.  This places the full responsibility for ensuring correct programs on the back of the programmer.  Experience has shown that this is not necessarily a good idea!  Prominent examples of languages that take this approach are C and C++. 

Another approach is to augment our translation so that an erroneous expression cannot be translated to a correct expression---that is, one that evaluates successfully at runtime. In the augmented translation, we introduce another construct called \ERROR, which signifies that there is no further valid evaluation possible. 

\subsection{Runtime Types}

Now we introduce the idea of \emph{runtime types} which take care of some incorrect translations. We keep a tag with each type of value, say 0 for Booleans, 1 for integers, 2 for tuples, and 3 for functions.  We check that we are getting the right kind of values where they are expected.  For example, we would check that we have a Boolean value for the test in a conditional if-then-else construct. 

Call the new translation $\Tr Ee$.  Define
\begin{eqnarray*}
\Tr E\true &\definedas& \PAIR~\overline 0~\TRUE\\
\Tr E\false &\definedas& \PAIR~\overline 0~\FALSE\\
\Tr En &\definedas& \PAIR~\overline 1~\overline n\\
\Tr E{(e_1,e_2,\ldots,e_n)} &\definedas& \PAIR~\overline 2~[\Tr E{e_1},\ldots,\Tr E{e_n}]\\
\Tr E{\lam xe} &\definedas& \PAIR~\overline 3~\lam x{\Tr Ee}\\
\ERROR &\definedas& \PAIR~\overline 4~\overline 0.
\end{eqnarray*}
Thus each value is paired with its runtime type.  The translation of general terms will be something like this. 
\begin{eqnarray*}
\lefteqn{\Tr E{\ifthenelse{e_0}{e_1}{e_2}}}\hspace{1cm}\\
&\definedas& (\lam x{\IF~(\EQ~(\FIRST~x)~\overline 0)~(\IF~(\SECOND~x)~(\lam z{\Tr E{e_1}})~(\lam z{\Tr E{e_2}})~\ID)~\ERROR})~\Tr E{e_0}
\end{eqnarray*}
We might have defined it more simply as
\[
{\IF~(\EQ~(\FIRST~\Tr E{e_0})~\overline 0)~(\IF~(\SECOND~\Tr E{e_0})~(\lam z{\Tr E{e_1}})~(\lam z{\Tr E{e_2}})~\ID)~\ERROR}
\]
which is functionally equivalent; but by doing it the way we did, $\Tr E{e_0}$ is only evaluated once.

We have to modify our definition of values in $\lambda$-CBV to accommodate the tags.  Under the new definition, $\ERROR$ will not be a value, but a non-value stuck expression.

The motivation behind the new construct $\ERROR$ is that if the source program should become stuck somewhere during its execution, then the translation of that program will evaluate to $\ERROR$, so that it also will be stuck.  Thus neither program will generate a value.

\subsection{Strong Typing}

Total adherence to source language semantics in the program translation, verified at compile time, runtime, or both, is called \emph{strong typing}. Both strongly typed and weakly typed languages are used modern programming. For example, ML and Scheme are strongly typed languages while C, C++ and Pascal are not. 

The translation from $e$ to $\SB e$ is \emph{compilation} and the process of reducing $\SB e$ and obtaining a value is 
\emph{execution}. Compilation, which happens once, is considered a static process, whereas execution is dynamic. 

\section{Static vs.\ Dynamic Scope}

Until now we could look at a program as written and immediately determine where any variable was bound. 
This was possible because the $\lambda$-calculus uses \emph{static scope} (also known as \emph{lexical scope}). 

In practice, the \emph{scope} of a variable is where that variable can be mentioned and used.  In static scoping, the places where a variable can be used are determined by the lexical structure of the program.  An alternative to static scoping is \emph{dynamic scoping}, in which a variable is bound to the most recent (in time) value assigned to that variable.

The difference becomes apparent when a function is applied.  In static scoping, any free variables in the function body are evaluated in the context of the defining occurrence of the function; whereas in dynamic scoping, any free variables in the function body are evaluated in the context of the function call.  The difference is illustrated by the following program:
\[
\begin{array}l
\letin d2{}\\
\hspace{1em}\letin f{\lam x{x+d}}{}\\
\hspace{2em}\letin d1{}\\
\hspace{3em}f~2
\end{array}
\]
In ML, which uses lexical scoping, the block above evaluates to 4:
\begin{enumerate}
\item The outer $d$ is bound to 2.
\item $f$ is bound to $\lam x{x+d}$.  Since $d$ is statically bound, this is will always be equivalent to $\lam x{x+2}$ (the value of $d$ cannot change, since there is no variable assignment in this language).
\item The inner $d$ is bound to 1.
\item $f~2$ is evaluated using the environment in which $f$ was defined; that is, $f$ is evaluated with $d$ bound to 2.  We get $2+2=4$. 
\end{enumerate}
If the block is evaluated using dynamic scoping, it evaluates to 3: 
\begin{enumerate}
\item The outer $d$ is bound to 2.
\item $f$ is bound to $\lam x{x+d}$.  The occurrence of $d$ in the body of $f$ is not locked to the outer declaration of $d$.
\item The inner $d$ is bound to 1.
\item $f~2$ is evaluated using the environment of the call, in which $d$ is 1.  We get $2 + 1 = 3$.
\end{enumerate}

Dynamically scoped languages are quite common, and include many interpreted scripting languages. 
Examples of languages with dynamic scoping are (in roughly chronological order): early versions of LISP, 
APL, PostScript, TeX, Perl, and Python.

Dynamic scoping does have some advantages: 
\begin{itemize}
\item Certain language features are easier to implement. 
\item It becomes possible to extend almost any piece of code by overriding the values of variables that are 
used internally by that piece. 
\end{itemize}
These advantages, however, come with a price: 
\begin{itemize}
\item Since it is impossible to determine statically what variables will be accessible at a particular point in a 
program, the compiler cannot determine where to find the correct value of a variable, necessitating a 
more expensive variable lookup mechanism. With static scoping, variable accesses can be implemented 
more efficiently, as array accesses. 
\item Implicit extensibility makes it very difficult to keep code modular: the true interface of any block of 
code becomes the entire set of variables used by that block. 
\end{itemize}

\subsection{Scope and the Interpretation of Free Variables}

Scoping rules are all about how to evaluate free variables in a program fragment.  With static scope, free variables of a function $\lam xe$ are interpreted according to the syntactic context in which the term $\lam xe$ occurs.  With dynamic scope, free variables of $\lam xe$ are interpreted according to the environment in effect when $\lam xe$ is applied.  These are not the same in general.

We can demonstrate the difference by defining two translations $\Tr{SS}{\cdot}$ and $\Tr{DS}{\cdot}$ for the two scoping rules.  Recall that an \emph{environment} is a function from variables $x$ to values.  The translations will take a $\lambda$-term $e$ and an environment $\rho$ and produce a meta-expression involving values and environments that can be evaluated under the usual rules of the $\lambda$-calculus to produce a value.  

The translation for static scoping is as follows: 
\begin{eqnarray*}
\Tr{SS} x~\rho &\definedas& \rho(x)\\
\Tr{SS}{e_1~e_2}~\rho &\definedas& {(\Tr{SS}{e_1}~\rho)~(\Tr{SS}{e_2}~\rho)}\\
\Tr{SS}{\lam xe}~\rho &\definedas& \lam v{\Tr{SS} e~\rho[v/x]},
\end{eqnarray*}
where $\rho[v/x]$ refers to the environment $\rho$ with the value of $x$ replaced by $v$:
\begin{eqnarray*}
\rho[v/x](y) &\definedas& \left\{\begin{array}{ll}
\rho(y), & y\neq x,\\
v, & y=x.
\end{array}\right.
\end{eqnarray*}

The translation for dynamic scoping is: 
\begin{eqnarray*}
\Tr{DS} x~\rho &\definedas& {\rho(x)}\\
\Tr{DS}{\lam xe}~\rho &\definedas& {\lam v{\lam\tau{\Tr{DS}e~\tau[v/x]}}}\quad\mbox{(throw out lexical environment)}\\
\Tr{DS}{e_1~e_2}~\rho &\definedas& {(\Tr{DS}{e_1}~\rho)~(\Tr{DS}{e_2}~\rho)~\rho}.
\end{eqnarray*}

That static scoping is the scoping discipline of $\lambda$-CBV is captured in the following theorem.

\medskip\noindent
\textbf{Theorem}\quad For any $\lambda$-CBV expression $e$ and environment $\rho$, $\Tr{SS}e\,\rho$ is $(\beta,\eta)$-equivalent to $\subst e{\rho(y)}{y,\ y\in\Set{Var}}$.

\textit{Proof.}
By structural induction on $e$.
\begin{eqnarray*}
\Tr{SS} x~\rho &=& \rho(x)\ \ =\ \ \subst x{\rho(y)}{y,\ y\in\Set{Var}},\\[1ex]
\Tr{SS}{e_1~e_2}~\rho &=& (\Tr{SS}{e_1}~\rho)~(\Tr{SS}{e_2}~\rho)\\
&=& (\subst{e_1}{\rho(y)}{y,\ y\in\Set{Var}})~(\subst{e_2}{\rho(y)}{y,\ y\in\Set{Var}})\\
&=& \subst{(e_1~e_2)}{\rho(y)}{y,\ y\in\Set{Var}},\\[1ex]
\Tr{SS}{\lam xe}~\rho
&=& \lam v{\Tr{SS} e~\rho[v/x]}\\
&=& \lam v{\subst e{\rho[v/x](y)}{y,\ y\in\Set{Var}}}\\
&=& \lam v{\subst{\subst e{\rho[v/x](y)}{y,\ y\in\Set{Var}-\{x\}}}{\rho[v/x](x)}x}\\
&=& \lam v{\subst{\subst e{\rho(y)}{y,\ y\in\Set{Var}-\{x\}}}vx}\\
&=_{\lefteqn{\scriptstyle\beta}}& \lam v{(\lam x{\subst e{\rho(y)}{y,\ y\in\Set{Var}-\{x\}}})~v}\\
&=_{\lefteqn{\scriptstyle\eta}}& \lam x{\subst e{\rho(y)}{y,\ y\in\Set{Var}-\{x\}}}\\
&=& \subst{(\lam xe)}{\rho(y)}{y,\ y\in\Set{Var}}.
\end{eqnarray*}
\relax\hfill$\Box$

The pairing of a function $\lam xe$ with an environment $\rho$ is called a \emph{closure}.  The theorem above says that $\Tr{SS}{\cdot}$ can be implemented by forming a closure consisting of the term $e$ and an environment $\rho$ that determines how to interpret the free variables of $e$.  By contrast, in dynamic scoping, the translated function does not record the lexical environment, so closures are not needed.

\end{document}
