Commit | Line | Data |
---|---|---|
db4c329a | 1 | import copy, time |
ea81a808 JM |
2 | from itertools import chain |
3 | ||
4 | import mal_types as types | |
dd7a4f55 | 5 | from mal_types import MalException, List, Vector |
8cb5cda4 JM |
6 | import mal_readline |
7 | import reader | |
ea81a808 JM |
8 | import printer |
9 | ||
10 | # Errors/Exceptions | |
dd7a4f55 | 11 | def throw(obj): raise MalException(obj) |
ea81a808 JM |
12 | |
13 | ||
14 | # String functions | |
15 | def pr_str(*args): | |
16 | return " ".join(map(lambda exp: printer._pr_str(exp, True), args)) | |
17 | ||
18 | def do_str(*args): | |
19 | return "".join(map(lambda exp: printer._pr_str(exp, False), args)) | |
20 | ||
21 | def prn(*args): | |
a05f7822 | 22 | print(" ".join(map(lambda exp: printer._pr_str(exp, True), args))) |
ea81a808 JM |
23 | return None |
24 | ||
25 | def println(*args): | |
8fe734d2 | 26 | print(" ".join(map(lambda exp: printer._pr_str(exp, False), args))) |
ea81a808 JM |
27 | return None |
28 | ||
29 | ||
30 | # Hash map functions | |
31 | def assoc(src_hm, *key_vals): | |
32 | hm = copy.copy(src_hm) | |
33 | for i in range(0,len(key_vals),2): hm[key_vals[i]] = key_vals[i+1] | |
34 | return hm | |
35 | ||
36 | def dissoc(src_hm, *keys): | |
37 | hm = copy.copy(src_hm) | |
b079f510 | 38 | for key in keys: |
953dc52a | 39 | hm.pop(key, None) |
ea81a808 JM |
40 | return hm |
41 | ||
42 | def get(hm, key): | |
ebaca6bb CB |
43 | if hm is not None: |
44 | return hm.get(key) | |
ea81a808 JM |
45 | else: |
46 | return None | |
47 | ||
48 | def contains_Q(hm, key): return key in hm | |
49 | ||
50 | def keys(hm): return types._list(*hm.keys()) | |
51 | ||
52 | def vals(hm): return types._list(*hm.values()) | |
53 | ||
54 | ||
55 | # Sequence functions | |
56 | def coll_Q(coll): return sequential_Q(coll) or hash_map_Q(coll) | |
57 | ||
58 | def cons(x, seq): return List([x]) + List(seq) | |
59 | ||
60 | def concat(*lsts): return List(chain(*lsts)) | |
61 | ||
b8ee29b2 JM |
62 | def nth(lst, idx): |
63 | if idx < len(lst): return lst[idx] | |
64 | else: throw("nth: index out of range") | |
ea81a808 | 65 | |
8d1e25ac DM |
66 | def first(lst): |
67 | if types._nil_Q(lst): return None | |
68 | else: return lst[0] | |
ea81a808 | 69 | |
8d1e25ac DM |
70 | def rest(lst): |
71 | if types._nil_Q(lst): return List([]) | |
72 | else: return List(lst[1:]) | |
ea81a808 JM |
73 | |
74 | def empty_Q(lst): return len(lst) == 0 | |
75 | ||
b8ee29b2 JM |
76 | def count(lst): |
77 | if types._nil_Q(lst): return 0 | |
78 | else: return len(lst) | |
ea81a808 | 79 | |
6791e640 JM |
80 | def apply(f, *args): return f(*(list(args[0:-1])+args[-1])) |
81 | ||
82 | def mapf(f, lst): return List(map(f, lst)) | |
83 | ||
ea81a808 JM |
84 | # retains metadata |
85 | def conj(lst, *args): | |
86 | if types._list_Q(lst): | |
87 | new_lst = List(list(reversed(list(args))) + lst) | |
88 | else: | |
89 | new_lst = Vector(lst + list(args)) | |
90 | if hasattr(lst, "__meta__"): | |
91 | new_lst.__meta__ = lst.__meta__ | |
92 | return new_lst | |
93 | ||
6791e640 JM |
94 | def seq(obj): |
95 | if types._list_Q(obj): | |
96 | return obj if len(obj) > 0 else None | |
97 | elif types._vector_Q(obj): | |
98 | return List(obj) if len(obj) > 0 else None | |
99 | elif types._string_Q(obj): | |
100 | return List([c for c in obj]) if len(obj) > 0 else None | |
101 | elif obj == None: | |
102 | return None | |
103 | else: throw ("seq: called on non-sequence") | |
ea81a808 JM |
104 | |
105 | # Metadata functions | |
106 | def with_meta(obj, meta): | |
a05f7822 | 107 | new_obj = types._clone(obj) |
ea81a808 JM |
108 | new_obj.__meta__ = meta |
109 | return new_obj | |
110 | ||
111 | def meta(obj): | |
a77b8357 | 112 | return getattr(obj, "__meta__", None) |
ea81a808 JM |
113 | |
114 | ||
115 | # Atoms functions | |
116 | def deref(atm): return atm.val | |
117 | def reset_BANG(atm,val): | |
118 | atm.val = val | |
119 | return atm.val | |
120 | def swap_BANG(atm,f,*args): | |
121 | atm.val = f(atm.val,*args) | |
122 | return atm.val | |
123 | ||
124 | ||
125 | ns = { | |
126 | '=': types._equal_Q, | |
127 | 'throw': throw, | |
128 | 'nil?': types._nil_Q, | |
129 | 'true?': types._true_Q, | |
130 | 'false?': types._false_Q, | |
9e1b1752 | 131 | 'number?': types._number_Q, |
6791e640 | 132 | 'string?': types._string_Q, |
ea81a808 JM |
133 | 'symbol': types._symbol, |
134 | 'symbol?': types._symbol_Q, | |
b8ee29b2 JM |
135 | 'keyword': types._keyword, |
136 | 'keyword?': types._keyword_Q, | |
9e1b1752 VS |
137 | 'fn?': lambda x: (types._function_Q(x) and not hasattr(x, '_ismacro_')), |
138 | 'macro?': lambda x: (types._function_Q(x) and | |
139 | hasattr(x, '_ismacro_') and | |
140 | x._ismacro_), | |
8cb5cda4 | 141 | |
ea81a808 JM |
142 | 'pr-str': pr_str, |
143 | 'str': do_str, | |
144 | 'prn': prn, | |
145 | 'println': println, | |
8cb5cda4 JM |
146 | 'readline': lambda prompt: mal_readline.readline(prompt), |
147 | 'read-string': reader.read_str, | |
148 | 'slurp': lambda file: open(file).read(), | |
ea81a808 JM |
149 | '<': lambda a,b: a<b, |
150 | '<=': lambda a,b: a<=b, | |
151 | '>': lambda a,b: a>b, | |
152 | '>=': lambda a,b: a>=b, | |
153 | '+': lambda a,b: a+b, | |
154 | '-': lambda a,b: a-b, | |
155 | '*': lambda a,b: a*b, | |
a05f7822 | 156 | '/': lambda a,b: int(a/b), |
db4c329a | 157 | 'time-ms': lambda : int(time.time() * 1000), |
ea81a808 JM |
158 | |
159 | 'list': types._list, | |
160 | 'list?': types._list_Q, | |
161 | 'vector': types._vector, | |
162 | 'vector?': types._vector_Q, | |
163 | 'hash-map': types._hash_map, | |
164 | 'map?': types._hash_map_Q, | |
165 | 'assoc': assoc, | |
166 | 'dissoc': dissoc, | |
167 | 'get': get, | |
168 | 'contains?': contains_Q, | |
169 | 'keys': keys, | |
170 | 'vals': vals, | |
171 | ||
172 | 'sequential?': types._sequential_Q, | |
173 | 'cons': cons, | |
174 | 'concat': concat, | |
175 | 'nth': nth, | |
176 | 'first': first, | |
177 | 'rest': rest, | |
178 | 'empty?': empty_Q, | |
179 | 'count': count, | |
ea81a808 JM |
180 | 'apply': apply, |
181 | 'map': mapf, | |
182 | ||
6791e640 JM |
183 | 'conj': conj, |
184 | 'seq': seq, | |
185 | ||
ea81a808 JM |
186 | 'with-meta': with_meta, |
187 | 'meta': meta, | |
188 | 'atom': types._atom, | |
189 | 'atom?': types._atom_Q, | |
190 | 'deref': deref, | |
191 | 'reset!': reset_BANG, | |
192 | 'swap!': swap_BANG} | |
193 |