Mercurial > repo
comparison interps/lambda/evaluator.py @ 996:859f9b4339e6
<Gregor> tar xf egobot.tar.xz
author | HackBot |
---|---|
date | Sun, 09 Dec 2012 19:30:08 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
995:6883f5911eb7 | 996:859f9b4339e6 |
---|---|
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") |