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
):
20 if len(a
) != len(b
): return False
21 for i
in range(len(a
)):
22 if not _equal_Q(a
[i
], b
[i
]): return False
24 ## elif _hash_map_Q(a):
29 ## if len(akeys) != len(bkeys): return False
30 ## for i in range(len(akeys)):
31 ## if akeys[i] != bkeys[i]: return False
32 ## if not equal_Q(a[akeys[i]], b[bkeys[i]]): return False
35 #elif ((a is nil and a is nil) or (a is true and b is true) or (a
36 # is false and b is false)):
39 throw_str("no = op defined for %s" % a
.__class
__.__name
__)
41 def _sequential_Q(seq
): return _list_Q(seq
) or _vector_Q(seq
)
44 if isinstance(obj
, MalFunc
):
45 return MalFunc(obj
.fn
, obj
.ast
, obj
.env
, obj
.params
,
46 obj
.EvalFunc
, obj
.ismacro
)
47 elif isinstance(obj
, MalList
):
48 return obj
.__class
__(obj
.values
)
49 elif isinstance(obj
, MalHashMap
):
50 return MalHashMap(obj
.dct
)
51 elif isinstance(obj
, MalAtom
):
52 return MalAtom(obj
.value
)
54 raise Exception("_clone on invalid type")
56 def _replace(match
, sub
, old_str
):
59 while idx
< len(old_str
):
60 midx
= old_str
.find(match
, idx
)
62 assert midx
>= 0 and midx
< len(old_str
)
63 new_str
= new_str
+ old_str
[idx
:midx
]
64 new_str
= new_str
+ sub
65 idx
= midx
+ len(match
)
66 new_str
= new_str
+ old_str
[idx
:]
73 class MalException(Exception):
74 def __init__(self
, object):
78 raise MalException(MalStr(unicode(s
)))
83 class MalMeta(MalType
): pass
86 class MalNil(MalType
): pass
89 assert isinstance(exp
, MalType
)
92 class MalTrue(MalType
): pass
95 assert isinstance(exp
, MalType
)
98 class MalFalse(MalType
): pass
101 assert isinstance(exp
, MalType
)
105 class MalInt(MalType
):
106 def __init__(self
, value
):
107 assert isinstance(value
, int)
110 assert isinstance(exp
, MalType
)
111 return exp
.__class
__ is MalInt
114 class MalStr(MalType
):
115 def __init__(self
, value
):
116 assert isinstance(value
, unicode)
119 return len(self
.value
)
121 assert isinstance(exp
, MalType
)
122 return exp
.__class
__ is MalStr
125 # A specially prefixed string
127 assert isinstance(mstr
, MalType
)
128 if isinstance(mstr
, MalStr
):
130 if val
[0] == u
"\u029e": return mstr
131 else: return MalStr(u
"\u029e" + val
)
133 throw_str("_keyword called on non-string")
134 # Create keyword from unicode string
136 assert isinstance(strn
, unicode)
137 return MalStr(u
"\u029e" + strn
)
139 if isinstance(exp
, MalStr
):
140 return exp
.value
[0] == u
"\u029e"
145 class MalSym(MalMeta
):
146 def __init__(self
, value
):
147 assert isinstance(value
, unicode)
151 assert isinstance(strn
, unicode)
154 assert isinstance(exp
, MalType
)
155 return exp
.__class
__ is MalSym
158 class MalList(MalMeta
):
159 def __init__(self
, vals
):
160 assert isinstance(vals
, list)
163 def append(self
, val
):
164 self
.values
.append(val
)
166 return MalList(self
.values
[1:])
168 return len(self
.values
)
169 def __getitem__(self
, i
):
170 assert isinstance(i
, int)
171 return self
.values
[i
]
172 def slice(self
, start
):
173 return MalList(self
.values
[start
:len(self
.values
)])
174 def slice2(self
, start
, end
):
176 return MalList(self
.values
[start
:end
])
177 def _list(*vals
): return MalList(list(vals
))
178 def _listl(lst
): return MalList(lst
)
180 assert isinstance(exp
, MalType
)
181 return exp
.__class
__ is MalList
184 class MalVector(MalList
):
186 def _vector(*vals
): return MalVector(list(vals
))
187 def _vectorl(lst
): return MalVector(lst
)
189 assert isinstance(exp
, MalType
)
190 return exp
.__class
__ is MalVector
193 class MalHashMap(MalMeta
):
194 def __init__(self
, dct
):
195 #assert isinstance(dct, {}.__class__)
198 def append(self
, val
):
200 def __getitem__(self
, k
):
201 assert isinstance(k
, unicode)
203 def __setitem__(self
, k
, v
):
204 assert isinstance(k
, unicode)
205 assert isinstance(v
, MalType
)
210 for i
in range(0, len(kvs
), 2):
212 assert isinstance(k
, MalStr
)
215 return MalHashMap(dct
)
216 def _hash_map_Q(exp
):
217 assert isinstance(exp
, MalType
)
218 return exp
.__class
__ is MalHashMap
221 # env import must happen after MalSym and MalList definitions to allow
222 # circular dependency
224 class MalFunc(MalMeta
):
225 def __init__(self
, fn
, ast
=None, env
=None, params
=None,
226 EvalFunc
=None, ismacro
=False):
227 if fn
is None and EvalFunc
is None:
228 throw_str("MalFunc requires either fn or EvalFunc")
233 self
.EvalFunc
= EvalFunc
234 self
.ismacro
= ismacro
236 def apply(self
, args
):
238 return self
.EvalFunc(self
.ast
, self
.gen_env(args
))
241 def gen_env(self
, args
):
242 return Env(self
.env
, self
.params
, args
)
243 def _function_Q(exp
):
244 assert isinstance(exp
, MalType
)
245 return exp
.__class
__ is MalFunc
249 class MalAtom(MalMeta
):
250 def __init__(self
, value
):
253 def _atom(val
): return MalAtom(val
)
254 def _atom_Q(exp
): return exp
.__class
__ is MalAtom