ParentheC.ss and pc2c.ss.
<expr> ::= (exp_const <integer>)
| (exp_var <integer>)
| (exp_if <expr> <expr> <expr>)
| (exp_mult <expr> <expr>)
| (exp_sub1 <expr>)
| (exp_zero <expr>)
| (exp_letcc <expr>)
| (exp_throw <expr> <expr>)
| (exp_lambda <expr>)
| (exp_app <expr> <expr>)
This is quite simple, and identical to the other languages that we
have written interpreters for. However, we now explicitly tag all language
constructs. When we refer to a variable (using
exp_var) we refer to the variable's
lexical address.
Note: we are providing a parser that will convert normal Scheme-like syntax into the language we are using on this assignment. For example,
> (parse '((lambda (a b c) (* a c)) 5 6 7))
(exp_app
(exp_app
(exp_app
(exp_lambda
(exp_lambda
(exp_lambda (exp_mult (exp_var 2) (exp_var 0)))))
(exp_const 5))
(exp_const 6))
(exp_const 7))
(define-union exp
(const n)
(var v)
(if test conseq alt)
(mult rand1 rand2)
(sub1 rand)
(zero rand)
(letcc body)
(throw vexp kexp)
(lambda body)
(app rator rand))
(define value-of
(lambda (expr env)
(union-case expr exp
[(const n) n]
[(var v) (apply-env env v)]
[(if test conseq alt)
(if (value-of test env)
(value-of conseq env)
(value-of alt env))]
[(mult rand1 rand2) (* (value-of rand1 env) (value-of rand2 env))]
[(sub1 rand) (- (value-of rand env) 1)]
[(zero rand) (zero? (value-of rand env))]
[(letcc body)
(call/cc
(lambda (k)
(value-of body (envr_extend k env))))]
[(throw vexp kexp)
((value-of kexp env) (value-of vexp env))]
[(lambda body) (clos_closure body env)]
[(app rator rand)
(apply-proc (value-of rator env) (value-of rand env))])))
(define-union envr
(empty)
(extend arg env))
(define apply-env
(lambda (env num)
(union-case env envr
[(empty) (error 'pc "unbound variable")]
[(extend arg env)
(if (zero? num)
arg
(apply-env env (sub1 num)))])))
(define-union clos
(closure code env))
(define apply-proc
(lambda (c a)
(union-case c clos
[(closure code env)
(value-of code (envr_extend a env))])))
; Factorial of 5...should be 120.
(pretty-print
(value-of (exp_app
(exp_lambda
(exp_app
(exp_app (exp_var 0) (exp_var 0))
(exp_const 5)))
(exp_lambda
(exp_lambda
(exp_if (exp_zero (exp_var 0))
(exp_const 1)
(exp_mult (exp_var 0)
(exp_app
(exp_app (exp_var 1) (exp_var 1))
(exp_sub1 (exp_var 0))))))))
(envr_empty)))
; Test of letcc and throw...should evaluate to 24.
(pretty-print
(value-of (exp_mult (exp_const 2)
(exp_letcc
(exp_mult (exp_const 5)
(exp_throw (exp_mult (exp_const 2) (exp_const 6))
(exp_var 0)))))
(envr_empty)))
Note that the programs we pass to value-of do not have
a quote in front of them. Why is this? Because the programs are no longer
lists. We are actually passing a series of nested unions created by
calling these tagged constructors.
pretty-print
command, so you will need to use printf in your main function
to display the results of the execution.
(define name (lambda () ...)) statements
to use define-label.
main (of no arguments) that does whatever
computation you want your program to accomplish.
mount-trampoline and
dismount-trampoline.
dismount-trampoline.
pc2c.ss, generate C code for your interpreter, and
run the C program, verifying that you see the correct output.
interp.pc that contains the
exact Scheme code you used to generate your C program.
burrow.cs.indiana.edu instead of
steel.ucs.indiana.edu. If you do not have a Burrow
account, you may obtain one by filling out a request form in
LH201.