Compiler Theory
Functions and Memory Cells
Functions
Syntax extension
e ::= … | λx.e | (e e) | x | y | … | xᵢ, where x, y, …, xᵢ (i ∈ ℕ).
The introduction rule for functions is λx.e.
Semantics
e → e Reductions
(λx.e) e’ → e[e’/x]
e[e’/x] = e Substitutions
———————————————————
true[e'/x] = true
and so on, for all values.
——————————————
x[e'/x] = e'
x ≠ y
—————————————
y[e'/x] = y
≠ here is syntactic difference.
For dynamic scoping, we only need one rule.
e[e'/y] = e₂
——————————————————————
(λx.e)[e'/y] = λx.e₂
For static scoping, we need two rules.
fresh x₁ e[e'/y] = e₂ e₁[e'/y] = e₂ x ≠ y
——————————————————————————————————————————————————
(λx.e)[e'/y] = λx₁.e₂
e[e'/y] = e₂ x = y
————————————————————————
(λx.e)[e'/y] = λx.e₂
Memory cells
Syntax
e ::= … | x := e | deref x | e;e
e ; e can also be modeled as begin e … e end.
Semantics
In order to write down small step operational semantics for memory cells, we need to model the heap. Thus, we add M to the rules to model the heap.
M ::= • | M,[x ↦ e]
M, e → M’, e’ Reductions
M, x := e → M,[x ↦ e], e
which means that allocations return e as a result.
M,(add1 n₁ ) + n₂ → M,n₁ + add1 n₂
and so on.
[x ↦ e] ∈ M
———————————————————
M, deref x → M, e
M, e₁ → M', e₁'
———————————————————————
M, e₁;e₂ → M', e₁';e₂
—————————————————
M, v;e₂ → M, e₂
M, e →* M, e Conversions
——————————————
M, e →* M, e
M, e → M', e' M', e' →* M'', e''
——————————————————————————————————————
M, e →* M'', e''
M, e₁ →* M', e₁' M', e₂ →* M'', e₂'
—————————————————————————————————————————
M, e₁ + e₂ →* M'', e₁' + e₂'
eval(e) = v
·, e →* M', v
———————————————
eval(e) = v