;; The first three lines of this file were inserted by DrScheme. They record metadata ;; about the language level of this file in a form that our tools can easily process. #reader(planet plai/plai:1:3/lang/reader) (define-type FAE [num (n number?)] [add (lhs FAE?) (rhs FAE?)] [sub (lhs FAE?) (rhs FAE?)] [id (name symbol?)] [fun (param symbol?) (body FAE?)] [app (fun-expr FAE?) (arg-expr FAE?)]) (define-type FAE-Value [numV (n number?)] [closureV (param symbol?) (body FAE?) (ds DefrdSub?)]) (define-type DefrdSub [mtSub] [aSub (name symbol?) (value FAE-Value?) (rest DefrdSub?)]) ;; ---------------------------------------- ;; parse : S-expr -> FAE (define (parse sexp) (cond [(number? sexp) (num sexp)] [(symbol? sexp) (id sexp)] [(pair? sexp) (case (car sexp) [(+) (add (parse (second sexp)) (parse (third sexp)))] [(-) (sub (parse (second sexp)) (parse (third sexp)))] [(fun) (fun (first (second sexp)) (parse (third sexp)))] [else (app (parse (first sexp)) (parse (second sexp)))])])) (test (parse 3) (num 3)) (test (parse 'x) (id 'x)) (test (parse '{+ 1 2}) (add (num 1) (num 2))) (test (parse '{- 1 2}) (sub (num 1) (num 2))) (test (parse '{fun {x} x}) (fun 'x (id 'x))) (test (parse '{1 2}) (app (num 1) (num 2))) ;; ---------------------------------------- ;; interp : FAE DefrdSub -> FAE-Value (define (interp a-fae ds) (type-case FAE a-fae [num (n) (numV n)] [add (l r) (num+ (interp l ds) (interp r ds))] [sub (l r) (num- (interp l ds) (interp r ds))] [id (name) (lookup name ds)] [fun (param body-expr) (closureV param body-expr ds)] [app (fun-expr arg-expr) (local [(define fun-val (interp fun-expr ds)) (define arg-val (interp arg-expr ds))] (interp (closureV-body fun-val) (aSub (closureV-param fun-val) arg-val (closureV-ds fun-val))))])) ;; num-op : (number number -> number) -> (FAE-Value FAE-Value -> FAE-Value) (define (num-op op op-name x y) (numV (op (numV-n x) (numV-n y)))) (define (num+ x y) (num-op + '+ x y)) (define (num- x y) (num-op - '- x y)) (define (lookup name ds) (type-case DefrdSub ds [mtSub () (error 'lookup "free variable")] [aSub (sub-name num rest-ds) (if (symbol=? sub-name name) num (lookup name rest-ds))])) (test (interp (parse 10) (mtSub)) (numV 10)) (test (interp (parse '{+ 10 17}) (mtSub)) (numV 27)) (test (interp (parse '{- 10 7}) (mtSub)) (numV 3)) (test (interp (parse '{{fun {x} {+ x 12}} {+ 1 17}}) (mtSub)) (numV 30)) (test (interp (parse 'x) (aSub 'x (numV 10) (mtSub))) (numV 10)) (test (interp (parse '{{fun {x} {{fun {f} {+ {f 1} {{fun {x} {f 2}} 3}}} {fun {y} {+ x y}}}} 0}) (mtSub)) (numV 3)) (test/exn (interp (parse 'x) (mtSub)) "free variable")