## Operational Semantics of Lambda Calculus with Letrec

We describe evaluation rules for our lambda calculus with letrec

We need such description to make rigorous proofs about compilers, including type systems

This is a mathematical description of an interpreter for this language

It is also analogous to relations that transform configurations in

- finite state machines
- push-down machines

Configuration in this case is simply an expression of lambda calculus with letrec

- for programming languages with state, configuration would also need to include (global and local) state, and stack

We define one-step relation on configurations, here denoted

We write to denote

- meaning: one step of evaluating leads to

## Evaluation Rules for Operational Semantics

#### Evaluate Primitive Operation

Example

Depends on the set of primitive operators in the language

#### Beta Reduce

#### Letrec Base

if does not contain any of the variables

#### Letrec Unfold

#### Context Rule

Here denotes expression containing one occurrence of and results from by replacing this ocurrence of by

**Note:** sometimes we pick a particular evaluation strategy

- eager: evaluate arguments of function application before unfolding function
- outermost: pick outermost expressions to evaluate

## Example

**Example of (outermost) evaluation**:

letrec (twice:int->int) = % x.(ite (<= x 0) 0 (+ 2 (twice (- x 1)))) in (twice 1) -unfold-> letrec (twice:int->int) = % x.(ite (<= x 0) 0 (+ 2 (twice (- x 1)))) in ((% x.(ite (<= x 0) 0 (+ 2 (twice (- x 1))))) 1) -beta-> letrec (twice:int->int) = % x.(ite (<= x 0) 0 (+ 2 (twice (- x 1)))) in (ite (<= 1 0) 0 (+ 2 (twice (- 1 1)))) -primitive(<=)--> letrec (twice:int->int) = % x.(ite (<= x 0) 0 (+ 2 (twice (- x 1)))) in (ite false 0 (+ 2 (twice (- 1 1)))) -primitive(ite)--> letrec (twice:int->int) = % x.(ite (<= x 0) 0 (+ 2 (twice (- x 1)))) in (+ 2 (twice (- 1 1))) -primitive(-)--> letrec (twice:int->int) = % x.(ite (<= x 0) 0 (+ 2 (twice (- x 1)))) in (+ 2 (twice 0)) -unfold--> letrec (twice:int->int) = % x.(ite (<= x 0) 0 (+ 2 (twice (- x 1)))) in (+ 2 ((% x.(ite (<= x 0) 0 (+ 2 (twice (- x 1))))) 0)) -beta-> letrec (twice:int->int) = % x.(ite (<= x 0) 0 (+ 2 (twice (- x 1)))) in (+ 2 (ite (<= 0 0) 0 (+ 2 (twice (- 0 1))))) -primitive(<=)-> letrec (twice:int->int) = % x.(ite (<= x 0) 0 (+ 2 (twice (- x 1)))) in (+ 2 (ite true 0 (+ 2 (twice (- 0 1))))) -primitive(ite)-> letrec (twice:int->int) = % x.(ite (<= x 0) 0 (+ 2 (twice (- x 1)))) in (+ 2 0) -primitive(+)-> letrec (twice:int->int) = % x.(ite (<= x 0) 0 (+ 2 (twice (- x 1)))) in 2 -base-> 2