%%% 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}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% 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, 2005}     %% 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{Operational Semantics}

Let's give an example of Structural Operational Semantics of
$\lambda$-calculus-like language with pair constructs and selectors.
Expressions are defined with the following grammar:

\begin{eqnarray*}
    e &::=& n \bnf x \bnf "true" \bnf "false"
        \bnf "null"
        \bnf \lam{x_1 \ldots x_n}{e}
        \bnf e_1 \oplus e_2
        \bnf \mbox{"if" $b$ "then" $e_1$ "else" $e_2$} \bnf \\
    &&  e_0e_1\ldots e_n \bnf
        \mbox{"let" $x=e_1$ "in" $e_2$}
        \bnf (e_1, e_2)
        \bnf "\#1"~e \bnf "\#2"~e \\
\end{eqnarray*}

\noindent and values defined with\footnote{We assume that $x_1
\ldots x_n$ in $\lam{x_1 \ldots x_n}{e}$ expressions are all unique
variables}:
\begin{eqnarray*}
    v &::=& \mbox{n} \bnf "true" \bnf "false"
        \bnf "null"
        \bnf x \bnf (v_1, v_2)
        \bnf \lam{x_1 \ldots x_n}{e}
\end{eqnarray*}

We have a special syntax for functions with multiple arguments, so
in our language, $\lam{x}{\lam{y}{e}}$ is a different term than
$\lam{xy}{e}$.

For our language, we will consider the following contextual
evaluation rule:

\begin{eqnarray*}
    \frac{e \stepsone e'}{E[e]\stepsone E[e']}
    \mbox{, where}~~E & ::= &
        ([.],e) \bnf (v,[.]) \bnf [.]\oplus e
        \bnf v\oplus [.] \bnf \\
    &&  \mbox{"if" $[.]$ "then" $e_1$ "else" $e_2$}
        \bnf "\#1"~[.] \bnf "\#2"~[.] \bnf\\
    &&  v_0\ldots v_{m-1}~[.]~e_{m+1}\ldots e_n
\end{eqnarray*}

\noindent and these axioms:

\[ \Rule{}{n_1 \oplus n_2 \stepsone v}
    \sidecond{where $n_1 \otimes n_2 = v$ ($\otimes$ is an algebraic
    operation corresponding to symbol $\oplus$)}
\]
\[ \Rule{}{\mbox{"if true then" $e_1$ "else" $e_2$} \stepsone e_1} \]
\[ \Rule{}{\mbox{"if false then" $e_1$ "else" $e_2$} \stepsone e_2} \]
\[ \Rule{}{"\#1"~(v_1,v_2) \stepsone v_1} \]
\[ \Rule{}{"\#2"~(v_1,v_2) \stepsone v_2} \]
\[ \Rule{}{\mbox{"let" $x=v$ "in" $e$} \stepsone e\{v/x\}} \]
\[ \Rule{}{(\lam{x_1\ldots x_n}{e})v_1\ldots v_n \stepsone
        e\{v_1/x_1,\ldots,v_n/x_n\}} \]

Notice that with the axioms above, functions must receive the right
number of arguments to be evaluated. An alternative axiom for
application could be considered which does not impose this
requirement:
\begin{displaymath}
    \Rule{}{(\lam{x_1\ldots x_n}{e})v_1\ldots v_m \stepsone
        \lam{x_{m+1}\ldots x_n}{e}\{v_1/x_1,\ldots,v_m/x_m\}}
        \sidecond{for $n\ge m$}
\end{displaymath}


\section{Strong Types}
Let us consider these expressions:\\
\indent "if" $v$ "then" $e_0$ "else" $e_1$,
where $v$ is not "true" or "false",\\
\indent $\#1~e~or~\#2~e$, where $e$ is evaluated to a non-pair value,\\
\indent $e_1\oplus e_2$, where $e_1$ or $e_2$ are not evaluated
to a number,\\
\indent application of a non-function or of a function to a wrong
number of arguments,\\
\indent division by zero.


\medskip These expressions are call \emph{stuck expressions}
since there are no rewriting rules for them. To help identify stuck
expressions in advance, we introduce the notion of \emph{strong
typing}: values are used only in accordance with their types. Stuck
expressions violate strong typing.

\medskip There are several approaches to solve this problem. One solution
is run-time type checking. First, we augment the translation with
$e~\rightarrow~"error"$ if there is no "ordinary" rewriting rule for
$e$ and $e$ is not a value. Then, we stop the evaluation in the
target language.$$e\rightarrow^*e1~\wedge~ !\exists e2.e1
\rightarrow e_2~\Rightarrow~\SB{e}\rightarrow^*"error"$$ Here is an
example of uML with run-time type checking. We tag each value with a
number to specify its type such as 0 for error, 1 for null, 2 for
boolean, 3 for int, 4 for pair, and 5 for function which can be
represented as a pair of number of expected arguments and the
function itself. The translation becomes,
\begin{eqnarray*}
  \SB{"true"} &=& (2,"true")\\
  \SB{"null"} &=& (1,"null")\\
  \SB{(e_1,e_2)} &=& (4,(\SB{e_1},\SB{e_2}))\\
  \SB{\lam{x_1\ldots x_n}{e}} &=& (5,(n,\lam{x_1\ldots
  x_n}{\SB{e}}))\\
  \SB{"if"~e_b~ "then"~e_1~"else"~e_2} &=& "let"~x~=~\SB{e_b}~"in"\\
  & & \quad "if"~\#1x = 2~ "then"\\
  & & \quad \quad "if"~ \#2 x~ "then"~ \SB{e_1}~ "else"~\SB{e_2} \\
  & & \quad "else"~ (0,0)\\
  & & \sidecond{where $x \notin \FV{e_b~e_1~e_2}$}\\
  \SB{e_1\oplus e_2} & = & "let"~x~=~\SB{e_1}~"in"\\
  & & \quad "let"~y~=~\SB{e_2}~"in"\\
  & & \quad \quad "if"~\#1~x=3~\wedge~\#1~y=3~"then"~(3,(\#2~x)\bigoplus(\#2~y))\\
  & & \quad \quad "else"~(0,0)
\end{eqnarray*}

\medskip
One advantage of this approach is precision, because 
the translation only gets stuck when there is no rewriting
rules for a non-value term. However, this approach requires overhead
for both storage and run time.

Another approach to solve the problem of strong type is static type
checking. Static type checking will rule out all stuck programs
given some assumptions about their runtime behavior. Static type
checking is fast. However, it's conservative in the sense that it
may reject programs that will not get stuck.

\section{Scope}
{\em Scope} of an identifier (e.g. function or variable name) refers
to the part of a program in which the identifier is defined and can
be used. The two approaches discussed in the class are {\em Static}
and {\em Dynamic} scoping.

\subsection{Static Scoping}
Also called Lexical, or Block-structured scoping. In this approach,
the binding of identifiers is done based on the static (lexical)
program structure, and corresponds to a block of code. Identifiers
always refer to their nearest enclosing binding. Most compiled
languages use Static scoping.

In the following example, variable $d$ defined on line (1) has scope
that extends over lines (2),(3) and (4), but cannot be accessed
directly from line (4), because it's shadowed by variable of the
same name defined on line (3). The result of a call to the $bump$
function on line (4) using static scoping is 4.

\begin{tabular}{rl}
\hline
    (1) \quad & let $d=1$ in \\
    (2) \quad & \quad let $bump=\lam{x}{x} + d$ in \\
    (3) \quad & \quad \quad let $d=2$ in \\
    (4) \quad & \quad \quad \quad $bump~3$ \\
\hline
\end{tabular}


\subsection{Dynamic Scoping}
In dynamic scoping, identifiers have a stack of values associated
with them. Each time an identifier is (re)defined, the new binding
it pushed onto its stack, and it is popped off when the execution
leaves the context where the binding was added. Evaluating the
identifier in {\em any} context yields its top binding from the
stack. So, in the example given above, call to the $bump$ function
on line (4) returns 5 (because on line (2), the value of variable
$d$ is 2, as assign to it on line (3)).

Some programming languages (such as Perl) use dynamic scoping. An
advantage of this approach is that it is easy to change behavior of
functions by assigning different values to variables that are used
within the functions. But at the same time, this opens a great
possibility for committing errors and causing unexpected behavior.
In dynamic scoping, functions not only have "input/output ports" in
terms of its parameters, but also have "dangling wires" that also
influence their behavior in form of its free variables.

\end{document}
