Boxes
@PL on
We are defining BFAE
, arithmetic expressions with boxes that encloses a value.
BFAE
adds box features to the language.
enum Expr: prevExpr {
// includes all the former definition
case Seqn(Expr, Expr) //box
case NewBox(Expr)
case OpenBox(Expr)
case SetBox(Expr, Expr)
}
We also need a new type of value BoxV
for boxes.
enum Value: oldValue {
case BoxV(Addr) //box
}
We are using Sto
in order to manage the storage that the boxes use. Each box holds an address where the value is stored.
typealias Sto = [Addr : Value]
typealias Addr = Int
This is a simple, and very stupid version of memory allocation.
func malloc(_ sto: Sto) -> Addr {
if let maxVal = sto.max(by: { a, b in a.key < b.key }) {
return maxVal.key
}
return 0
}
Interpretation implementation.
func interp(_ e: Expr, _ env: Env, _ sto: Sto) -> (Value, Sto)
{
switch e {
case .Num(let n):
return (.NumV(n), sto)
case .Add(let l, let r):
let (v1, s1) = interp(l, env, sto)
let (v2, s2) = interp(r, env, s1)
return (NumVOperation(ADD, v1, v2), s2)
case .Sub(let l, let r):
let (v1, s1) = interp(l, env, sto)
let (v2, s2) = interp(r, env, s1)
return (NumVOperation(SUB, v1, v2), s2)
case .Val(let x, let i, let b):
let (v, s) = interp(i, env, sto)
return interp(b, env + [x : v], s)
case .Id(let x):
return (env[x]!, sto)
case .Fun(let x, let b):
return (.CloV(x, b, env), sto)
case .App(let f, let a):
let (v, s) = interp(f, env, sto)
switch v {
case .CloV(let x, let b, let fenv):
let (va, sa) = interp(a, env, s)
return interp(b, fenv + [x : va], sa)
default:
exit(1)
}
case .Seqn(let l, let r):
let (_, s1) = interp(l, env, sto)
return interp(r, env, s1)
case .NewBox(let e):
let (v, s) = interp(e, env, sto)
let addr = malloc(sto)
return (.BoxV(addr), s + [addr : v])
case .OpenBox(let e):
let (v, s) = interp(e, env, sto)
switch v {
case .BoxV(let addr):
return (s[addr]!, s)
default:
exit(1)
}
case .SetBox(let b, let e):
let (v, s) = interp(b, env, sto)
switch v {
case .BoxV(let addr):
let (ve, se) = interp(e, env, s)
return (ve, se + [addr : ve])
default:
exit(0)
}
}
}
func INTERP(_ e: Expr) -> Value {
let (v, _) = interp(e, Env(), Sto())
return v
}
print(INTERP(
.Val("b", .NewBox(.Num(10)), .OpenBox(.Seqn(.SetBox(.Id("b"), .Num(3)), .Id("b"))))
)) //NumV(3)
All the materials are from CS320 class held on 2021 spring, KAIST.