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