## EECS 395 Programming Languages: Homework 6

Due: Saturday, February 26th, 2011, noon

### Part 1 – Mutable Structs

Add struct and get forms for records as in HW3 (although we called it rec in that assignment), and also add a set form that modifies the value of a record field:

<RCFAE> = <number>
| {+ <RCFAE> <RCFAE>}
| {- <RCFAE> <RCFAE>}
| {fun {<id>} <RCFAE>}
| {<RCFAE> <RCFAE>}             ;; function application
| <id>
| {with {<id> <RCFAE>} <RCFAE>} ;; shorthand for fun & app
| {struct {<id> <RCFAE>} ...}
| {get <RCFAE> <id>}
| {set <RCFAE> <id> <RCFAE>}
| {seqn <RCFAE> <RCFAE>}

A struct form allocates a new record. A get form accesses from the record produced by the sub-expression the value of the field named by the identifier. A set form changes within the record produced by the first sub-expression the value of the field named by the identifer; the value of the second sub-expression determines the field's new value, and the origianl (now clobbered) value must be the result of the set expression.

Also extend parse and define the usual interp-expr, which takes an expression and interprets it with an empty initial deferred substitution and empty initial store, and returns either a number, 'procedure, or 'struct (without returning the store).

Your implementation must not use mutation at the PLAI level.

Examples (don't forget the tests from HW3):

(test (interp-expr (parse '{{fun {r}
{get r x}}
{struct {x 1}}}))
1)

(test (interp-expr (parse '{{fun {r}
{seqn
{set r x 5}
{get r x}}}
{struct {x 1}}}))
5)

(test (interp-expr (parse `{set {struct {x 42}} x 2}))
42)

(test (interp-expr (parse '{{{{{fun {g}
{fun {s}
{fun {r1}
{fun {r2}
{+ {get r1 b}
{seqn
{{s r1} {g r2}}
{+ {seqn
{{s r2} {g r1}}
{get r1 b}}
{get r2 b}}}}}}}}
{fun {r} {get r a}}}            ; g
{fun {r} {fun {v} {set r b v}}}} ; s
{struct {a 0} {b 2}}}             ; r1
{struct {a 3} {b 4}}}))            ; r2
5)

### Part 2 – Eliminating old bindings

If you used the same strategy we did in class for implementing the store, this program:

{with {b {struct {x 1}}}
{with {f {fun {f}
{seqn {set b x 2}
{f f}}}}
{f f}}}
will (eventually) consume all of the memory available because the store grows without bound. Adjust your implementation so that the store's size is proportional only to the number of struct expressions that were evaluated, not to the number of set operations.

;; size : any -> number
;; computes a (very rough!) approximate to
;; the size a PLAI object takes in memory
(define (size s)
(cond
[(struct? s)
(size (struct->vector s))]
[(vector? s)
(for/fold ([tot 0])
([ele (in-vector s)])
(+ tot (size ele)))]
[(pair? s)
(+ 1 (size (car s)) (size (cdr s)))]
[else 1]))
Something like this:
;; interp : RCFAE DefrdSub Store -> Value*Store
(define (interp a-rcfae ds store)
(printf "size ~s\n" (size store))
(type-case RCFAE a-rcfae
...)

### Part 3 – Errors

There are five different kinds of errors that can occur (at runtime) in this language and for each error in the input program, your interpreter must signal an error that includes one of the following phrases:

free identifier
application expected procedure
numeric operation expected number
record operation expected record
unknown field

### Part N – Handin instructions

Provide a definition of interp-expr : RCFAE -> number or 'procedure or 'struct, as above.

Provide a definition of parse : sexpression -> RCFAE, as usual (no extra n-ary functions this time, but do include withas a parser transformation)

 Last update: Wednesday, February 23rd, 2011robby@eecs.northwestern.edu