1 import sys
, copy
, types
as pytypes
6 assert isinstance(a
, MalType
) and isinstance(b
, MalType
)
7 ota
, otb
= a
.__class
__, b
.__class
__
8 if not (ota
is otb
or (_sequential_Q(a
) and _sequential_Q(b
))):
11 assert isinstance(a
, MalSym
) and isinstance(b
, MalSym
)
12 return a
.value
== b
.value
14 assert isinstance(a
, MalStr
) and isinstance(b
, MalStr
)
15 return a
.value
== b
.value
17 assert isinstance(a
, MalInt
) and isinstance(b
, MalInt
)
18 return a
.value
== b
.value
19 elif _list_Q(a
) or _vector_Q(a
):
21 if len(a
) != len(b
): return False
22 for i
in range(len(a
)):
23 if not _equal_Q(a
[i
], b
[i
]): return False
25 ## elif _hash_map_Q(a):
30 ## if len(akeys) != len(bkeys): return False
31 ## for i in range(len(akeys)):
32 ## if akeys[i] != bkeys[i]: return False
33 ## if not equal_Q(a[akeys[i]], b[bkeys[i]]): return False
36 #elif ((a is nil and a is nil) or (a is true and b is true) or (a
37 # is false and b is false)):
40 throw_str("no = op defined for %s" % a
.__class
__.__name
__)
42 def _sequential_Q(seq
): return _list_Q(seq
) or _vector_Q(seq
)
43 ##def _sequential_Q(seq): return _list_Q(seq)
46 ## #if type(obj) == type(lambda x:x):
47 if isinstance(obj
, MalFunc
):
48 return MalFunc(obj
.fn
, obj
.ast
, obj
.env
, obj
.params
,
49 obj
.EvalFunc
, obj
.ismacro
)
50 elif isinstance(obj
, MalList
):
51 raise Exception("_clone on invalid type")
53 ## return pytypes.FunctionType(
54 ## obj.__code__, obj.__globals__, name = obj.__name__,
55 ## argdefs = obj.__defaults__, closure = obj.__closure__)
57 ## return pytypes.FunctionType(
58 ## obj.func_code, obj.func_globals, name = obj.func_name,
59 ## argdefs = obj.func_defaults, closure = obj.func_closure)
61 ## return copy.copy(obj)
63 def _replace(match
, sub
, old_str
):
66 while idx
< len(old_str
):
67 midx
= old_str
.find(match
, idx
)
69 assert midx
>= 0 and midx
< len(old_str
)
70 new_str
= new_str
+ old_str
[idx
:midx
]
71 new_str
= new_str
+ sub
72 idx
= midx
+ len(match
)
73 new_str
= new_str
+ old_str
[idx
:]
80 class MalException(Exception):
81 def __init__(self
, object):
85 raise MalException(MalStr(unicode(s
)))
92 class MalNil(MalType
): pass
95 assert isinstance(exp
, MalType
)
98 class MalTrue(MalType
): pass
101 assert isinstance(exp
, MalType
)
104 class MalFalse(MalType
): pass
107 assert isinstance(exp
, MalType
)
111 class MalInt(MalType
):
112 def __init__(self
, value
):
113 assert isinstance(value
, int)
116 assert isinstance(exp
, MalType
)
117 return exp
.__class
__ is MalInt
120 class MalStr(MalType
):
121 def __init__(self
, value
):
122 assert isinstance(value
, unicode)
125 return len(self
.value
)
127 assert isinstance(exp
, MalType
)
128 return exp
.__class
__ is MalStr
131 class MalSym(MalType
):
132 def __init__(self
, value
):
133 assert isinstance(value
, unicode)
136 assert isinstance(strn
, unicode)
139 assert isinstance(exp
, MalType
)
140 return exp
.__class
__ is MalSym
143 # A specially prefixed string
145 assert isinstance(mstr
, MalType
)
146 if isinstance(mstr
, MalStr
):
148 if val
[0] == u
"\u029e": return mstr
149 else: return MalStr(u
"\u029e" + val
)
151 throw_str("_keyword called on non-string")
152 # Create keyword from unicode string
154 assert isinstance(strn
, unicode)
155 return MalStr(u
"\u029e" + strn
)
157 if isinstance(exp
, MalStr
):
158 return exp
.value
[0] == u
"\u029e"
163 class MalList(MalType
):
164 def __init__(self
, vals
):
165 assert isinstance(vals
, list)
167 def append(self
, val
):
168 self
.values
.append(val
)
170 return MalList(self
.values
[1:])
172 return len(self
.values
)
173 def __getitem__(self
, i
):
174 assert isinstance(i
, int)
175 return self
.values
[i
]
176 def slice(self
, start
):
177 return MalList(self
.values
[start
:len(self
.values
)])
178 def slice2(self
, start
, end
):
180 return MalList(self
.values
[start
:end
])
181 ## def __add__(self, rhs): return List(list.__add__(self, rhs))
182 ## def __getitem__(self, i):
183 ## if type(i) == slice: return List(list.__getitem__(self, i))
184 ## elif i >= len(self): return None
185 ## else: return list.__getitem__(self, i)
186 def _list(*vals
): return MalList(list(vals
))
187 def _listl(lst
): return MalList(lst
)
189 assert isinstance(exp
, MalType
)
190 return exp
.__class
__ is MalList
193 class MalVector(MalList
):
195 def _vector(*vals
): return MalVector(list(vals
))
196 def _vectorl(lst
): return MalVector(lst
)
198 assert isinstance(exp
, MalType
)
199 return exp
.__class
__ is MalVector
202 class MalHashMap(MalType
):
203 def __init__(self
, dct
):
204 #assert isinstance(dct, {}.__class__)
206 def append(self
, val
):
208 def __getitem__(self
, k
):
209 assert isinstance(k
, unicode)
211 def __setitem__(self
, k
, v
):
212 assert isinstance(k
, unicode)
213 assert isinstance(v
, MalType
)
218 for i
in range(0, len(kvs
), 2):
220 assert isinstance(k
, MalStr
)
223 return MalHashMap(dct
)
224 #def _hash_maph(l): return MalHashMap(l.values)
225 def _hash_map_Q(exp
):
226 assert isinstance(exp
, MalType
)
227 return exp
.__class
__ is MalHashMap
230 # env import must happen after MalSym and MalList definitions to allow
231 # circular dependency
233 class MalFunc(MalType
):
234 def __init__(self
, fn
, ast
=None, env
=None, params
=None,
235 EvalFunc
=None, ismacro
=False):
236 if fn
is None and EvalFunc
is None:
237 throw_str("MalFunc requires either fn or EvalFunc")
239 #assert isinstance(ast, MalType) or ast is None
243 self
.EvalFunc
= EvalFunc
244 self
.ismacro
= ismacro
246 def apply(self
, args
):
248 return self
.EvalFunc(self
.ast
, self
.gen_env(args
))
251 def gen_env(self
, args
):
252 return Env(self
.env
, self
.params
, args
)
253 def _function_Q(exp
):
254 assert isinstance(exp
, MalType
)
255 return exp
.__class
__ is MalFunc
259 class MalAtom(MalType
):
260 def __init__(self
, val
):
262 def _atom(val
): return MalAtom(val
)
263 def _atom_Q(exp
): return exp
.__class
__ is MalAtom