RPython: step8 basics.
[jackhill/mal.git] / rpython / core.py
1 import copy, time
2
3 import mal_types as types
4 from mal_types import (MalType, nil, true, false,
5 MalInt, MalStr, MalList)
6 import mal_readline
7 import reader
8 import printer
9
10 # General functions
11 def do_equal(args):
12 if types._equal_Q(args[0], args[1]): return true
13 else: return false
14
15 ## Errors/Exceptions
16 #def throw(exc): raise Exception(exc)
17
18
19 # String functions
20 def pr_str(args):
21 parts = []
22 for exp in args.values: parts.append(printer._pr_str(exp, True))
23 return MalStr(u" ".join(parts))
24
25 def do_str(args):
26 parts = []
27 for exp in args.values: parts.append(printer._pr_str(exp, False))
28 return MalStr(u"".join(parts))
29
30 def prn(args):
31 parts = []
32 for exp in args.values: parts.append(printer._pr_str(exp, True))
33 print(u" ".join(parts))
34 return nil
35
36 def println(args):
37 parts = []
38 for exp in args.values: parts.append(printer._pr_str(exp, False))
39 print(u" ".join(parts))
40 return nil
41
42 def read_str(args):
43 a0 = args[0]
44 assert isinstance(a0, MalStr)
45 return reader.read_str(str(a0.value))
46
47 def slurp(args):
48 a0 = args[0]
49 assert isinstance(a0, MalStr)
50 return MalStr(unicode(open(str(a0.value)).read()))
51
52 # Number functions
53 def lt(args):
54 a, b = args[0], args[1]
55 assert isinstance(a, MalInt)
56 assert isinstance(b, MalInt)
57 if a.value < b.value: return true
58 else: return false
59 def lte(args):
60 a, b = args[0], args[1]
61 assert isinstance(a, MalInt)
62 assert isinstance(b, MalInt)
63 if a.value <= b.value: return true
64 else: return false
65 def gt(args):
66 a, b = args[0], args[1]
67 assert isinstance(a, MalInt)
68 assert isinstance(b, MalInt)
69 if a.value > b.value: return true
70 else: return false
71 def gte(args):
72 a, b = args[0], args[1]
73 assert isinstance(a, MalInt)
74 assert isinstance(b, MalInt)
75 if a.value >= b.value: return true
76 else: return false
77
78 def plus(args):
79 a, b = args[0], args[1]
80 assert isinstance(a, MalInt)
81 assert isinstance(b, MalInt)
82 return MalInt(a.value+b.value)
83 def minus(args):
84 a, b = args[0], args[1]
85 assert isinstance(a, MalInt)
86 assert isinstance(b, MalInt)
87 return MalInt(a.value-b.value)
88 def multiply(args):
89 a, b = args[0], args[1]
90 assert isinstance(a, MalInt)
91 assert isinstance(b, MalInt)
92 return MalInt(a.value*b.value)
93 def divide(args):
94 a, b = args[0], args[1]
95 assert isinstance(a, MalInt)
96 assert isinstance(b, MalInt)
97 return MalInt(int(a.value/b.value))
98
99
100 ## Hash map functions
101 #def assoc(src_hm, *key_vals):
102 # hm = copy.copy(src_hm)
103 # for i in range(0,len(key_vals),2): hm[key_vals[i]] = key_vals[i+1]
104 # return hm
105 #
106 #def dissoc(src_hm, *keys):
107 # hm = copy.copy(src_hm)
108 # for key in keys:
109 # if key in hm: del hm[key]
110 # return hm
111 #
112 #def get(hm, key):
113 # if hm and key in hm:
114 # return hm[key]
115 # else:
116 # return None
117 #
118 #def contains_Q(hm, key): return key in hm
119 #
120 #def keys(hm): return types._list(*hm.keys())
121 #
122 #def vals(hm): return types._list(*hm.values())
123 #
124
125 # Sequence functions
126 def do_list(ml):
127 assert isinstance(ml, MalList)
128 return ml
129
130 def list_Q(args):
131 if isinstance(args[0], MalList): return true
132 else: return false
133
134 def empty_Q(args):
135 assert isinstance(args, MalType)
136 seq = args[0]
137 if isinstance(seq, MalList):
138 if len(seq) == 0: return true
139 else: return false
140 elif seq is nil:
141 return true
142 else:
143 raise Exception("empty? called on non-sequence")
144
145 def count(args):
146 assert isinstance(args, MalType)
147 seq = args[0]
148 if isinstance(seq, MalList):
149 return MalInt(len(seq))
150 elif seq is nil:
151 return MalInt(0)
152 else:
153 raise Exception("count called on non-sequence")
154
155 #def coll_Q(coll): return sequential_Q(coll) or hash_map_Q(coll)
156 #
157 def cons(args):
158 x, seq = args[0], args[1]
159 assert isinstance(seq, MalList)
160 return MalList([x] + seq.values)
161
162 def concat(args):
163 new_lst = []
164 for l in args.values:
165 assert isinstance(l, MalList)
166 new_lst = new_lst + l.values
167 return MalList(new_lst)
168
169 def nth(args):
170 lst, idx = args[0], args[1]
171 assert isinstance(lst, MalList)
172 assert isinstance(idx, MalInt)
173 if idx.value < len(lst): return lst[idx.value]
174 else: raise Exception("nth: index out of range")
175
176 def first(args):
177 a0 = args[0]
178 assert isinstance(a0, MalList)
179 if len(a0) == 0: return nil
180 else: return a0[0]
181
182 def rest(args):
183 a0 = args[0]
184 assert isinstance(a0, MalList)
185 if len(a0) == 0: return MalList([])
186 else: return a0.rest()
187
188 ## retains metadata
189 #def conj(lst, *args):
190 # if types._list_Q(lst):
191 # new_lst = List(list(reversed(list(args))) + lst)
192 # else:
193 # new_lst = Vector(lst + list(args))
194 # if hasattr(lst, "__meta__"):
195 # new_lst.__meta__ = lst.__meta__
196 # return new_lst
197 #
198 #def apply(f, *args): return f(*(list(args[0:-1])+args[-1]))
199 #
200 #def mapf(f, lst): return List(map(f, lst))
201 #
202 #
203 ## Metadata functions
204 #def with_meta(obj, meta):
205 # new_obj = types._clone(obj)
206 # new_obj.__meta__ = meta
207 # return new_obj
208 #
209 #def meta(obj):
210 # if hasattr(obj, "__meta__"): return obj.__meta__
211 # else: return None
212 #
213 #
214 ## Atoms functions
215 #def deref(atm): return atm.val
216 #def reset_BANG(atm,val):
217 # atm.val = val
218 # return atm.val
219 #def swap_BANG(atm,f,*args):
220 # atm.val = f(atm.val,*args)
221 # return atm.val
222
223
224 ns = {
225 '=': do_equal,
226 # 'throw': throw,
227 # 'nil?': types._nil_Q,
228 # 'true?': types._true_Q,
229 # 'false?': types._false_Q,
230 # 'symbol': types._symbol,
231 # 'symbol?': types._symbol_Q,
232 # 'keyword': types._keyword,
233 # 'keyword?': types._keyword_Q,
234 #
235 'pr-str': pr_str,
236 'str': do_str,
237 'prn': prn,
238 'println': println,
239 # 'readline': lambda prompt: mal_readline.readline(prompt),
240 'read-string': read_str,
241 'slurp': slurp,
242 '<': lt,
243 '<=': lte,
244 '>': gt,
245 '>=': gte,
246 '+': plus,
247 '-': minus,
248 '*': multiply,
249 '/': divide,
250 # 'time-ms': lambda : int(time.time() * 1000),
251 #
252 'list': do_list,
253 'list?': list_Q,
254 # 'vector': types._vector,
255 # 'vector?': types._vector_Q,
256 # 'hash-map': types._hash_map,
257 # 'map?': types._hash_map_Q,
258 # 'assoc': assoc,
259 # 'dissoc': dissoc,
260 # 'get': get,
261 # 'contains?': contains_Q,
262 # 'keys': keys,
263 # 'vals': vals,
264 #
265 # 'sequential?': types._sequential_Q,
266 'cons': cons,
267 'concat': concat,
268 'nth': nth,
269 'first': first,
270 'rest': rest,
271 'empty?': empty_Q,
272 'count': count,
273 # 'conj': conj,
274 # 'apply': apply,
275 # 'map': mapf,
276 #
277 # 'with-meta': with_meta,
278 # 'meta': meta,
279 # 'atom': types._atom,
280 # 'atom?': types._atom_Q,
281 # 'deref': deref,
282 # 'reset!': reset_BANG,
283 # 'swap!': swap_BANG
284 }
285