DISABLE FDs (REMOVE ME).
[jackhill/mal.git] / python / step2_eval.py
1 import sys, traceback
2 import mal_readline
3 import mal_types as types
4 import reader, printer
5
6 # read
7 def READ(str):
8 return reader.read_str(str)
9
10 # eval
11 def eval_ast(ast, env):
12 if types._symbol_Q(ast):
13 try:
14 return env[ast]
15 except:
16 raise Exception("'" + ast + "' not found")
17 elif types._list_Q(ast):
18 return types._list(*map(lambda a: EVAL(a, env), ast))
19 elif types._vector_Q(ast):
20 return types._vector(*map(lambda a: EVAL(a, env), ast))
21 elif types._hash_map_Q(ast):
22 keyvals = []
23 for k in ast.keys():
24 keyvals.append(EVAL(k, env))
25 keyvals.append(EVAL(ast[k], env))
26 return types._hash_map(*keyvals)
27 else:
28 return ast # primitive value, return unchanged
29
30 def EVAL(ast, env):
31 #print("EVAL %s" % printer._pr_str(ast))
32 if not types._list_Q(ast):
33 return eval_ast(ast, env)
34
35 # apply list
36 if len(ast) == 0: return ast
37 el = eval_ast(ast, env)
38 f = el[0]
39 return f(*el[1:])
40
41 # print
42 def PRINT(exp):
43 return printer._pr_str(exp)
44
45 # repl
46 repl_env = {}
47 def REP(str):
48 return PRINT(EVAL(READ(str), repl_env))
49
50 repl_env['+'] = lambda a,b: a+b
51 repl_env['-'] = lambda a,b: a-b
52 repl_env['*'] = lambda a,b: a*b
53 repl_env['/'] = lambda a,b: int(a/b)
54
55 # repl loop
56 while True:
57 try:
58 line = mal_readline.readline("user> ")
59 if line == None: break
60 if line == "": continue
61 print(REP(line))
62 except reader.Blank: continue
63 except Exception as e:
64 print("".join(traceback.format_exception(*sys.exc_info())))