Commit | Line | Data |
---|---|---|
2dd89a96 JM |
1 | #import sys, traceback |
2 | import mal_readline | |
3 | import mal_types as types | |
ab02c5bb JM |
4 | from mal_types import (MalSym, MalInt, MalStr, |
5 | _keywordu, | |
8855a05a | 6 | MalList, _list, MalVector, MalHashMap, MalFunc) |
2dd89a96 JM |
7 | import reader, printer |
8 | ||
9 | # read | |
10 | def READ(str): | |
11 | return reader.read_str(str) | |
12 | ||
13 | # eval | |
14 | def eval_ast(ast, env): | |
15 | if types._symbol_Q(ast): | |
16 | assert isinstance(ast, MalSym) | |
17 | if ast.value in env: | |
18 | return env[ast.value] | |
19 | else: | |
20 | raise Exception(u"'" + ast.value + u"' not found") | |
21 | elif types._list_Q(ast): | |
22 | res = [] | |
23 | for a in ast.values: | |
24 | res.append(EVAL(a, env)) | |
25 | return MalList(res) | |
8855a05a JM |
26 | elif types._vector_Q(ast): |
27 | res = [] | |
28 | for a in ast.values: | |
29 | res.append(EVAL(a, env)) | |
30 | return MalVector(res) | |
31 | elif types._hash_map_Q(ast): | |
32 | new_dct = {} | |
33 | for k in ast.dct.keys(): | |
34 | new_dct[k] = EVAL(ast.dct[k], env) | |
35 | return MalHashMap(new_dct) | |
2dd89a96 JM |
36 | else: |
37 | return ast # primitive value, return unchanged | |
38 | ||
39 | def EVAL(ast, env): | |
40 | #print("EVAL %s" % printer._pr_str(ast)) | |
41 | if not types._list_Q(ast): | |
42 | return eval_ast(ast, env) | |
43 | ||
44 | # apply list | |
efa2daef | 45 | if len(ast) == 0: return ast |
2dd89a96 JM |
46 | el = eval_ast(ast, env) |
47 | f = el.values[0] | |
48 | if isinstance(f, MalFunc): | |
49 | return f.apply(el.values[1:]) | |
50 | else: | |
51 | raise Exception("%s is not callable" % f) | |
52 | ||
53 | ||
54 | def PRINT(exp): | |
55 | return printer._pr_str(exp) | |
56 | ||
57 | # repl | |
58 | repl_env = {} | |
59 | def REP(str, env): | |
60 | return PRINT(EVAL(READ(str), env)) | |
61 | ||
62 | def plus(args): | |
63 | a, b = args[0], args[1] | |
64 | assert isinstance(a, MalInt) | |
65 | assert isinstance(b, MalInt) | |
66 | return MalInt(a.value+b.value) | |
67 | def minus(args): | |
68 | a, b = args[0], args[1] | |
69 | assert isinstance(a, MalInt) | |
70 | assert isinstance(b, MalInt) | |
71 | return MalInt(a.value-b.value) | |
72 | def multiply(args): | |
73 | a, b = args[0], args[1] | |
74 | assert isinstance(a, MalInt) | |
75 | assert isinstance(b, MalInt) | |
76 | return MalInt(a.value*b.value) | |
77 | def divide(args): | |
78 | a, b = args[0], args[1] | |
79 | assert isinstance(a, MalInt) | |
80 | assert isinstance(b, MalInt) | |
81 | return MalInt(int(a.value/b.value)) | |
82 | repl_env[u'+'] = MalFunc(plus) | |
83 | repl_env[u'-'] = MalFunc(minus) | |
84 | repl_env[u'*'] = MalFunc(multiply) | |
85 | repl_env[u'/'] = MalFunc(divide) | |
86 | ||
87 | def entry_point(argv): | |
2dd89a96 JM |
88 | while True: |
89 | try: | |
90 | line = mal_readline.readline("user> ") | |
91 | if line == "": continue | |
92 | print(REP(line, repl_env)) | |
93 | except EOFError as e: | |
94 | break | |
ab02c5bb JM |
95 | except reader.Blank: |
96 | continue | |
97 | except types.MalException as e: | |
98 | print(u"Error: %s" % printer._pr_str(e.object, False)) | |
2dd89a96 | 99 | except Exception as e: |
ab02c5bb | 100 | print("Error: %s" % e) |
2dd89a96 JM |
101 | #print("".join(traceback.format_exception(*sys.exc_info()))) |
102 | return 0 | |
103 | ||
104 | # _____ Define and setup target ___ | |
105 | def target(*args): | |
106 | return entry_point | |
107 | ||
108 | # Just run entry_point if not RPython compilation | |
109 | import sys | |
110 | if not sys.argv[0].endswith('rpython'): | |
111 | entry_point(sys.argv) |