996
|
1 from parser import *
|
|
2
|
|
3 class EvaluatorException(Exception):
|
|
4 pass
|
|
5
|
|
6 def eval(exp, env):
|
|
7 # symbols are names to be left unevaluated.
|
|
8 if isinstance(exp, NameExp):
|
|
9 raise EvaluatorException("unbound variable: " + exp.body)
|
|
10 if isinstance(exp, LambdaExp):
|
|
11 # no change
|
|
12 return exp
|
|
13 if isinstance(exp, ApplyExp):
|
|
14 # We're lazy, so we apply before evaluating the argument.
|
|
15 # We do of course need to evaluate the function.
|
|
16 rator = eval(exp.rator, env)
|
|
17 rand = exp.rand
|
|
18 return apply(rator, rand, env)
|
|
19 if isinstance(exp, StringExp):
|
|
20 import sys
|
|
21 sys.stdout.write(exp.line)
|
|
22 return LambdaExp('x', NameExp('x')) # i.e. the identity function
|
|
23 if isinstance(exp, SpecialExp):
|
|
24 if exp.body == '#list':
|
|
25 # list all definitions in the environment
|
|
26 import sys
|
|
27 defs = env.keys()
|
|
28 defs.sort()
|
|
29 sys.stdout.write('[' + ' '.join(defs) + ']')
|
|
30 return exp
|
|
31 raise EvaluatorException("Unknown expression type for evaluation")
|
|
32
|
|
33 def substitute(exp, name, value):
|
|
34 if isinstance(exp, StringExp):
|
|
35 return exp
|
|
36 if isinstance(exp, NameExp):
|
|
37 if exp.body == name:
|
|
38 return value
|
|
39 return exp
|
|
40 if isinstance(exp, ApplyExp):
|
|
41 return ApplyExp(substitute(exp.rator, name, value), substitute(exp.rand, name, value))
|
|
42 if isinstance(exp, SpecialExp):
|
|
43 return exp
|
|
44 if isinstance(exp, LambdaExp):
|
|
45 # lambda can shadow the name
|
|
46 if name == exp.arg:
|
|
47 return exp
|
|
48 return LambdaExp(exp.arg, substitute(exp.body, name, value))
|
|
49 print exp
|
|
50 raise EvaluatorException("Unknown expression type for substitution")
|
|
51
|
|
52 def apply(rator, rand, env):
|
|
53 # since we're lazy, rand is unevaluated, so it might be anything
|
|
54 # Rator, on the other hand ought to be a lambda or a special word
|
|
55 if isinstance(rator, LambdaExp):
|
|
56 # okay, now we actually have to do stuff
|
|
57 # first we substitute all instances of the first named parameter
|
|
58 # of the lambda with the rand.
|
|
59 body = substitute(rator.body, rator.arg, rand)
|
|
60 return eval(body, env)
|
|
61 if isinstance(rator, SpecialExp):
|
|
62 if rator.body == '#show':
|
|
63 # first evaluates the operand, then shows it, returns the result of the evaluation
|
|
64 import sys
|
|
65 rand = eval(rand, env)
|
|
66 sys.stdout.write(str(rand))
|
|
67 return rand
|
|
68 else:
|
|
69 raise EvaluatorException("Unknown special word: " + rator.body)
|
|
70 raise EvaluatorException("Trying to apply something that isn't a lambda")
|