Commit | Line | Data |
---|---|---|
31690700 JM |
1 | import sys, traceback |
2 | import mal_readline | |
ea81a808 JM |
3 | import mal_types as types |
4 | import reader, printer | |
5 | from env import Env | |
31690700 JM |
6 | |
7 | # read | |
8 | def READ(str): | |
ea81a808 | 9 | return reader.read_str(str) |
31690700 JM |
10 | |
11 | # eval | |
12 | def eval_ast(ast, env): | |
ea81a808 | 13 | if types._symbol_Q(ast): |
31690700 | 14 | return env.get(ast) |
ea81a808 JM |
15 | elif types._list_Q(ast): |
16 | return types._list(*map(lambda a: EVAL(a, env), ast)) | |
17 | elif types._vector_Q(ast): | |
18 | return types._vector(*map(lambda a: EVAL(a, env), ast)) | |
19 | elif types._hash_map_Q(ast): | |
31690700 JM |
20 | keyvals = [] |
21 | for k in ast.keys(): | |
22 | keyvals.append(EVAL(k, env)) | |
23 | keyvals.append(EVAL(ast[k], env)) | |
ea81a808 | 24 | return types._hash_map(*keyvals) |
31690700 JM |
25 | else: |
26 | return ast # primitive value, return unchanged | |
27 | ||
28 | def EVAL(ast, env): | |
ea81a808 JM |
29 | #print("EVAL %s" % ast) |
30 | if not types._list_Q(ast): | |
31 | return eval_ast(ast, env) | |
31690700 | 32 | |
ea81a808 JM |
33 | # apply list |
34 | if len(ast) == 0: return ast | |
35 | a0 = ast[0] | |
31690700 | 36 | |
ea81a808 JM |
37 | if "def!" == a0: |
38 | a1, a2 = ast[1], ast[2] | |
39 | res = EVAL(a2, env) | |
40 | return env.set(a1, res) | |
41 | elif "let*" == a0: | |
42 | a1, a2 = ast[1], ast[2] | |
43 | let_env = Env(env) | |
44 | for i in range(0, len(a1), 2): | |
45 | let_env.set(a1[i], EVAL(a1[i+1], let_env)) | |
46 | return EVAL(a2, let_env) | |
47 | else: | |
48 | el = eval_ast(ast, env) | |
49 | f = el[0] | |
50 | return f(*el[1:]) | |
31690700 JM |
51 | |
52 | ||
53 | def PRINT(exp): | |
ea81a808 | 54 | return printer._pr_str(exp) |
31690700 JM |
55 | |
56 | # repl | |
57 | repl_env = Env() | |
58 | def REP(str): | |
59 | return PRINT(EVAL(READ(str), repl_env)) | |
60 | def _ref(k,v): repl_env.set(k, v) | |
61 | ||
62 | _ref('+', lambda a,b: a+b) | |
63 | _ref('-', lambda a,b: a-b) | |
64 | _ref('*', lambda a,b: a*b) | |
65 | _ref('/', lambda a,b: a/b) | |
66 | ||
67 | while True: | |
68 | try: | |
69 | line = mal_readline.readline("user> ") | |
70 | if line == None: break | |
71 | if line == "": continue | |
72 | print(REP(line)) | |
ea81a808 | 73 | except reader.Blank: continue |
31690700 JM |
74 | except Exception as e: |
75 | print "".join(traceback.format_exception(*sys.exc_info())) |