clojure, groovy, rpython, scala: fix macro result evaluation
[jackhill/mal.git] / rpython / step2_eval.py
1 #import sys, traceback
2 import mal_readline
3 import mal_types as types
4 from mal_types import (MalSym, MalInt, MalStr,
5 _keywordu,
6 MalList, _list, MalVector, MalHashMap, MalFunc)
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)
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)
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
45 el = eval_ast(ast, env)
46 f = el.values[0]
47 if isinstance(f, MalFunc):
48 return f.apply(el.values[1:])
49 else:
50 raise Exception("%s is not callable" % f)
51
52 # print
53 def PRINT(exp):
54 return printer._pr_str(exp)
55
56 # repl
57 repl_env = {}
58 def REP(str, env):
59 return PRINT(EVAL(READ(str), env))
60
61 def plus(args):
62 a, b = args[0], args[1]
63 assert isinstance(a, MalInt)
64 assert isinstance(b, MalInt)
65 return MalInt(a.value+b.value)
66 def minus(args):
67 a, b = args[0], args[1]
68 assert isinstance(a, MalInt)
69 assert isinstance(b, MalInt)
70 return MalInt(a.value-b.value)
71 def multiply(args):
72 a, b = args[0], args[1]
73 assert isinstance(a, MalInt)
74 assert isinstance(b, MalInt)
75 return MalInt(a.value*b.value)
76 def divide(args):
77 a, b = args[0], args[1]
78 assert isinstance(a, MalInt)
79 assert isinstance(b, MalInt)
80 return MalInt(int(a.value/b.value))
81 repl_env[u'+'] = MalFunc(plus)
82 repl_env[u'-'] = MalFunc(minus)
83 repl_env[u'*'] = MalFunc(multiply)
84 repl_env[u'/'] = MalFunc(divide)
85
86 def entry_point(argv):
87 while True:
88 try:
89 line = mal_readline.readline("user> ")
90 if line == "": continue
91 print(REP(line, repl_env))
92 except EOFError as e:
93 break
94 except reader.Blank:
95 continue
96 except types.MalException as e:
97 print(u"Error: %s" % printer._pr_str(e.object, False))
98 except Exception as e:
99 print("Error: %s" % e)
100 #print("".join(traceback.format_exception(*sys.exc_info())))
101 return 0
102
103 # _____ Define and setup target ___
104 def target(*args):
105 return entry_point
106
107 # Just run entry_point if not RPython compilation
108 import sys
109 if not sys.argv[0].endswith('rpython'):
110 entry_point(sys.argv)