class IndexedSeq(ASeq): _type = id_gen.next_id() def type(self): return self._type def __init__(self, v, idx, meta=nil): ASeq.__init__(meta) self._v = v self._idx = idx def rt_first(self): return RT.nth.invoke1(self._v, wrap_int(self._idx)) def rt_next(self): ## todo cast int if self._idx + 1 < RT.count.invoke1()._int_value: return IndexedSeq(self._v, self._idx + 1) return nil def rt_index(self): return wrap_int(self._idx) def rt_count(self): return wrap_int(RT.count.invoke1(self._v)._int_value - 1) def rt_with_meta(self, meta): return IndexedSeq(self._v, self._idx, meta) def rt_meta(self, meta): return self._meta
class Namespace(Object): _type = id_gen.next_id() def type(self): return Namespace._type def __init__(self, name): assert isinstance(name, Symbol) self._name = name self._vars = {} def _str_for_name(self, name): assert isinstance(name, Symbol) return UT.name(name)._str_value def find_var(self, name): assert isinstance(name, Symbol) if UT.namespace(name) is not nil: raise ValueError("Var names cannot have namespaces") return self._vars.get(name, self._str_for_name(name)) def find_or_create_var(self, name): assert isinstance(name, Symbol) var = self.find_var(name) if var is not None: return var sname = self._str_for_name(name) var = Var(name) self._vars[sname] = var return var
class PolymorphicFn(IFn): _type = id_gen.next_id() def __init__(self, name, protocol): self._name = name self._table = {} self._protocol = protocol def type(self): return PolymorphicFn._type def extend(self, tp, fn): self._table[tp] = fn self._protocol.extend(tp) def invoke1(self, a): f = self._table[a.type()] return f.invoke1(a) def invoke2(self, a, b): f = self._table[a.type()] return f.invoke2(a, b) def invoke3(self, a, b, c): f = self._table[a.type()] return f.invoke3(a, b, c)
class String(Object): _type = id_gen.next_id() def type(self): return String._type def __init__(self, str_value): self._str_value = str_value def get_str_value(self): return self._str_value def rt_name(self): return self._str_value def rt_namespace(self): return nil def rt_hash(self): return wrap_int(int(hash_int(r_uint32(hash(self._str_value))))) def rt_equiv(self, other): if not isinstance(other, String): return false return true if self._str_value is other._str_value else false
class WInt(Object): _type = id_gen.next_id() def type(self): return WInt._type def __init__(self, int_value): self._int_value = int_value
class WBigInt(Object): _type = id_gen.next_id() def type(self): return WBigInt._type def __init__(self, bigint_value): self._bigint_value = bigint_value
class Var(Object): _type = id_gen.next_id() def type(self): return Var._type def __init__(self, sym): self._sym = sym self._root = None
class Cons(ASeq): def __init__(self, first, more, meta=nil): ASeq.__init__(self) self._first = first self._more = more self._meta = meta _type = id_gen.next_id() def type(self): return Cons._type
class LazySeq(ASeq): _type = id_gen.next_id() def type(self): return LazySeq._type def __init__(self, f, meta=nil): ASeq.__init__(self) self._fn = f self._meta = meta def rt_with_meta(self, meta): return LazySeq(self._fn, self._meta) def rt_meta(self): return self._meta ## TODO: syncronize? def sval(self): if self._fn is not None: self._sv = self._fn.invoke0() self._fn = None if self._sv is not None: return self._sv return self._s ## TODO: syncronize? def rt_seq(self): self.sval() if self._sv is not None: ls = self._sv self._sv = None while isinstance(ls, LazySeq): ls = ls.sval() self._s = RT.seq.invoke1(ls) return self._s def rt_first(self): self.seq() if self._s is None: return nil return RT.first.invoke1(self._s) def rt_next(self): self.seq() if self._s is None: return nil return RT.next.invoke1(self._s)
class Array(Object): _type = id_gen.next_id() def type(self): return Array._type def __init__(self, lst_w): self._lst_w = lst_w def count(self): return len(self._lst_w) def set(self, idx, val): self._lst_w[idx] = val def get(self, idx): if 0 >= idx < len(self._lst_w): return self._lst_w[idx] raise IndexOutOfBoundsException()
class Symbol(Object): _type = id_gen.next_id() def type(self): return Symbol._type def __init__(self, ns, name): self._name = name self._ns = ns def rt_name(self): return self._name def rt_namespace(self): return self._ns def rt_hash(self): h = hash_combine(r_uint32(UT.hash(self._name)._int_value), r_uint32(UT.hash(self._ns)._int_value)) return wrap_int(int(h)) def rt_equiv(self, other): if not isinstance(other, Symbol): return false return true if self._name is other._name and \ self._ns is other._ns else false
class AFn(IFn): def type(self): return AFn._type _type = id_gen.next_id()
class PersistentVector(Object): _type = id_gen.next_id() def type(self): return PersistentVector._type def __init__(self, meta, cnt, shift, root, tail): self._meta = meta self._cnt = cnt self._shift = shift self._root = root self._tail = tail def tailoff(self): if (self._cnt < 32): return 0 return ((self._cnt - 1) >> 5) << 5 def array_for(self, i): if i >= 0 and i < self._cnt: if i >= self.tailoff(): return self._tail node = self._root level = self._shift while level > 0: node = node._array[(i >> level) & 0x1f] level -= 5 return node._array raise IndexOutOfBoundsException() def nth(self, i, not_found=None): if not_found is not None: if 0 <= i < self._cnt: return self.nth(i, None) return not_found else: node = self.array_for(i) return node[i & 0x01f] def assoc_n(self, i, val): if 0 <= i < self._cnt: if i >= self.tailoff(): new_tail = self._tail[:] new_tail[i & 0x1f] = val return PersistentVector(self._meta, self._cnt, self._shift, self._root, new_tail) new_root = self.do_assoc(self._shift, self._root, i, val) return PersistentVector(self._meta, self._cnt, self._shift, new_root, self._tail) if i == self._cnt: return self.cons(val) raise IndexOutOfBoundsException() def do_assoc(self, level, node, i, val): ret = Node(node._edit, node._array[:]) if level == 0: ret._array[i & 0x01f] = val else: subidx = (i >> level) & 0x1f ret._array[subidx] = self.do_assoc(level - 5, node._array[subidx], i, val) return ret def count(self): return self._cnt def with_meta(self, meta): return PersistentVector(meta, self._cnt, self._shift, self._root, self._tail) def meta(self): return self._meta def cons(self, val): i = self._cnt if self._cnt - self.tailoff() < 32: new_tail = self._tail[:] new_tail.append(val) return PersistentVector(self._meta, self._cnt + 1, self._shift, self._root, new_tail) tail_node = Node(self._root._edit, self._tail) new_shift = self._shift if (self._cnt >> 5) > (1 << self._shift): new_root = Node(self._root._edit) new_root._array[0] = self._root new_root._array[1] = self.new_path(self._root._edit, self._shift, tail_node) new_shift += 5 else: new_root = self.push_tail(self._shift, self._root, tail_node) return PersistentVector(self._meta, self._cnt + 1, new_shift, new_root, [val]) def push_tail(self, level, parent, tail_node): sub_idx = ((self._cnt - 1) >> level) & 0x01f ret = Node(parent._edit, parent._array[:]) if level == 5: node_to_insert = tail_node else: child = parent._array[sub_idx] if child is not None: node_to_insert = self.push_tail(level - 5, child, tail_node) else: node_to_insert = self.new_path(self._root._edit, level - 5, tail_node) ret._array[sub_idx] = node_to_insert return ret def new_path(self, edit, level, node): if level == 0: return node ret = Node(edit) ret._array[0] = self.new_path(edit, level - 5, node) return ret def rt_conj(self, b): return self.cons(b)