Skip to content

Commit 879987b

Browse files
committed
rpython: complete the eval_ast merge, add DEBUG-EVAL
1 parent 80bc451 commit 879987b

10 files changed

+147
-244
lines changed

impls/rpython/env.py

+7-10
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,17 @@ def __init__(self, outer=None, binds=None, exprs=None):
2121
else:
2222
self.data[bind.value] = exprs[i]
2323

24-
def find(self, key):
25-
assert isinstance(key, MalSym)
26-
if key.value in self.data: return self
27-
elif self.outer: return self.outer.find(key)
28-
else: return None
29-
3024
def set(self, key, value):
3125
assert isinstance(key, MalSym)
3226
assert isinstance(value, MalType)
3327
self.data[key.value] = value
3428
return value
3529

3630
def get(self, key):
37-
assert isinstance(key, MalSym)
38-
env = self.find(key)
39-
if not env: throw_str("'" + str(key.value) + "' not found")
40-
return env.data[key.value]
31+
assert isinstance(key, str)
32+
env = self
33+
while key not in env.data:
34+
env = env.outer
35+
if env is None:
36+
return None
37+
return env.data[key]

impls/rpython/step2_eval.py

+11-17
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,14 @@ def READ(str):
1111
return reader.read_str(str)
1212

1313
# eval
14-
def eval_ast(ast, env):
14+
def EVAL(ast, env):
15+
# print("EVAL " + printer._pr_str(ast))
1516
if types._symbol_Q(ast):
1617
assert isinstance(ast, MalSym)
1718
if ast.value in env:
1819
return env[ast.value]
1920
else:
2021
raise Exception(u"'" + ast.value + u"' not found")
21-
elif types._list_Q(ast):
22-
res = []
23-
for a in ast.values:
24-
res.append(EVAL(a, env))
25-
return MalList(res)
2622
elif types._vector_Q(ast):
2723
res = []
2824
for a in ast.values:
@@ -33,20 +29,18 @@ def eval_ast(ast, env):
3329
for k in ast.dct.keys():
3430
new_dct[k] = EVAL(ast.dct[k], env)
3531
return MalHashMap(new_dct)
36-
else:
32+
elif not types._list_Q(ast):
3733
return ast # primitive value, return unchanged
38-
39-
def EVAL(ast, env):
40-
#print("EVAL %s" % printer._pr_str(ast))
41-
if not types._list_Q(ast):
42-
return eval_ast(ast, env)
43-
34+
else:
4435
# apply list
4536
if len(ast) == 0: return ast
46-
el = eval_ast(ast, env)
47-
f = el.values[0]
37+
a0 = ast[0]
38+
f = EVAL(a0, env)
39+
args = []
40+
for i in range(1, len(ast)):
41+
args.append(EVAL(ast[i], env))
4842
if isinstance(f, MalFunc):
49-
return f.apply(el.values[1:])
43+
return f.apply(args)
5044
else:
5145
raise Exception("%s is not callable" % f)
5246

@@ -55,7 +49,7 @@ def PRINT(exp):
5549
return printer._pr_str(exp)
5650

5751
# repl
58-
repl_env = {}
52+
repl_env = {}
5953
def REP(str, env):
6054
return PRINT(EVAL(READ(str), env))
6155

impls/rpython/step3_env.py

+17-22
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import mal_readline
33
import mal_types as types
44
from mal_types import (MalSym, MalInt, MalStr,
5-
_symbol, _keywordu,
5+
nil, false, _symbol, _keywordu, throw_str,
66
MalList, _list, MalVector, MalHashMap, MalFunc)
77
import reader, printer
88
from env import Env
@@ -12,15 +12,11 @@ def READ(str):
1212
return reader.read_str(str)
1313

1414
# eval
15-
def eval_ast(ast, env):
15+
def EVAL(ast, env):
16+
if env.get("DEBUG-EVAL") not in (None, nil, false):
17+
print("EVAL " + printer._pr_str(ast))
1618
if types._symbol_Q(ast):
17-
assert isinstance(ast, MalSym)
18-
return env.get(ast)
19-
elif types._list_Q(ast):
20-
res = []
21-
for a in ast.values:
22-
res.append(EVAL(a, env))
23-
return MalList(res)
19+
return env.get(ast.value) or throw_str("'" + ast.value + "' not found")
2420
elif types._vector_Q(ast):
2521
res = []
2622
for a in ast.values:
@@ -31,35 +27,34 @@ def eval_ast(ast, env):
3127
for k in ast.dct.keys():
3228
new_dct[k] = EVAL(ast.dct[k], env)
3329
return MalHashMap(new_dct)
34-
else:
30+
elif not types._list_Q(ast):
3531
return ast # primitive value, return unchanged
36-
37-
def EVAL(ast, env):
38-
#print("EVAL %s" % printer._pr_str(ast))
39-
if not types._list_Q(ast):
40-
return eval_ast(ast, env)
41-
32+
else:
4233
# apply list
4334
if len(ast) == 0: return ast
4435
a0 = ast[0]
45-
if not isinstance(a0, MalSym):
36+
if isinstance(a0, MalSym):
37+
a0sym = a0.value
38+
else:
4639
raise Exception("attempt to apply on non-symbol")
4740

48-
if u"def!" == a0.value:
41+
if u"def!" == a0sym:
4942
a1, a2 = ast[1], ast[2]
5043
res = EVAL(a2, env)
5144
return env.set(a1, res)
52-
elif u"let*" == a0.value:
45+
elif u"let*" == a0sym:
5346
a1, a2 = ast[1], ast[2]
5447
let_env = Env(env)
5548
for i in range(0, len(a1), 2):
5649
let_env.set(a1[i], EVAL(a1[i+1], let_env))
5750
return EVAL(a2, let_env)
5851
else:
59-
el = eval_ast(ast, env)
60-
f = el.values[0]
52+
f = EVAL(a0, env)
53+
args = []
54+
for i in range(1, len(ast)):
55+
args.append(EVAL(ast[i], env))
6156
if isinstance(f, MalFunc):
62-
return f.apply(el.values[1:])
57+
return f.apply(args)
6358
else:
6459
raise Exception("%s is not callable" % f)
6560

impls/rpython/step4_if_fn_do.py

+17-21
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import mal_readline
33
import mal_types as types
44
from mal_types import (MalSym, MalInt, MalStr,
5-
nil, true, false, _symbol, _keywordu,
5+
nil, true, false, _symbol, _keywordu, throw_str,
66
MalList, _list, MalVector, MalHashMap, MalFunc)
77
import reader, printer
88
from env import Env
@@ -13,15 +13,11 @@ def READ(str):
1313
return reader.read_str(str)
1414

1515
# eval
16-
def eval_ast(ast, env):
16+
def EVAL(ast, env):
17+
if env.get("DEBUG-EVAL") not in (None, nil, false):
18+
print("EVAL " + printer._pr_str(ast))
1719
if types._symbol_Q(ast):
18-
assert isinstance(ast, MalSym)
19-
return env.get(ast)
20-
elif types._list_Q(ast):
21-
res = []
22-
for a in ast.values:
23-
res.append(EVAL(a, env))
24-
return MalList(res)
20+
return env.get(ast.value) or throw_str("'" + ast.value + "' not found")
2521
elif types._vector_Q(ast):
2622
res = []
2723
for a in ast.values:
@@ -32,14 +28,9 @@ def eval_ast(ast, env):
3228
for k in ast.dct.keys():
3329
new_dct[k] = EVAL(ast.dct[k], env)
3430
return MalHashMap(new_dct)
35-
else:
31+
elif not types._list_Q(ast):
3632
return ast # primitive value, return unchanged
37-
38-
def EVAL(ast, env):
39-
#print("EVAL %s" % printer._pr_str(ast))
40-
if not types._list_Q(ast):
41-
return eval_ast(ast, env)
42-
33+
else:
4334
# apply list
4435
if len(ast) == 0: return ast
4536
a0 = ast[0]
@@ -59,8 +50,11 @@ def EVAL(ast, env):
5950
let_env.set(a1[i], EVAL(a1[i+1], let_env))
6051
return EVAL(a2, let_env)
6152
elif u"do" == a0sym:
62-
el = eval_ast(ast.rest(), env)
63-
return el.values[-1]
53+
if len(ast) == 0:
54+
return nil
55+
for i in range(1, len(ast) - 1):
56+
EVAL(ast[i], env)
57+
return EVAL(ast[-1], env)
6458
elif u"if" == a0sym:
6559
a1, a2 = ast[1], ast[2]
6660
cond = EVAL(a1, env)
@@ -73,10 +67,12 @@ def EVAL(ast, env):
7367
a1, a2 = ast[1], ast[2]
7468
return MalFunc(None, a2, env, a1, EVAL)
7569
else:
76-
el = eval_ast(ast, env)
77-
f = el.values[0]
70+
f = EVAL(a0, env)
71+
args = []
72+
for i in range(1, len(ast)):
73+
args.append(EVAL(ast[i], env))
7874
if isinstance(f, MalFunc):
79-
return f.apply(el.rest())
75+
return f.apply(args)
8076
else:
8177
raise Exception("%s is not callable" % f)
8278

impls/rpython/step5_tco.py

+16-23
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import mal_readline
33
import mal_types as types
44
from mal_types import (MalSym, MalInt, MalStr,
5-
nil, true, false, _symbol, _keywordu,
5+
nil, true, false, _symbol, _keywordu, throw_str,
66
MalList, _list, MalVector, MalHashMap, MalFunc)
77
import reader, printer
88
from env import Env
@@ -13,15 +13,12 @@ def READ(str):
1313
return reader.read_str(str)
1414

1515
# eval
16-
def eval_ast(ast, env):
16+
def EVAL(ast, env):
17+
while True:
18+
if env.get("DEBUG-EVAL") not in (None, nil, false):
19+
print("EVAL " + printer._pr_str(ast))
1720
if types._symbol_Q(ast):
18-
assert isinstance(ast, MalSym)
19-
return env.get(ast)
20-
elif types._list_Q(ast):
21-
res = []
22-
for a in ast.values:
23-
res.append(EVAL(a, env))
24-
return MalList(res)
21+
return env.get(ast.value) or throw_str("'" + ast.value + "' not found")
2522
elif types._vector_Q(ast):
2623
res = []
2724
for a in ast.values:
@@ -32,15 +29,9 @@ def eval_ast(ast, env):
3229
for k in ast.dct.keys():
3330
new_dct[k] = EVAL(ast.dct[k], env)
3431
return MalHashMap(new_dct)
35-
else:
32+
elif not types._list_Q(ast):
3633
return ast # primitive value, return unchanged
37-
38-
def EVAL(ast, env):
39-
while True:
40-
#print("EVAL %s" % printer._pr_str(ast))
41-
if not types._list_Q(ast):
42-
return eval_ast(ast, env)
43-
34+
else:
4435
# apply list
4536
if len(ast) == 0: return ast
4637
a0 = ast[0]
@@ -63,8 +54,8 @@ def EVAL(ast, env):
6354
elif u"do" == a0sym:
6455
if len(ast) == 0:
6556
return nil
66-
elif len(ast) > 1:
67-
eval_ast(ast.slice2(1, len(ast)-1), env)
57+
for i in range(1, len(ast) - 1):
58+
EVAL(ast[i], env)
6859
ast = ast[-1] # Continue loop (TCO)
6960
elif u"if" == a0sym:
7061
a1, a2 = ast[1], ast[2]
@@ -78,14 +69,16 @@ def EVAL(ast, env):
7869
a1, a2 = ast[1], ast[2]
7970
return MalFunc(None, a2, env, a1, EVAL)
8071
else:
81-
el = eval_ast(ast, env)
82-
f = el.values[0]
72+
f = EVAL(a0, env)
73+
args = []
74+
for i in range(1, len(ast)):
75+
args.append(EVAL(ast[i], env))
8376
if isinstance(f, MalFunc):
8477
if f.ast:
8578
ast = f.ast
86-
env = f.gen_env(el.rest()) # Continue loop (TCO)
79+
env = f.gen_env(args) # Continue loop (TCO)
8780
else:
88-
return f.apply(el.rest())
81+
return f.apply(args)
8982
else:
9083
raise Exception("%s is not callable" % f)
9184

impls/rpython/step6_file.py

+16-23
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import mal_readline
33
import mal_types as types
44
from mal_types import (MalSym, MalInt, MalStr,
5-
nil, true, false, _symbol, _keywordu,
5+
nil, true, false, _symbol, _keywordu, throw_str,
66
MalList, _list, MalVector, MalHashMap, MalFunc)
77
import reader, printer
88
from env import Env
@@ -13,15 +13,12 @@ def READ(str):
1313
return reader.read_str(str)
1414

1515
# eval
16-
def eval_ast(ast, env):
16+
def EVAL(ast, env):
17+
while True:
18+
if env.get("DEBUG-EVAL") not in (None, nil, false):
19+
print("EVAL " + printer._pr_str(ast))
1720
if types._symbol_Q(ast):
18-
assert isinstance(ast, MalSym)
19-
return env.get(ast)
20-
elif types._list_Q(ast):
21-
res = []
22-
for a in ast.values:
23-
res.append(EVAL(a, env))
24-
return MalList(res)
21+
return env.get(ast.value) or throw_str("'" + ast.value + "' not found")
2522
elif types._vector_Q(ast):
2623
res = []
2724
for a in ast.values:
@@ -32,15 +29,9 @@ def eval_ast(ast, env):
3229
for k in ast.dct.keys():
3330
new_dct[k] = EVAL(ast.dct[k], env)
3431
return MalHashMap(new_dct)
35-
else:
32+
elif not types._list_Q(ast):
3633
return ast # primitive value, return unchanged
37-
38-
def EVAL(ast, env):
39-
while True:
40-
#print("EVAL %s" % printer._pr_str(ast))
41-
if not types._list_Q(ast):
42-
return eval_ast(ast, env)
43-
34+
else:
4435
# apply list
4536
if len(ast) == 0: return ast
4637
a0 = ast[0]
@@ -63,8 +54,8 @@ def EVAL(ast, env):
6354
elif u"do" == a0sym:
6455
if len(ast) == 0:
6556
return nil
66-
elif len(ast) > 1:
67-
eval_ast(ast.slice2(1, len(ast)-1), env)
57+
for i in range(1, len(ast) - 1):
58+
EVAL(ast[i], env)
6859
ast = ast[-1] # Continue loop (TCO)
6960
elif u"if" == a0sym:
7061
a1, a2 = ast[1], ast[2]
@@ -78,14 +69,16 @@ def EVAL(ast, env):
7869
a1, a2 = ast[1], ast[2]
7970
return MalFunc(None, a2, env, a1, EVAL)
8071
else:
81-
el = eval_ast(ast, env)
82-
f = el.values[0]
72+
f = EVAL(a0, env)
73+
args = []
74+
for i in range(1, len(ast)):
75+
args.append(EVAL(ast[i], env))
8376
if isinstance(f, MalFunc):
8477
if f.ast:
8578
ast = f.ast
86-
env = f.gen_env(el.rest()) # Continue loop (TCO)
79+
env = f.gen_env(args) # Continue loop (TCO)
8780
else:
88-
return f.apply(el.rest())
81+
return f.apply(args)
8982
else:
9083
raise Exception("%s is not callable" % f)
9184

0 commit comments

Comments
 (0)