All: *ARGV* and *host-language*. Misc syncing/fixes.
[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 el = eval_ast(ast, env)
37 f = el[0]
38 return f(*el[1:])
39
40 def PRINT(exp):
41 return printer._pr_str(exp)
42
43 # repl
44 repl_env = {}
45 def REP(str):
46 return PRINT(EVAL(READ(str), repl_env))
47
48 repl_env['+'] = lambda a,b: a+b
49 repl_env['-'] = lambda a,b: a-b
50 repl_env['*'] = lambda a,b: a*b
51 repl_env['/'] = lambda a,b: int(a/b)
52
53 # repl loop
54 while True:
55 try:
56 line = mal_readline.readline("user> ")
57 if line == None: break
58 if line == "": continue
59 print(REP(line))
60 except reader.Blank: continue
61 except Exception as e:
62 print("".join(traceback.format_exception(*sys.exc_info())))