DISABLE FDs (REMOVE ME).
[jackhill/mal.git] / python / step4_if_fn_do.py
CommitLineData
31690700
JM
1import sys, traceback
2import mal_readline
ea81a808
JM
3import mal_types as types
4import reader, printer
5from env import Env
6import core
31690700
JM
7
8# read
9def READ(str):
ea81a808 10 return reader.read_str(str)
31690700
JM
11
12# eval
13def eval_ast(ast, env):
ea81a808 14 if types._symbol_Q(ast):
31690700 15 return env.get(ast)
ea81a808
JM
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):
31690700
JM
21 keyvals = []
22 for k in ast.keys():
23 keyvals.append(EVAL(k, env))
24 keyvals.append(EVAL(ast[k], env))
ea81a808 25 return types._hash_map(*keyvals)
31690700
JM
26 else:
27 return ast # primitive value, return unchanged
28
29def EVAL(ast, env):
86b689f3 30 #print("EVAL %s" % printer._pr_str(ast))
ea81a808
JM
31 if not types._list_Q(ast):
32 return eval_ast(ast, env)
31690700 33
ea81a808
JM
34 # apply list
35 if len(ast) == 0: return ast
36 a0 = ast[0]
31690700 37
ea81a808
JM
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)
31690700 62 else:
ea81a808
JM
63 el = eval_ast(ast, env)
64 f = el[0]
65 return f(*el[1:])
31690700
JM
66
67# print
68def PRINT(exp):
ea81a808 69 return printer._pr_str(exp)
31690700
JM
70
71# repl
72repl_env = Env()
73def REP(str):
74 return PRINT(EVAL(READ(str), repl_env))
31690700 75
8cb5cda4 76# core.py: defined using python
b8ee29b2 77for k, v in core.ns.items(): repl_env.set(types._symbol(k), v)
31690700 78
8cb5cda4 79# core.mal: defined using the language itself
31690700
JM
80REP("(def! not (fn* (a) (if a false true)))")
81
86b689f3 82# repl loop
31690700
JM
83while True:
84 try:
85 line = mal_readline.readline("user> ")
86 if line == None: break
87 if line == "": continue
88 print(REP(line))
ea81a808 89 except reader.Blank: continue
31690700 90 except Exception as e:
a05f7822 91 print("".join(traceback.format_exception(*sys.exc_info())))