#lang plai (define-type FAE [num (n number?)] [add (lhs FAE?)(rhs FAE?)] [id (name symbol?)] [fun (param symbol?)(body FAE?)] [app (fun-expr FAE?)(arg-expr FAE?)]) (define (parse sexp) (cond ((number? sexp)(num sexp)) ((symbol? sexp)(id sexp)) ((list? sexp) (case (first sexp) ((+)(add (parse (second sexp)) (parse (third sexp)))) ((fun)(fun (caadr sexp) (parse (third sexp)))) ((with)(app (fun (caadr sexp) (parse (third sexp))) (parse (cadadr sexp)))) (else (app (parse(first sexp)) (parse (second sexp)))) )) )) (define-type FAE-Value [numV (n number?)] [closureV (param symbol?) (body FAE?) (env Env?)]) (define-type Env [mtSub] [aSub (name symbol?)(value FAE-Value?)(env Env?)]) ;; lookup:symbol Env -> FAE-Value (define (lookup name env) (type-case Env env [mtSub ()(error 'lookup "no binding for identifier")] [aSub (bound-name bound-value rest-env) (if (symbol=? bound-name name) bound-value (lookup name rest-env))])) ;; num+: numV numV -> numV (define (num+ n1 n2) (numV (+(numV-n n1)(numV-n n2)))) ;; interp: FAE Env -> FAE-Value (define (interp expr env) (type-case FAE expr [num (n)(numV n)] [add (l r)(num+ (interp l env)(interp r env))] [id (v)(lookup v env)] [fun (bound-id bound-body) (closureV bound-id bound-body env)] [app (fun-expr arg-expr) (local ([define fun-val (interp fun-expr env)]) (interp (closureV-body fun-val) (aSub (closureV-param fun-val) (interp arg-expr env) (closureV-env fun-val))))]))