Fix unescaping in matlab, miniMAL and rpython.
[jackhill/mal.git] / rpython / step3_env.py
CommitLineData
e6cfacb4
JM
1#import sys, traceback
2import mal_readline
3import mal_types as types
ab02c5bb
JM
4from mal_types import (MalSym, MalInt, MalStr,
5 _symbol, _keywordu,
8855a05a 6 MalList, _list, MalVector, MalHashMap, MalFunc)
e6cfacb4
JM
7import reader, printer
8from env import Env
9
10# read
11def READ(str):
12 return reader.read_str(str)
13
14# eval
15def 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)
8855a05a
JM
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)
e6cfacb4
JM
34 else:
35 return ast # primitive value, return unchanged
36
37def 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
67def PRINT(exp):
68 return printer._pr_str(exp)
69
70# repl
71repl_env = Env()
72def REP(str, env):
73 return PRINT(EVAL(READ(str), env))
74
75def 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)
80def 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)
85def 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)
90def 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))
95repl_env.set(_symbol(u'+'), MalFunc(plus))
96repl_env.set(_symbol(u'-'), MalFunc(minus))
97repl_env.set(_symbol(u'*'), MalFunc(multiply))
98repl_env.set(_symbol(u'/'), MalFunc(divide))
99
100def entry_point(argv):
e6cfacb4
JM
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
ab02c5bb
JM
108 except reader.Blank:
109 continue
110 except types.MalException as e:
111 print(u"Error: %s" % printer._pr_str(e.object, False))
e6cfacb4 112 except Exception as e:
ab02c5bb 113 print("Error: %s" % e)
e6cfacb4
JM
114 #print("".join(traceback.format_exception(*sys.exc_info())))
115 return 0
116
117# _____ Define and setup target ___
118def target(*args):
119 return entry_point
120
121# Just run entry_point if not RPython compilation
122import sys
123if not sys.argv[0].endswith('rpython'):
124 entry_point(sys.argv)