Commit | Line | Data |
---|---|---|
ea81a808 JM |
1 | import copy |
2 | from itertools import chain | |
3 | ||
4 | import mal_types as types | |
5 | from mal_types import List, Vector | |
6 | import printer | |
7 | ||
8 | # Errors/Exceptions | |
9 | def throw(exc): raise Exception(exc) | |
10 | ||
11 | ||
12 | # String functions | |
13 | def pr_str(*args): | |
14 | return " ".join(map(lambda exp: printer._pr_str(exp, True), args)) | |
15 | ||
16 | def do_str(*args): | |
17 | return "".join(map(lambda exp: printer._pr_str(exp, False), args)) | |
18 | ||
19 | def prn(*args): | |
20 | print " ".join(map(lambda exp: printer._pr_str(exp, True), args)) | |
21 | return None | |
22 | ||
23 | def println(*args): | |
24 | line = " ".join(map(lambda exp: printer._pr_str(exp, False), args)) | |
25 | print line.replace('\\n', '\n') | |
26 | return None | |
27 | ||
28 | ||
29 | # Hash map functions | |
30 | def assoc(src_hm, *key_vals): | |
31 | hm = copy.copy(src_hm) | |
32 | for i in range(0,len(key_vals),2): hm[key_vals[i]] = key_vals[i+1] | |
33 | return hm | |
34 | ||
35 | def dissoc(src_hm, *keys): | |
36 | hm = copy.copy(src_hm) | |
b079f510 JM |
37 | for key in keys: |
38 | if key in hm: del hm[key] | |
ea81a808 JM |
39 | return hm |
40 | ||
41 | def get(hm, key): | |
42 | if key in hm: | |
43 | return hm[key] | |
44 | else: | |
45 | return None | |
46 | ||
47 | def contains_Q(hm, key): return key in hm | |
48 | ||
49 | def keys(hm): return types._list(*hm.keys()) | |
50 | ||
51 | def vals(hm): return types._list(*hm.values()) | |
52 | ||
53 | ||
54 | # Sequence functions | |
55 | def coll_Q(coll): return sequential_Q(coll) or hash_map_Q(coll) | |
56 | ||
57 | def cons(x, seq): return List([x]) + List(seq) | |
58 | ||
59 | def concat(*lsts): return List(chain(*lsts)) | |
60 | ||
61 | def nth(lst, idx): return lst[idx] | |
62 | ||
63 | def first(lst): return lst[0] | |
64 | ||
65 | def rest(lst): return List(lst[1:]) | |
66 | ||
67 | def empty_Q(lst): return len(lst) == 0 | |
68 | ||
69 | def count(lst): return len(lst) | |
70 | ||
71 | # retains metadata | |
72 | def conj(lst, *args): | |
73 | if types._list_Q(lst): | |
74 | new_lst = List(list(reversed(list(args))) + lst) | |
75 | else: | |
76 | new_lst = Vector(lst + list(args)) | |
77 | if hasattr(lst, "__meta__"): | |
78 | new_lst.__meta__ = lst.__meta__ | |
79 | return new_lst | |
80 | ||
81 | def apply(f, *args): return f(*(list(args[0:-1])+args[-1])) | |
82 | ||
83 | def mapf(f, lst): return List(map(f, lst)) | |
84 | ||
85 | ||
86 | # Metadata functions | |
87 | def with_meta(obj, meta): | |
a34b0200 JM |
88 | if type(obj) == type(lambda x:x): |
89 | new_obj = obj.__copy__() | |
90 | else: | |
91 | new_obj = copy.copy(obj) | |
ea81a808 JM |
92 | new_obj.__meta__ = meta |
93 | return new_obj | |
94 | ||
95 | def meta(obj): | |
96 | if hasattr(obj, "__meta__"): return obj.__meta__ | |
97 | else: return None | |
98 | ||
99 | ||
100 | # Atoms functions | |
101 | def deref(atm): return atm.val | |
102 | def reset_BANG(atm,val): | |
103 | atm.val = val | |
104 | return atm.val | |
105 | def swap_BANG(atm,f,*args): | |
106 | atm.val = f(atm.val,*args) | |
107 | return atm.val | |
108 | ||
109 | ||
110 | ns = { | |
111 | '=': types._equal_Q, | |
112 | 'throw': throw, | |
113 | 'nil?': types._nil_Q, | |
114 | 'true?': types._true_Q, | |
115 | 'false?': types._false_Q, | |
116 | 'symbol': types._symbol, | |
117 | 'symbol?': types._symbol_Q, | |
118 | 'pr-str': pr_str, | |
119 | 'str': do_str, | |
120 | 'prn': prn, | |
121 | 'println': println, | |
122 | '<': lambda a,b: a<b, | |
123 | '<=': lambda a,b: a<=b, | |
124 | '>': lambda a,b: a>b, | |
125 | '>=': lambda a,b: a>=b, | |
126 | '+': lambda a,b: a+b, | |
127 | '-': lambda a,b: a-b, | |
128 | '*': lambda a,b: a*b, | |
129 | '/': lambda a,b: a/b, | |
130 | ||
131 | 'list': types._list, | |
132 | 'list?': types._list_Q, | |
133 | 'vector': types._vector, | |
134 | 'vector?': types._vector_Q, | |
135 | 'hash-map': types._hash_map, | |
136 | 'map?': types._hash_map_Q, | |
137 | 'assoc': assoc, | |
138 | 'dissoc': dissoc, | |
139 | 'get': get, | |
140 | 'contains?': contains_Q, | |
141 | 'keys': keys, | |
142 | 'vals': vals, | |
143 | ||
144 | 'sequential?': types._sequential_Q, | |
145 | 'cons': cons, | |
146 | 'concat': concat, | |
147 | 'nth': nth, | |
148 | 'first': first, | |
149 | 'rest': rest, | |
150 | 'empty?': empty_Q, | |
151 | 'count': count, | |
152 | 'conj': conj, | |
153 | 'apply': apply, | |
154 | 'map': mapf, | |
155 | ||
156 | 'with-meta': with_meta, | |
157 | 'meta': meta, | |
158 | 'atom': types._atom, | |
159 | 'atom?': types._atom_Q, | |
160 | 'deref': deref, | |
161 | 'reset!': reset_BANG, | |
162 | 'swap!': swap_BANG} | |
163 |