22 2 Midterm
22 2 Midterm
Instructions
Concrete syntax
[VAE]
expr ::= num | "(" expr "+" expr ")" | "(" expr "-" expr ")" | "(" expr "*" expr ")"
| "if0" "(" expr ")" "{" expr "}" "else" "{" expr "}" | "{" expr ";" expr "}"
| id | "{" "val" id "=" expr ";" expr "}"
[FAE, LFAE]
expr ::= ... | "{" id "=>" expr "}" | expr "(" expr ")"
[RFAE]
expr ::= ... | "{" "def" id "(" id ")" "=" expr ";" expr "}"
[BFAE]
expr ::= ... | "Box" "(" expr ")" | expr "." "get" | expr "." "set" "(" expr ")"
[MFAE]
expr ::= ... | "{" id "=" expr "}"
1
Abstract syntax
Each language uses only a part of the below definition, according to the concrete syntax defined above.
e ::= n | e + e | e − e | e × e | if0 e e e | e; e | x | val x = e; e
| λx.e | e e | def x(x) = e; e | ref e | !e | e := e | x = e
sealed trait Expr
case class Num(n: Int) extends Expr
case class Add(l: Expr, r: Expr) extends Expr
case class Sub(l: Expr, r: Expr) extends Expr
case class Mul(l: Expr, r: Expr) extends Expr
case class If0(c: Expr, t: Expr, f: Expr) extends Expr
case class Seq(l: Expr, r: Expr) extends Expr
case class Id(x: String) extends Expr
case class Val(x: String, e: Expr, b: Expr) extends Expr
case class Fun(x: String, b: Expr) extends Expr
case class App(f: Expr, a: Expr) extends Expr
case class Rec(f: String, x: String, b: Expr, e: Expr) extends Expr
case class NewBox(e: Expr) extends Expr
case class OpenBox(b: Expr) extends Expr
case class SetBox(b: Expr, e: Expr) extends Expr
case class Set(x: String, e: Expr) extends Expr
Values
[VAE]
v ::= n
sealed trait Value
case class NumV(n: Int) extends Value
[FAE, RFAE]
v ::= · · · | hλx.e, σi
case class CloV(x: String, b: Expr, var env: Env) extends Value
[BFAE, MFAE]
v ::= · · · | a
case class AddrV(a: Addr) extends Value
[LFAE]
v ::= · · · | (e, σ)
case class ExprV(e: Expr, env: Env) extends Value
Semantics
[VAE, FAE, RFAE] (VAE and FAE use only a part of the below rules.)
fin
σ ∈ Id →7 Val
type Env = Map[String, Value]
σ ` e1 ⇒ n1 σ ` e2 ⇒ n2 σ ` e1 ⇒ n1 σ ` e2 ⇒ n2 σ ` e1 ⇒ n1 σ ` e2 ⇒ n2
σ`n⇒n
σ ` e1 + e2 ⇒ n1 + n2 σ ` e1 − e2 ⇒ n1 − n2 σ ` e1 × e2 ⇒ n1 × n2
σ ` e1 ⇒ 0 σ ` e 2 ⇒ v2 σ ` e 1 ⇒ v1 v1 6= 0 σ ` e 3 ⇒ v3 σ ` e 1 ⇒ v1 σ ` e 2 ⇒ v2
σ ` if0 e1 e2 e3 ⇒ v2 σ ` if0 e1 e2 e3 ⇒ v3 σ ` e 1 ; e 2 ⇒ v2
x ∈ Domain(σ) σ ` e 1 ⇒ v1 σ[x 7→ v1 ] ` e2 ⇒ v2
σ ` λx.e ⇒ hλx.e, σi
σ ` x ⇒ σ(x) σ ` val x = e1 ; e2 ⇒ v2
2
[BFAE] (Showing only representative rules)
fin
σ ∈ Id →7 Val
fin
M ∈ Addr →7 Val
type Addr = Int
type Env = Map[String, Value]
type Sto = Map[Addr, Value]
σ, M ` e1 ⇒ n1 , M1 σ, M1 ` e2 ⇒ n2 , M2
σ, M ` n ⇒ n, M
σ, M ` e1 + e2 ⇒ n1 + n2 , M2
σ, M ` e1 ⇒ hλx.e, σ 0 i, M1 σ, M1 ` e2 ⇒ v2 , M2 σ 0 [x 7→ v2 ], M2 ` e ⇒ v, M3
σ, M ` e1 e2 ⇒ v, M3
σ, M ` e ⇒ v, M1 a 6∈ Domain(M1 ) σ, M ` e ⇒ a, M1 a ∈ Domain(M1 )
σ, M ` ref e ⇒ a, M1 [a 7→ v] σ, M `!e ⇒ M1 (a), M1
σ, M ` e1 ⇒ a, M1 σ, M1 ` e2 ⇒ v, M2
σ, M ` e1 := e2 ⇒ v, M2 [a 7→ v]
σ, M ` e1 ⇒ hλx.e, σ 0 i, M1
0
σ, M1 ` e2 ⇒ v , M2 a 6∈ Domain(M2 ) σ 0 [x 7→ a], M2 [a 7→ v 0 ] ` e ⇒ v, M3
σ, M ` e1 e2 ⇒ v, M3
A(n) (a) is a function that is not a value, and a(n) (b) is a function that is a value.
If a language uses (c) , the body of a function is evaluated under the environment when
the function is defined, and if it uses (d) , the body is evaluated under the environment
when the function is called. To implement (c) , a(n) (e) , which captures the
environment when the function is defined, is necessary.
3
2) (10pts) Consider a language with the following concrete syntax:
expr ::= num | "(" expr "*" expr ")" | "(" expr "^" expr ")" | "set" id "=" expr
where
• num consists of one or more numeric characters, and
• id is a nonempty string that does not contain numeric characters and white spaces.
a) (8pts) For each of the following, describe whether a given string is expr or not. You do not
need to explain the reason.
A) (2 * (3 ^ x))
B) (set x = (2 * 3))
C) (set x = (2 * 3) ^ set x = (4 * 5))
D) (2 * 3) ^ (4 * 5)
You will get 2 × max(0, (number of correct answers) − (number of wrong answers)) points. If you
do not write anything, it will be considered neither correct nor wrong.
b) (2pts) We define the abstract syntax of the language as follows:
e ::= n | e × e | eˆe | set x = e
Complete the following implementation:
sealed trait Expr
case class Num(n: Int) extends Expr
case class Mul(l: Expr, r: Expr) extends Expr
case class Exp( (A) ) extends Expr
case class Set( (B) ) extends Expr
We represent x with a string.
a) (2pts) Write every bound occurrence and its binding occurrence. (If an identifier numbered n
is a bound occurrence whose binding occurrence is an identifier numbered m, write n → m.)
b) (2pts) Write every free occurrence. (If an identifier numbered n is a free occurrence, write n.)
c) (2pts) Write every shadowing occurrence and its shadowed occurrence. (If an identifier numbered
n shadows an identifier numbered m, write n → m.)
d) (2pts) Write the result of evaluating the expression under static scope.
e) (2pts) Write the result of evaluating the expression under dynamic scope.
4
4) (10pts) Draw the evaluation derivation of each of the following FAE expressions:
a) (5pts) (λf.(f (1 + 2))) (λy.(5 − y))
b) (5pts) ((λx.(λy.(x + y))) 2) 4
5) (10pts) Rewrite each of the following BFAE expressions by replacing val and sequencing (;) with
functions and applications. Do not evaluate the expression.
a) (5pts)
{
val x = { Box(3); x.get };
(x + x)
}
b) (5pts)
{
val b = Box(5);
{ b.set((b.get + 3)); (b.get + 1) }
}
5
7) (10pts) Consider the following interp for BFAE that prints given arguments each time it is called:
What does interp(e, Map(), Map()) print for each of the following definitions of e?
6
8) (5pts) Consider the following FAE expression, which evaluates to a function:
1 {
2 val fX = { fY => {
3 val f = { n => fY(fY) };
4 { n => if0 (n) { 0 } else { (n + f((n - 1))) } }
5 }};
6 fX(fX)
7 }
Does the function compute the sum from 0 to n, where n ∈ N? If not, fix the expression (use line
numbers in your answer). If your answer is “yes,” you do not need to explain the reason.
10) (5pts) Suppose a garbage-collected interepreter uses the following kinds of record:
• Tag 1: a record containing one integer
• Tag 2: a record containing one integer and one pointer
• Tag 3: a record containing two pointers
• Tag 99: forwarding pointer (to to-space)
The interpreter has one register, which always contains a pointer, and a memory pool of size 34. The
allocator/collector is a two-space copying collector, so each space is of size 17. Records are allocated
consecutively in from-space, starting from the first memory location, 0.
The following is the snapshot of the memory just before garbage collection, where all the memory
has been allocated:
• Register: 6
• From space: 2 0 0 2 3 15 3 15 9 3 0 15 2 2 0 1 0
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
• To space: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
What are the values in the register, the from-space, and the to-space after garbage collection? Draw
your answer just like the above figure.
7
11) (5pts) Consider the following interp for LFAE that prints given arguments each time it is called:
def strict(v: Value): Value = v match {
case ExprV(e, env) => strict(interp(e, env))
case _ => v }
def interp(e: Expr, env: Env): Value = {
println(s"$e, $env")
e match {
case Num(n) => NumV(n)
case Add(l, r) => (strict(interp(l, env)), strict(interp(r, env))) match {
case (NumV(x), NumV(y)) => NumV(x + y)
case _ => error() }
case Id(x) => env.getOrElse(x, error())
case Fun(x, b) => CloV(x, b, env)
case App(f, a) => strict(interp(f, env)) match {
case CloV(x, b, fenv) => interp(b, fenv + (x -> ExprV(a, env)))
case _ => error() }}}
What does interp(e, Map()) print for the following definition of e?
App(Fun("x", App(Fun("y", Add(Id("y"), Id("y"))), Id("x"))), Num(1)), which is
{ x => { y => (y + y) }(x) }(1)
You can use any notation you prefer in your answer. If you think your notation is confusing, describe
what your notation means in the answer.
12) (15pts) This question extends BFAE with pipe (.), which feeds a value to a function.
e ::= · · · | e . e
e1 . e2 first evaluates e1 to v1 and then evaluates e2 to v2 . v2 must be a closure. v2 is applied to v1
using the usual function application semantics.
a) (3pts) Write the operational semantics of e1 . e2 of the form σ, M ` e ⇒ v, M .
b) (3pts) Complete the following interpreter implementation by filling ???.
case class Pipe(a: Expr, f: Expr) extends Expr
def interp(e: Expr, env: Env, sto: Sto): (Value, Sto) = e match {
...
case Pipe(a, f) => ??? }
c) (9pts) Complete the desugar function, which takes a BFAE expression and returns an expression
that lacks Pipe but produces the same result as the given expression, by filling ???.
def desugar(e: Expr): Expr = e match {
case Num(n) => Num(n)
case Id(x) => Id(x)
case Val(x, e, b) => Val(x, desugar(e), desugar(b))
case Fun(x, b) => Fun(x, desugar(b))
case App(f, a) => App(desugar(f), desugar(a))
case NewBox(e) => NewBox(desugar(e))
case OpenBox(b) => OpenBox(desugar(b))
case SetBox(b, e) => SetBox(desugar(b), desugar(e))
case Pipe(a, f) => ??? }
You may use the helper functions for Q6 (binding, bound, free, and fresh) in your answer.
—End of Exam—