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