Lecture 2: Verified Interpreters
Teacher: François Pottier
From operational semantics to (verified) interpreter
You have different semantics and want to translate between them.
A naïve interpreter
- An interpreter:
-
executes a program.
Of course, OCaml doesn’t perform naïve step-by-step $β$-reductions, but for the sake of simplicity, we’ll study a simplified example of small-step semantic to begin with.
type var = int (* a de Bruijn index *)
type term =
| Var of var
| Lam of (* bind: *) term
| App of term * term
(* Example: *)
let id = Lam (Var 0)
Now: definition of $⇑^i (+k)$:
let rec lift_ i k (t : term) : term = match t with
| Var x -> if x < i then t else Var (x + k)
| Lam t -> Lam (lift_ (i + 1) k t)
| App (t1, t2) -> App (lift_ i k t1, lift_ i k t2)
let lift k t = lift_ 0 k t
And substitutions:
let rec subst_ i (sigma : var -> term) (t : term) : term =
match t with
| Var x -> if x < i then t else lift i (sigma (x - i))
| Lam t -> Lam (subst_ (i + 1) sigma t)
| App (t1, t2) -> App (subst_ i sigma t1, subst_ i sigma t2)
let subst sigma t = subst_ 0 sigma t
and then the substitution $u · id$:
let singleton (u : term) : var -> term = function
0 -> u
| x -> Var (x - 1)
Small-step call-by-value reduction:
let in_context f ox = match ox with
| None -> None
| Some x -> Some (f x)
let is_value = function
| Var _ | Lam _ -> true
| App _ -> false
let rec step (t : term) : term option =
match t with
| Lam _ | Var _ -> None
(* Plotkin’s BetaV *)
| App (Lam t, v) when is_value v ->
Some (subst (singleton v) t)
(* Plotkin’s AppL *)
| App (t, u) when not (is_value t) ->
in_context (fun t’ -> App (t’, u)) (step t)
(* Plotkin’s AppVR *)
| App (v, u) when is_value v ->
in_context (fun u’ -> App (v, u’)) (step u)
(* All cases covered already, but OCaml cannot see it. *)
| App (_, _) -> assert false
⟶ Very inefficient
Natural/Big-step Semantics
Reduction sequence of $t t’$ has the form:
\[t t' ⟶^\ast_{cbv} (λx.u) t' ⟶^\ast_{cbv} (λx.u) v ⟶_{cbv} u[v/x] ⟶^\ast_{cbv} v\]where $t ⟶^\ast_{cbv} λx.u$ and $t’ ⟶^\ast_{cbv} v$
Big-step relation $↓_{cbv}$
\[\cfrac{}{v \, ↓_{cbv} \, v} \qquad \cfrac{t_1 \, ↓_{cbv} \, λx.u_1 \qquad t_2 \, ↓_{cbv} \, v_2 \qquad u_1[v_2/x] ↓_{cbv} v}{t_1 t_2 \, ↓_{cbv} \, v}\]A proof of
- $t ⟶^\ast_{cbv} t’$ has linear structure
- $t ↓_{cbv} v$ has tree structure.
Big-step interpreter
exception RuntimeError
let rec eval (t : term) : term =
match t with
| Lam _ | Var _ -> t
| App (t1, t2) ->
let v1 = eval t1 in
let v2 = eval t2 in
match v1 with
| Lam u1 -> eval (subst (singleton v2) u1)
|_ -> raise RuntimeError
NB: May not terminate (evaluate $Ω$ for example)
Big-step vs. Small-step
Lemma (From Big-step to Small-step): If $t ↓{cbv} v$, then $t ⟶^\ast{cbv} v$.
Lemma (From Small-step to Big-step): If $t_1 ⟶{cbv} t_2$ and $t_2 ↓{cbv} v$, then $t_1 ↓_{cbv} v$.
Environments and closures
- Environment:
-
finite map of variables to (closed) values.
Idea: record $x$ being bounded to $v$ while evaluating a $t$. Instead of applying the substitution $[v/x]$ to the code, record the binding $x ⟼ v$ in an environment.
- Closure:
-
a pair $⟨λx.t \; \mid \; e⟩$, where $e$ is an environment and $fv(λx.t) ⊆ dom(e)$ (a closure is closed)
bigcbv
: $t ↓_{cbv} v$
ebigcbv
: $∅ ⊢ t ↓_{cbv} c$
Leave a comment