\documentclass[11pt]{article}

\input{../latex/compilerstoolbox.sty}
\usepackage{homework}
\usepackage{tikz}
\usepackage{proof}
\setlength{\inferLineSkip}{4pt}
\usepackage{latexsym}
\usepackage{graphicx}

\def\rotatechartwo#1{\reflectbox{#1}}
\newcommand{\assdate}{Tuesday, March 19, 2024 (11:59PM)}
\newcommand{\assnum}{4}
\newcommand{\asstitle}{Memory and Dynamic Semantics}
\newcommand{\lecturer}{Jan and Co.}

\begin{document}
\maketitle

\newcommand{\production}[3]{\ensuremath{\gamma_{#1}} & : & \nonterm{#2} & $\rightarrow$ & {#3} \\}

\textbf{Reminder:} Assignments are individual assignments,
not done in pairs.  The work must be all your own.
Hand in your solutions on Gradescope.
Please read the late policy for written assignments on the course web page.

\clearpage

\hspace{0cm}

\section*{Problem 1: Memory Semantics (10 points)}

% Memory Dynamic Semantics (10 points)

Consider the code snippet below:

\begin{verbatim}
int[] x = alloc_array(int, 0);
x[0] += 1 / 0;
\end{verbatim}
%
And an elaborated abstract syntax tree of the program:
%
\begin{verbatim}
  declare(x, int[],seq (assign(x,alloc_array(int, 0)),
    asnop(x[0], plus, binop(1, div, 0)))
  )
\end{verbatim}



Provide a trace using dynamic semantics rules from lecture to determine what the
correct outcome is. If a step has side conditions (e.g. $n \ge 0$, etc.)
explicitly justify them\footnote{See the lecture notes on mutable store and
structs for the updated dynamic semantic rules, be careful about the +=
operation.}. Your trace should have exactly 10 steps.

\begin{align*}
& H; \cdot; \cdot \vdash \\ & \sdecl{\x}{\tarr\tint}{
\sseq{\sassn{x}{\sallocArray{\tint}{0}}}
    {\sasnop{\eindex{\x}{0}}{\aplus}{\binop{1}{\adiv}{0}}}
} \brhd \cdot \\
\stepsto \quad & ?; ?; ? \vdash ? \\
\stepsto \quad & \dots
\end{align*}

\clearpage

\hspace{0cm}

\section*{Problem 2: Enums (20 points)}

% Enums (20 Points)

\newcommand{\denum}[2]{\texttt{enum}~#1~\{ #2 \};}
\newcommand{\sswitch}[2]{\texttt{switch}(#1)\{ #2 \}}


Many programming languages contain enumerations or sets of named constants.
These {\sf enum} constructs appear in languages such as C, C++, and Java, among
others.\\\\
In C, enumeration types $u$ can be declared as
$$
\texttt{enum}~u;
$$
or defined as

$$
\denum{u}{v_1, \dotsc, v_n}
$$
where $v_1, \dotsc, v_n$ are distinct identifiers, and $u$ is an identifier.
Enum values are introduced by named constants $v_i$, which are now valid expressions.
Enum values can be used in ${\sf switch}$ statements, which take the form

$$
\sswitch{e}{v_1\mapsto s_1~|~\dotsc~|~v_n\mapsto s_n}
$$
Informally, a switch statement inspects the enum value that $e$ evaluates to and
branches accordingly. In the above example, if $e$ steps to the constant $v_1$,
then the statement $s_1$ will be executed. If $e$ steps to $v_2$, then $s_2$
will be executed. The pattern continues.

Below are a couple of rules that begin to describe the static
semantics of enumerations.

\[\begin{array}{ccc}
  \infer[\text{(S1)}]{\Sigma; \Gamma \proves \sswitch{e}{v_1\mapsto s_1~|~\dotsc~|~v_n\mapsto s_n} : ? }
      {?}
&\hspace{4em}&
  \infer[\text{(S2)}]{\Sigma; \Gamma \proves v : ?}{?}
\end{array}\]


The rules use an enumeration signature
$\Sigma$ that contains all defined enumerations. You can assume that
every enumeration $u$ and every element $v$ appears at most
once in the signature.

$$\Sigma ::= \cdot \mid \denum{u}{ v_1, \dotsc, v_n }, \Sigma$$

\begin{enumerate}
  \item [(a)] Complete the type rules for enumerations to maintain the type
  safety of C0. Hint: one thing that the premises for the rule S1 should check
  is that the named constants $v_1, \ldots, v_n$ are distinct and exhaustive.
  \item [(b)] Extend the dynamic semantics for expressions and statements to
  describe the evaluation of named constants and the execution of switch
  statements. You should only need two rules.
\end{enumerate}


\clearpage

\hspace{0cm}

\section*{Problem 3: Polymorphism (20 points)}

% Polymorphism (25 points)

The C0 language has very few mechanisms for polymorphic function definitions.
C provides a more expressive, but inherently unsafe, mechanism by allowing
pointers of type \texttt{void*}. A pointer of this type can reference data of
any type. The programmer uses explicit casts to convert to and from this type.
In this problem we explore a safe version of \texttt{void*} which implements
runtime tag-checking of types---which, incidentally, is the approach taken in
C0's successor C1.

\subsection*{Tagging and Untagging Data}

The key to making coercions from the \texttt{void*} type-safe is to tag pointers of
type \texttt{void*} with the contained data's type.
When the runtime encounters a cast from type \texttt{void*} to another pointer type,
the tag is checked to ensure that the cast is safe.

In the source language, we introduce new tagging and untagging constructs:
\[
\begin{array}{lcl}
e & ::= & \ldots \mid \mathtt{tag}(\tau{*}, e) \mid \mathtt{untag}(\tau{*}, e)
\end{array}
\]
with the following typing rules
\[
\begin{array}{c}
  \infer{\Gamma \vdash \mathtt{tag}(\tau{*}, e) : \mathtt{void}{*}}
	{\Gamma \vdash e : \tau{*} & \tau{*} \ne \mathtt{void}{*}}
  \hspace{3em}
  \infer{\Gamma \vdash \mathtt{untag}(\tau{*}, e) : \tau{*}}
        {\Gamma \vdash e : \mathtt{void}{*} & \tau{*} \ne \mathtt{void}{*}}
\end{array}
\]
Tagging will never cause an error: regardless of the type of a pointer value, we can always
weaken its type to \texttt{void*} and create a tag. Untagging a value (as in $\texttt{untag}(\tau{*}, v)$) should
raise a runtime error if $v$ is the result of tagging a non-null pointer with a type differing from $\tau{*}$.
For example, if $p : \mathtt{int}*$ is a non-null value, then the following is an expression
that will typecheck but whose evaluation will raise a runtime error:
\[
\mathtt{untag}(\mathtt{bool}*, \mathtt{tag}(\mathtt{int}*, p))
\]

Untagging the result of tagging a null pointer should succeed regardless of the type
the null pointer is tagged with. For example, the evaluation of this expression should
succeed:
\[
\mathtt{untag}(\mathtt{bool}*, \mathtt{tag}(\mathtt{int}*, \mathtt{NULL}))
\]

\clearpage
\hspace{0em}

\subsection*{A Safe Implementation}

In our safe implementation, a value $p$ of type $\mathtt{void}{*}$ will always
be either null (0), or a pointer to 16 bytes of memory on the heap.
The first 8 bytes on the heap are the tag for the type $\tau{*}$, and the second 8
contain a representation for $p$ (which is an address).

Assume we have a function $\mathtt{tagof}(\tau)$, which takes as argument a
type $\tau$ and returns an 8-byte tag $w$ uniquely representing $\tau$
\footnote{Formally, C0 allows for unboundedly many unique types to be
defined, but let's pretend that there is a limit of $2^{64}$.}.
The default value for type $\mathtt{void}{*}$ is null (0).

\begin{enumerate}
\item[(a)] Provide the formal dynamic semantics for $\mathtt{tag}(\tau{*}, e)$.
  Your answer should consist of one or more transition rules.
  At least one of the rules should have the form
  \[ H; S; \eta \vdash \mathtt{tag}(\tau{*}, e) \rhd K \quad \stepsto \quad ?; ?; ? \vdash ? \]
  Some of your transitions will involve allocation on the heap $H$.

\item[(b)] Provide the formal dynamic semantics for $\mathtt{untag}(\tau{*}, e)$.
  As with part (a), your answer should consist of one or more transition rules.
  At least one of the rules should have the form
  \[ H; S; \eta \vdash \mathtt{untag}(\tau{*}, e) \rhd K \quad \stepsto \quad ?; ?; ? \vdash ? \]
\end{enumerate}


\end{document}

%%% Local Variables:
%%% mode: latex
%%% TeX-master: t
%%% End:
