DISABLE FDs (REMOVE ME).
[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 if len(ast) == 0: return ast
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 # print
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):
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
95 except reader.Blank:
96 continue
97 except types.MalException as e:
98 print(u"Error: %s" % printer._pr_str(e.object, False))
99 except Exception as e:
100 print("Error: %s" % e)
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)