make, swift3: fix parsing empty literal sequences.
[jackhill/mal.git] / rpython / step2_eval.py
CommitLineData
2dd89a96
JM
1#import sys, traceback
2import mal_readline
3import mal_types as types
ab02c5bb
JM
4from mal_types import (MalSym, MalInt, MalStr,
5 _keywordu,
8855a05a 6 MalList, _list, MalVector, MalHashMap, MalFunc)
2dd89a96
JM
7import reader, printer
8
9# read
10def READ(str):
11 return reader.read_str(str)
12
13# eval
14def 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
39def 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# print
54def PRINT(exp):
55 return printer._pr_str(exp)
56
57# repl
58repl_env = {}
59def REP(str, env):
60 return PRINT(EVAL(READ(str), env))
61
62def 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)
67def 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)
72def 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)
77def 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))
82repl_env[u'+'] = MalFunc(plus)
83repl_env[u'-'] = MalFunc(minus)
84repl_env[u'*'] = MalFunc(multiply)
85repl_env[u'/'] = MalFunc(divide)
86
87def 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 ___
105def target(*args):
106 return entry_point
107
108# Just run entry_point if not RPython compilation
109import sys
110if not sys.argv[0].endswith('rpython'):
111 entry_point(sys.argv)