DISABLE FDs (REMOVE ME).
[jackhill/mal.git] / python / step4_if_fn_do.py
1 import sys, traceback
2 import mal_readline
3 import mal_types as types
4 import reader, printer
5 from env import Env
6 import core
7
8 # read
9 def READ(str):
10 return reader.read_str(str)
11
12 # eval
13 def eval_ast(ast, env):
14 if types._symbol_Q(ast):
15 return env.get(ast)
16 elif types._list_Q(ast):
17 return types._list(*map(lambda a: EVAL(a, env), ast))
18 elif types._vector_Q(ast):
19 return types._vector(*map(lambda a: EVAL(a, env), ast))
20 elif types._hash_map_Q(ast):
21 keyvals = []
22 for k in ast.keys():
23 keyvals.append(EVAL(k, env))
24 keyvals.append(EVAL(ast[k], env))
25 return types._hash_map(*keyvals)
26 else:
27 return ast # primitive value, return unchanged
28
29 def EVAL(ast, env):
30 #print("EVAL %s" % printer._pr_str(ast))
31 if not types._list_Q(ast):
32 return eval_ast(ast, env)
33
34 # apply list
35 if len(ast) == 0: return ast
36 a0 = ast[0]
37
38 if "def!" == a0:
39 a1, a2 = ast[1], ast[2]
40 res = EVAL(a2, env)
41 return env.set(a1, res)
42 elif "let*" == a0:
43 a1, a2 = ast[1], ast[2]
44 let_env = Env(env)
45 for i in range(0, len(a1), 2):
46 let_env.set(a1[i], EVAL(a1[i+1], let_env))
47 return EVAL(a2, let_env)
48 elif "do" == a0:
49 el = eval_ast(ast[1:], env)
50 return el[-1]
51 elif "if" == a0:
52 a1, a2 = ast[1], ast[2]
53 cond = EVAL(a1, env)
54 if cond is None or cond is False:
55 if len(ast) > 3: return EVAL(ast[3], env)
56 else: return None
57 else:
58 return EVAL(a2, env)
59 elif "fn*" == a0:
60 a1, a2 = ast[1], ast[2]
61 return types._function(EVAL, Env, a2, env, a1)
62 else:
63 el = eval_ast(ast, env)
64 f = el[0]
65 return f(*el[1:])
66
67 # print
68 def PRINT(exp):
69 return printer._pr_str(exp)
70
71 # repl
72 repl_env = Env()
73 def REP(str):
74 return PRINT(EVAL(READ(str), repl_env))
75
76 # core.py: defined using python
77 for k, v in core.ns.items(): repl_env.set(types._symbol(k), v)
78
79 # core.mal: defined using the language itself
80 REP("(def! not (fn* (a) (if a false true)))")
81
82 # repl loop
83 while True:
84 try:
85 line = mal_readline.readline("user> ")
86 if line == None: break
87 if line == "": continue
88 print(REP(line))
89 except reader.Blank: continue
90 except Exception as e:
91 print("".join(traceback.format_exception(*sys.exc_info())))