[pypy-svn] r26071 - in pypy/dist/pypy: jit/timeshifter rpython rpython/lltypesystem rpython/ootypesystem rpython/ootypesystem/test rpython/test

antocuni at codespeak.net antocuni at codespeak.net
Fri Apr 21 00:17:56 CEST 2006


Author: antocuni
Date: Fri Apr 21 00:17:24 2006
New Revision: 26071

Added:
   pypy/dist/pypy/rpython/lltypesystem/rdict.py   (contents, props changed)
   pypy/dist/pypy/rpython/ootypesystem/rdict.py   (contents, props changed)
   pypy/dist/pypy/rpython/ootypesystem/test/test_oodict.py   (contents, props changed)
Modified:
   pypy/dist/pypy/jit/timeshifter/timeshift.py
   pypy/dist/pypy/rpython/lltypesystem/rlist.py
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/ootypesystem/rlist.py
   pypy/dist/pypy/rpython/ootypesystem/test/test_oolist.py
   pypy/dist/pypy/rpython/rbuiltin.py
   pypy/dist/pypy/rpython/rdict.py
   pypy/dist/pypy/rpython/rtyper.py
   pypy/dist/pypy/rpython/test/test_rdict.py
   pypy/dist/pypy/rpython/typesystem.py
Log:
- rdict has been made type-system depended. Almost all old code has
been moved to lltypesystem/rdict.py.

- some files has been fixed because they imported directly
rpython.rdict.

- a new Dict definition has been added to ootype.py.

Three tests in test_rtuple.py fail because by now ootypesystem lacks a
DictRepr, but they should automatically pass as soon as
ootypesystem.rdict.DictRepr will be added.



Modified: pypy/dist/pypy/jit/timeshifter/timeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/timeshift.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/timeshift.py	Fri Apr 21 00:17:24 2006
@@ -5,8 +5,8 @@
 from pypy.annotation import listdef, dictdef
 from pypy.jit.timeshifter import rvalue
 from pypy.jit.timeshifter.rtimeshift import JITState
-from pypy.rpython import rmodel, rdict, rgenop, annlowlevel
-from pypy.rpython.lltypesystem import rtuple, rlist
+from pypy.rpython import rmodel, rgenop, annlowlevel
+from pypy.rpython.lltypesystem import rtuple, rlist, rdict
 from pypy.jit.timeshifter import rtimeshift
 from pypy.jit.timeshifter.rtyper import HintRTyper, originalconcretetype
 from pypy.jit.timeshifter.rtyper import GreenRepr, RedRepr, HintLowLevelOpList

Added: pypy/dist/pypy/rpython/lltypesystem/rdict.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/lltypesystem/rdict.py	Fri Apr 21 00:17:24 2006
@@ -0,0 +1,773 @@
+from pypy.annotation.pairtype import pairtype
+from pypy.annotation import model as annmodel
+from pypy.objspace.flow.model import Constant
+from pypy.rpython.rdict import AbstractDictRepr, rtype_newdict
+from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.rarithmetic import r_uint
+from pypy.rpython.objectmodel import hlinvoke
+from pypy.rpython import robject
+from pypy.rpython import objectmodel
+from pypy.rpython import rmodel
+
+# ____________________________________________________________
+#
+#  generic implementation of RPython dictionary, with parametric DICTKEY and
+#  DICTVALUE types.
+#
+#  XXX for immutable dicts, the array should be inlined and
+#      num_pristine_entries and everused are not needed.
+#
+#    struct dictentry {
+#        DICTKEY key;
+#        bool f_valid;      # (optional) the entry is filled
+#        bool f_everused;   # (optional) the entry is or has ever been filled
+#        DICTVALUE value;
+#        int f_hash;        # (optional) key hash, if hard to recompute
+#    }
+#    
+#    struct dicttable {
+#        int num_items;
+#        int num_pristine_entries;  # never used entries
+#        Array *entries;
+#        (Function DICTKEY, DICTKEY -> bool) *fnkeyeq;
+#        (Function DICTKEY -> int) *fnkeyhash;
+#    }
+#
+#
+
+class DictRepr(AbstractDictRepr):
+
+    def __init__(self, rtyper, key_repr, value_repr, dictkey, dictvalue,
+                 custom_eq_hash=None):
+        self.rtyper = rtyper
+        self.DICT = lltype.GcForwardReference()
+        self.lowleveltype = lltype.Ptr(self.DICT)
+        self.custom_eq_hash = custom_eq_hash is not None
+        if not isinstance(key_repr, rmodel.Repr):  # not computed yet, done by setup()
+            assert callable(key_repr)
+            self._key_repr_computer = key_repr 
+        else:
+            self.external_key_repr, self.key_repr = self.pickkeyrepr(key_repr)
+        if not isinstance(value_repr, rmodel.Repr):  # not computed yet, done by setup()
+            assert callable(value_repr)
+            self._value_repr_computer = value_repr 
+        else:
+            self.external_value_repr, self.value_repr = self.pickrepr(value_repr)
+        self.dictkey = dictkey
+        self.dictvalue = dictvalue
+        self.dict_cache = {}
+        self._custom_eq_hash_repr = custom_eq_hash
+        # setup() needs to be called to finish this initialization
+        
+    def pickrepr(self, item_repr):
+        if self.custom_eq_hash:
+            return item_repr, item_repr
+        else:
+            return rmodel.externalvsinternal(self.rtyper, item_repr)
+
+    def pickkeyrepr(self, key_repr):
+        external, internal = self.pickrepr(key_repr)
+        if external != internal:
+            internal = external
+            while not self.rtyper.needs_hash_support(internal.classdef):
+                internal = internal.rbase
+        return external, internal
+        
+    def compact_repr(self):
+        return 'DictR %s %s' % (self.key_repr.compact_repr(), self.value_repr.compact_repr())
+
+    def _setup_repr(self):
+        if 'key_repr' not in self.__dict__:
+            key_repr = self._key_repr_computer()
+            self.external_key_repr, self.key_repr = self.pickkeyrepr(key_repr)
+        if 'value_repr' not in self.__dict__:
+            self.external_value_repr, self.value_repr = self.pickrepr(self._value_repr_computer())
+        if isinstance(self.DICT, lltype.GcForwardReference):
+            self.DICTKEY = self.key_repr.lowleveltype
+            self.DICTVALUE = self.value_repr.lowleveltype
+
+            # compute the shape of the DICTENTRY structure
+            entryfields = []
+            entrymeths = {
+                'must_clear_key':   (isinstance(self.DICTKEY, lltype.Ptr)
+                                     and self.DICTKEY._needsgc()),
+                'must_clear_value': (isinstance(self.DICTVALUE, lltype.Ptr)
+                                     and self.DICTVALUE._needsgc()),
+                }
+
+            # * the key
+            entryfields.append(("key", self.DICTKEY))
+
+            # * if NULL is not a valid ll value for the key or the value
+            #   field of the entry, it can be used as a marker for
+            #   never-used entries.  Otherwise, we need an explicit flag.
+            s_key   = self.dictkey.s_value
+            s_value = self.dictvalue.s_value
+            nullkeymarker = not self.key_repr.can_ll_be_null(s_key)
+            nullvaluemarker = not self.value_repr.can_ll_be_null(s_value)
+
+            if nullkeymarker:
+                entrymeths['everused'] = ll_everused_from_key
+            elif nullvaluemarker:
+                entrymeths['everused'] = ll_everused_from_value
+            else:
+                entryfields.append(("f_everused", lltype.Bool))
+                entrymeths['everused'] = ll_everused_from_flag
+
+            # * if the key or the value can also contain a "dummy" non-null
+            #   marker, we use it for deleted entries.
+            rtyper = self.rtyper
+            dummy_obj = self.key_repr.get_ll_dummyval_obj(rtyper, s_key)
+            if dummy_obj:
+                entrymeths['dummy_obj'] = dummy_obj
+                entrymeths['valid'] = ll_valid_from_key
+                entrymeths['mark_deleted'] = ll_mark_deleted_in_key
+                # the key is overwritten by 'dummy' when the entry is deleted
+                entrymeths['must_clear_key'] = False
+            else:
+                dummy_obj = self.value_repr.get_ll_dummyval_obj(rtyper,
+                                                                s_value)
+                if dummy_obj:
+                    entrymeths['dummy_obj'] = dummy_obj
+                    entrymeths['valid'] = ll_valid_from_value
+                    entrymeths['mark_deleted'] = ll_mark_deleted_in_value
+                    # value is overwritten by 'dummy' when entry is deleted
+                    entrymeths['must_clear_value'] = False
+                else:
+                    entryfields.append(("f_valid", lltype.Bool))
+                    entrymeths['valid'] = ll_valid_from_flag
+                    entrymeths['mark_deleted'] = ll_mark_deleted_in_flag
+
+            # * the value
+            entryfields.append(("value", self.DICTVALUE))
+
+            # * the hash, if needed
+            if self.custom_eq_hash:
+                fasthashfn = None
+            else:
+                fasthashfn = self.key_repr.get_ll_fasthash_function()
+            if fasthashfn is None:
+                entryfields.append(("f_hash", lltype.Signed))
+                entrymeths['hash'] = ll_hash_from_cache
+            else:
+                entrymeths['hash'] = ll_hash_recomputed
+                entrymeths['fasthashfn'] = fasthashfn
+
+            # Build the lltype data structures
+            self.DICTENTRY = lltype.Struct("dictentry", adtmeths=entrymeths,
+                                           *entryfields)
+            self.DICTENTRYARRAY = lltype.GcArray(self.DICTENTRY)
+            fields =          [ ("num_items", lltype.Signed),
+                                ("num_pristine_entries", lltype.Signed), 
+                                ("entries", lltype.Ptr(self.DICTENTRYARRAY)) ]
+            if self.custom_eq_hash:
+                self.r_rdict_eqfn, self.r_rdict_hashfn = self._custom_eq_hash_repr()
+                fields.extend([ ("fnkeyeq", self.r_rdict_eqfn.lowleveltype),
+                                ("fnkeyhash", self.r_rdict_hashfn.lowleveltype) ])
+                adtmeths = {
+                    'keyhash':        ll_keyhash_custom,
+                    'keyeq':          ll_keyeq_custom,
+                    'r_rdict_eqfn':   self.r_rdict_eqfn,
+                    'r_rdict_hashfn': self.r_rdict_hashfn,
+                    'paranoia':       True,
+                    }
+            else:
+                # figure out which functions must be used to hash and compare
+                ll_keyhash = self.key_repr.get_ll_hash_function()
+                ll_keyeq = self.key_repr.get_ll_eq_function()  # can be None
+                ll_keyhash = lltype.staticAdtMethod(ll_keyhash)
+                if ll_keyeq is not None:
+                    ll_keyeq = lltype.staticAdtMethod(ll_keyeq)
+                adtmeths = {
+                    'keyhash':  ll_keyhash,
+                    'keyeq':    ll_keyeq,
+                    'paranoia': False,
+                    }
+            self.DICT.become(lltype.GcStruct("dicttable", adtmeths=adtmeths,
+                                             *fields))
+
+    def recast_value(self, llops, v):
+        return llops.convertvar(v, self.value_repr, self.external_value_repr)
+
+    def recast_key(self, llops, v):
+        return llops.convertvar(v, self.key_repr, self.external_key_repr)
+
+    def convert_const(self, dictobj):
+        # get object from bound dict methods
+        #dictobj = getattr(dictobj, '__self__', dictobj) 
+        if dictobj is None:
+            return lltype.nullptr(self.DICT)
+        if not isinstance(dictobj, (dict, objectmodel.r_dict)):
+            raise TyperError("expected a dict: %r" % (dictobj,))
+        try:
+            key = Constant(dictobj)
+            return self.dict_cache[key]
+        except KeyError:
+            self.setup()
+            l_dict = ll_newdict_size(self.DICT, len(dictobj))
+            self.dict_cache[key] = l_dict 
+            r_key = self.key_repr
+            r_value = self.value_repr
+            if isinstance(dictobj, objectmodel.r_dict):
+                if self.r_rdict_eqfn.lowleveltype != lltype.Void:
+                    l_fn = self.r_rdict_eqfn.convert_const(dictobj.key_eq)
+                    l_dict.fnkeyeq = l_fn
+                if self.r_rdict_hashfn.lowleveltype != lltype.Void:
+                    l_fn = self.r_rdict_hashfn.convert_const(dictobj.key_hash)
+                    l_dict.fnkeyhash = l_fn
+
+                for dictkeycontainer, dictvalue in dictobj._dict.items():
+                    llkey = r_key.convert_const(dictkeycontainer.key)
+                    llvalue = r_value.convert_const(dictvalue)
+                    ll_dict_insertclean(l_dict, llkey, llvalue,
+                                        dictkeycontainer.hash)
+                return l_dict
+
+            else:
+                for dictkey, dictvalue in dictobj.items():
+                    llkey = r_key.convert_const(dictkey)
+                    llvalue = r_value.convert_const(dictvalue)
+                    ll_dict_insertclean(l_dict, llkey, llvalue,
+                                        l_dict.keyhash(llkey))
+                return l_dict
+
+    def rtype_len(self, hop):
+        v_dict, = hop.inputargs(self)
+        return hop.gendirectcall(ll_dict_len, v_dict)
+
+    def rtype_is_true(self, hop):
+        v_dict, = hop.inputargs(self)
+        return hop.gendirectcall(ll_dict_is_true, v_dict)
+
+    def make_iterator_repr(self, *variant):
+        return DictIteratorRepr(self, *variant)
+
+    def rtype_method_get(self, hop):
+        v_dict, v_key, v_default = hop.inputargs(self, self.key_repr,
+                                                 self.value_repr)
+        hop.exception_cannot_occur()
+        v_res = hop.gendirectcall(ll_get, v_dict, v_key, v_default)
+        return self.recast_value(hop.llops, v_res)
+
+    def rtype_method_setdefault(self, hop):
+        v_dict, v_key, v_default = hop.inputargs(self, self.key_repr,
+                                                 self.value_repr)
+        hop.exception_cannot_occur()
+        v_res = hop.gendirectcall(ll_setdefault, v_dict, v_key, v_default)
+        return self.recast_value(hop.llops, v_res)
+    
+    def rtype_method_copy(self, hop):
+        v_dict, = hop.inputargs(self)
+        hop.exception_cannot_occur()
+        return hop.gendirectcall(ll_copy, v_dict)
+
+    def rtype_method_update(self, hop):
+        v_dic1, v_dic2 = hop.inputargs(self, self)
+        hop.exception_cannot_occur()
+        return hop.gendirectcall(ll_update, v_dic1, v_dic2)
+
+    def _rtype_method_kvi(self, hop, spec):
+        v_dic, = hop.inputargs(self)
+        r_list = hop.r_result
+        v_func = hop.inputconst(lltype.Void, spec)
+        cLIST = hop.inputconst(lltype.Void, r_list.lowleveltype.TO)
+        hop.exception_cannot_occur()
+        return hop.gendirectcall(ll_kvi, v_dic, cLIST, v_func)
+
+    def rtype_method_keys(self, hop):
+        return self._rtype_method_kvi(hop, dum_keys)
+
+    def rtype_method_values(self, hop):
+        return self._rtype_method_kvi(hop, dum_values)
+
+    def rtype_method_items(self, hop):
+        return self._rtype_method_kvi(hop, dum_items)
+
+    def rtype_method_iterkeys(self, hop):
+        hop.exception_cannot_occur()
+        return DictIteratorRepr(self, "keys").newiter(hop)
+
+    def rtype_method_itervalues(self, hop):
+        hop.exception_cannot_occur()
+        return DictIteratorRepr(self, "values").newiter(hop)
+
+    def rtype_method_iteritems(self, hop):
+        hop.exception_cannot_occur()
+        return DictIteratorRepr(self, "items").newiter(hop)
+
+    def rtype_method_clear(self, hop):
+        v_dict, = hop.inputargs(self)
+        hop.exception_cannot_occur()
+        return hop.gendirectcall(ll_clear, v_dict)
+
+class __extend__(pairtype(DictRepr, rmodel.Repr)): 
+
+    def rtype_getitem((r_dict, r_key), hop):
+        v_dict, v_key = hop.inputargs(r_dict, r_dict.key_repr)
+        if not r_dict.custom_eq_hash:
+            hop.has_implicit_exception(KeyError)   # record that we know about it
+        hop.exception_is_here()
+        v_res = hop.gendirectcall(ll_dict_getitem, v_dict, v_key)
+        return r_dict.recast_value(hop.llops, v_res)
+
+    def rtype_delitem((r_dict, r_key), hop):
+        v_dict, v_key = hop.inputargs(r_dict, r_dict.key_repr)
+        if not r_dict.custom_eq_hash:
+            hop.has_implicit_exception(KeyError)   # record that we know about it        
+        hop.exception_is_here()
+        return hop.gendirectcall(ll_dict_delitem, v_dict, v_key)
+
+    def rtype_setitem((r_dict, r_key), hop):
+        v_dict, v_key, v_value = hop.inputargs(r_dict, r_dict.key_repr, r_dict.value_repr)
+        if r_dict.custom_eq_hash:
+            hop.exception_is_here()
+        else:
+            hop.exception_cannot_occur()
+        hop.gendirectcall(ll_dict_setitem, v_dict, v_key, v_value)
+
+    def rtype_contains((r_dict, r_key), hop):
+        v_dict, v_key = hop.inputargs(r_dict, r_dict.key_repr)
+        return hop.gendirectcall(ll_contains, v_dict, v_key)
+        
+class __extend__(pairtype(DictRepr, DictRepr)):
+    def convert_from_to((r_dict1, r_dict2), v, llops):
+        # check that we don't convert from Dicts with
+        # different key/value types 
+        if r_dict1.dictkey is None or r_dict2.dictkey is None:
+            return NotImplemented
+        if r_dict1.dictkey is not r_dict2.dictkey:
+            return NotImplemented
+        if r_dict1.dictvalue is None or r_dict2.dictvalue is None:
+            return NotImplemented
+        if r_dict1.dictvalue is not r_dict2.dictvalue:
+            return NotImplemented
+        return v
+
+# ____________________________________________________________
+#
+#  Low-level methods.  These can be run for testing, but are meant to
+#  be direct_call'ed from rtyped flow graphs, which means that they will
+#  get flowed and annotated, mostly with SomePtr.
+
+def ll_everused_from_flag(entry):
+    return entry.f_everused
+
+def ll_everused_from_key(entry):
+    return bool(entry.key)
+
+def ll_everused_from_value(entry):
+    return bool(entry.value)
+
+def ll_valid_from_flag(entry):
+    return entry.f_valid
+
+def ll_mark_deleted_in_flag(entry):
+    entry.f_valid = False
+
+def ll_valid_from_key(entry):
+    ENTRY = lltype.typeOf(entry).TO
+    dummy = ENTRY.dummy_obj.ll_dummy_value
+    return entry.everused() and entry.key != dummy
+
+def ll_mark_deleted_in_key(entry):
+    ENTRY = lltype.typeOf(entry).TO
+    dummy = ENTRY.dummy_obj.ll_dummy_value
+    entry.key = dummy
+
+def ll_valid_from_value(entry):
+    ENTRY = lltype.typeOf(entry).TO
+    dummy = ENTRY.dummy_obj.ll_dummy_value
+    return entry.everused() and entry.value != dummy
+
+def ll_mark_deleted_in_value(entry):
+    ENTRY = lltype.typeOf(entry).TO
+    dummy = ENTRY.dummy_obj.ll_dummy_value
+    entry.value = dummy
+
+def ll_hash_from_cache(entry):
+    return entry.f_hash
+
+def ll_hash_recomputed(entry):
+    ENTRY = lltype.typeOf(entry).TO
+    return ENTRY.fasthashfn(entry.key)
+
+def ll_keyhash_custom(d, key):
+    DICT = lltype.typeOf(d).TO
+    return hlinvoke(DICT.r_rdict_hashfn, d.fnkeyhash, key)
+
+def ll_keyeq_custom(d, key1, key2):
+    DICT = lltype.typeOf(d).TO
+    return hlinvoke(DICT.r_rdict_eqfn, d.fnkeyeq, key1, key2)
+
+def dum_keys(): pass
+def dum_values(): pass
+def dum_items():pass
+dum_variant = {"keys":   dum_keys,
+               "values": dum_values,
+               "items":  dum_items}
+
+def ll_dict_len(d):
+    return d.num_items 
+
+def ll_dict_is_true(d):
+    # check if a dict is True, allowing for None
+    return bool(d) and d.num_items != 0
+
+def ll_dict_getitem(d, key):
+    entry = ll_dict_lookup(d, key, d.keyhash(key))
+    if entry.valid():
+        return entry.value 
+    else: 
+        raise KeyError 
+
+def ll_dict_setitem(d, key, value):
+    hash = d.keyhash(key)
+    entry = ll_dict_lookup(d, key, hash)
+    everused = entry.everused()
+    valid    = entry.valid()
+    # set up the new entry
+    ENTRY = lltype.typeOf(entry).TO
+    entry.value = value
+    if valid:
+        return
+    entry.key = key
+    if hasattr(ENTRY, 'f_hash'):  entry.f_hash = hash
+    if hasattr(ENTRY, 'f_valid'): entry.f_valid = True
+    d.num_items += 1
+    if not everused:
+        if hasattr(ENTRY, 'f_everused'): entry.f_everused = True
+        d.num_pristine_entries -= 1
+        if d.num_pristine_entries <= len(d.entries) / 3:
+            ll_dict_resize(d)
+
+def ll_dict_insertclean(d, key, value, hash):
+    # Internal routine used by ll_dict_resize() to insert an item which is
+    # known to be absent from the dict.  This routine also assumes that
+    # the dict contains no deleted entries.  This routine has the advantage
+    # of never calling d.keyhash() and d.keyeq(), so it cannot call back
+    # to user code.  ll_dict_insertclean() doesn't resize the dict, either.
+    entry = ll_dict_lookup_clean(d, hash)
+    ENTRY = lltype.typeOf(entry).TO
+    entry.value = value
+    entry.key = key
+    if hasattr(ENTRY, 'f_hash'):     entry.f_hash = hash
+    if hasattr(ENTRY, 'f_valid'):    entry.f_valid = True
+    if hasattr(ENTRY, 'f_everused'): entry.f_everused = True
+    d.num_items += 1
+    d.num_pristine_entries -= 1
+
+def ll_dict_delitem(d, key):
+    entry = ll_dict_lookup(d, key, d.keyhash(key))
+    if not entry.valid():
+        raise KeyError
+    entry.mark_deleted()
+    d.num_items -= 1
+    # clear the key and the value if they are GC pointers
+    ENTRY = lltype.typeOf(entry).TO
+    if ENTRY.must_clear_key:
+        key = entry.key   # careful about destructor side effects:
+                          # keep key alive until entry.value has also
+                          # been zeroed (if it must be)
+        entry.key = lltype.nullptr(ENTRY.key.TO)
+    if ENTRY.must_clear_value:
+        entry.value = lltype.nullptr(ENTRY.value.TO)
+    num_entries = len(d.entries)
+    if num_entries > DICT_INITSIZE and d.num_items < num_entries / 4:
+        ll_dict_resize(d)
+
+def ll_dict_resize(d):
+    old_entries = d.entries
+    old_size = len(old_entries) 
+    # make a 'new_size' estimate and shrink it if there are many
+    # deleted entry markers
+    new_size = old_size * 2
+    while new_size > DICT_INITSIZE and d.num_items < new_size / 4:
+        new_size /= 2
+    d.entries = lltype.malloc(lltype.typeOf(old_entries).TO, new_size)
+    d.num_items = 0
+    d.num_pristine_entries = new_size
+    i = 0
+    while i < old_size:
+        entry = old_entries[i]
+        if entry.valid():
+            ll_dict_insertclean(d, entry.key, entry.value, entry.hash())
+        i += 1
+
+# ------- a port of CPython's dictobject.c's lookdict implementation -------
+PERTURB_SHIFT = 5
+
+def ll_dict_lookup(d, key, hash):
+    DICT = lltype.typeOf(d).TO
+    entries = d.entries
+    mask = len(entries) - 1
+    i = r_uint(hash & mask) 
+    # do the first try before any looping 
+    entry = entries[i]
+    if entry.valid():
+        checkingkey = entry.key
+        if checkingkey == key:
+            return entry   # found the entry
+        if d.keyeq is not None and entry.hash() == hash:
+            # correct hash, maybe the key is e.g. a different pointer to
+            # an equal object
+            found = d.keyeq(checkingkey, key)
+            if DICT.paranoia:
+                if (entries != d.entries or
+                    not entry.valid() or entry.key != checkingkey):
+                    # the compare did major nasty stuff to the dict: start over
+                    return ll_dict_lookup(d, key, hash)
+            if found:
+                return entry   # found the entry
+        freeslot = lltype.nullptr(lltype.typeOf(entry).TO)
+    elif entry.everused():
+        freeslot = entry
+    else:
+        return entry    # pristine entry -- lookup failed
+
+    # In the loop, a deleted entry (everused and not valid) is by far
+    # (factor of 100s) the least likely outcome, so test for that last.
+    perturb = r_uint(hash) 
+    while 1: 
+        i = ((i << 2) + i + perturb + 1) & mask
+        entry = entries[i]
+        if not entry.everused():
+            return freeslot or entry 
+        elif entry.valid():
+            checkingkey = entry.key
+            if checkingkey == key:
+                return entry
+            if d.keyeq is not None and entry.hash() == hash:
+                # correct hash, maybe the key is e.g. a different pointer to
+                # an equal object
+                found = d.keyeq(checkingkey, key)
+                if DICT.paranoia:
+                    if (entries != d.entries or
+                        not entry.valid() or entry.key != checkingkey):
+                        # the compare did major nasty stuff to the dict:
+                        # start over
+                        return ll_dict_lookup(d, key, hash)
+                if found:
+                    return entry   # found the entry
+        elif not freeslot:
+            freeslot = entry 
+        perturb >>= PERTURB_SHIFT
+
+def ll_dict_lookup_clean(d, hash):
+    # a simplified version of ll_dict_lookup() which assumes that the
+    # key is new, and the dictionary doesn't contain deleted entries.
+    # It only find the next free slot for the given hash.
+    entries = d.entries
+    mask = len(entries) - 1
+    i = r_uint(hash & mask) 
+    entry = entries[i]
+    perturb = r_uint(hash) 
+    while entry.everused():
+        i = ((i << 2) + i + perturb + 1) & mask
+        entry = entries[i]
+        perturb >>= PERTURB_SHIFT
+    return entry
+
+# ____________________________________________________________
+#
+#  Irregular operations.
+
+DICT_INITSIZE = 8
+
+def ll_newdict(DICT):
+    d = lltype.malloc(DICT)
+    d.entries = lltype.malloc(DICT.entries.TO, DICT_INITSIZE)
+    #d.num_items = 0    -- defaults
+    d.num_pristine_entries = DICT_INITSIZE
+    return d
+
+def ll_newdict_size(DICT, length_estimate):
+    length_estimate = (length_estimate // 2) * 3
+    n = DICT_INITSIZE
+    while n < length_estimate:
+        n *= 2
+    d = lltype.malloc(DICT)
+    d.entries = lltype.malloc(DICT.entries.TO, n)
+    #d.num_items = 0    -- defaults
+    d.num_pristine_entries = DICT_INITSIZE
+    return d
+
+
+def rtype_r_dict(hop):
+    r_dict = hop.r_result
+    if not r_dict.custom_eq_hash:
+        raise TyperError("r_dict() call does not return an r_dict instance")
+    v_eqfn, v_hashfn = hop.inputargs(r_dict.r_rdict_eqfn,
+                                     r_dict.r_rdict_hashfn)
+    cDICT = hop.inputconst(lltype.Void, r_dict.DICT)
+    hop.exception_cannot_occur()
+    v_result = hop.gendirectcall(ll_newdict, cDICT)
+    if r_dict.r_rdict_eqfn.lowleveltype != lltype.Void:
+        cname = hop.inputconst(lltype.Void, 'fnkeyeq')
+        hop.genop('setfield', [v_result, cname, v_eqfn])
+    if r_dict.r_rdict_hashfn.lowleveltype != lltype.Void:
+        cname = hop.inputconst(lltype.Void, 'fnkeyhash')
+        hop.genop('setfield', [v_result, cname, v_hashfn])
+    return v_result
+
+# ____________________________________________________________
+#
+#  Iteration.
+
+class DictIteratorRepr(rmodel.IteratorRepr):
+
+    def __init__(self, r_dict, variant="keys"):
+        self.r_dict = r_dict
+        self.variant = variant
+        self.lowleveltype = lltype.Ptr(lltype.GcStruct('dictiter',
+                                         ('dict', r_dict.lowleveltype),
+                                         ('index', lltype.Signed)))
+
+    def newiter(self, hop):
+        v_dict, = hop.inputargs(self.r_dict)
+        citerptr = hop.inputconst(lltype.Void, self.lowleveltype)
+        return hop.gendirectcall(ll_dictiter, citerptr, v_dict)
+
+    def rtype_next(self, hop):
+        variant = self.variant
+        v_iter, = hop.inputargs(self)
+        v_func = hop.inputconst(lltype.Void, dum_variant[self.variant])
+        if variant in ('keys', 'values'):
+            c1 = hop.inputconst(lltype.Void, None)
+        else:
+            c1 = hop.inputconst(lltype.Void, hop.r_result.lowleveltype)
+        hop.has_implicit_exception(StopIteration) # record that we know about it
+        hop.exception_is_here()
+        v = hop.gendirectcall(ll_dictnext, v_iter, v_func, c1)
+        if variant == 'keys':
+            return self.r_dict.recast_key(hop.llops, v)
+        elif variant == 'values':
+            return self.r_dict.recast_value(hop.llops, v)
+        else:
+            return v
+
+def ll_dictiter(ITERPTR, d):
+    iter = lltype.malloc(ITERPTR.TO)
+    iter.dict = d
+    iter.index = 0
+    return iter
+
+def ll_dictnext(iter, func, RETURNTYPE):
+    dict = iter.dict
+    if dict:
+        entries = dict.entries
+        index = iter.index
+        entries_len = len(entries)
+        while index < entries_len:
+            entry = entries[index]
+            index = index + 1
+            if entry.valid():
+                iter.index = index
+                if func is dum_items:
+                    r = lltype.malloc(RETURNTYPE.TO)
+                    r.item0 = recast(RETURNTYPE.TO.item0, entry.key)
+                    r.item1 = recast(RETURNTYPE.TO.item1, entry.value)
+                    return r
+                elif func is dum_keys:
+                    return entry.key
+                elif func is dum_values:
+                    return entry.value
+        # clear the reference to the dict and prevent restarts
+        iter.dict = lltype.nullptr(lltype.typeOf(iter).TO.dict.TO)
+    raise StopIteration
+
+# _____________________________________________________________
+# methods
+
+def ll_get(dict, key, default):
+    entry = ll_dict_lookup(dict, key, dict.keyhash(key))
+    if entry.valid():
+        return entry.value
+    else: 
+        return default
+
+def ll_setdefault(dict, key, default):
+    entry = ll_dict_lookup(dict, key, dict.keyhash(key))
+    if entry.valid():
+        return entry.value
+    else:
+        ll_dict_setitem(dict, key, default)
+        return default
+
+def ll_copy(dict):
+    DICT = lltype.typeOf(dict).TO
+    dictsize = len(dict.entries)
+    d = lltype.malloc(DICT)
+    d.entries = lltype.malloc(DICT.entries.TO, dictsize)
+    d.num_items = dict.num_items
+    d.num_pristine_entries = dict.num_pristine_entries
+    if hasattr(DICT, 'fnkeyeq'):   d.fnkeyeq   = dict.fnkeyeq
+    if hasattr(DICT, 'fnkeyhash'): d.fnkeyhash = dict.fnkeyhash
+    i = 0
+    while i < dictsize:
+        d_entry = d.entries[i]
+        entry = dict.entries[i]
+        ENTRY = lltype.typeOf(entry).TO
+        d_entry.key = entry.key
+        if hasattr(ENTRY, 'f_valid'):    d_entry.f_valid    = entry.f_valid
+        if hasattr(ENTRY, 'f_everused'): d_entry.f_everused = entry.f_everused
+        d_entry.value = entry.value
+        if hasattr(ENTRY, 'f_hash'):     d_entry.f_hash     = entry.f_hash
+        i += 1
+    return d
+
+def ll_clear(d):
+    if len(d.entries) == d.num_pristine_entries == DICT_INITSIZE:
+        return
+    DICT = lltype.typeOf(d).TO
+    d.entries = lltype.malloc(DICT.entries.TO, DICT_INITSIZE)
+    d.num_items = 0
+    d.num_pristine_entries = DICT_INITSIZE
+
+def ll_update(dic1, dic2):
+    entries = dic2.entries
+    d2len = len(entries)
+    i = 0
+    while i < d2len:
+        entry = entries[i]
+        if entry.valid():
+            ll_dict_setitem(dic1, entry.key, entry.value)
+        i += 1
+
+# this is an implementation of keys(), values() and items()
+# in a single function.
+# note that by specialization on func, three different
+# and very efficient functions are created.
+
+def recast(P, v):
+    if isinstance(P, lltype.Ptr):
+        return lltype.cast_pointer(P, v)
+    else:
+        return v
+
+def ll_kvi(dic, LIST, func):
+    res = LIST.ll_newlist(dic.num_items)
+    entries = dic.entries
+    dlen = len(entries)
+    items = res.ll_items()
+    i = 0
+    p = 0
+    while i < dlen:
+        entry = entries[i]
+        if entry.valid():
+            ELEM = lltype.typeOf(items).TO.OF
+            if func is dum_items:
+                r = lltype.malloc(ELEM.TO)
+                r.item0 = recast(ELEM.TO.item0, entry.key)
+                r.item1 = recast(ELEM.TO.item1, entry.value)
+                items[p] = r
+            elif func is dum_keys:
+                items[p] = recast(ELEM, entry.key)
+            elif func is dum_values:
+                items[p] = recast(ELEM, entry.value)
+            p += 1
+        i += 1
+    return res
+
+def ll_contains(d, key):
+    entry = ll_dict_lookup(d, key, d.keyhash(key))
+    return entry.valid()

Modified: pypy/dist/pypy/rpython/lltypesystem/rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rlist.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rlist.py	Fri Apr 21 00:17:24 2006
@@ -49,15 +49,6 @@
         self.listitem = listitem
         self.list_cache = {}
         # setup() needs to be called to finish this initialization
-##        self.ll_concat = ll_concat
-##        self.ll_extend = ll_extend
-##        self.ll_listslice_startonly = ll_listslice_startonly
-##        self.ll_listslice = ll_listslice
-##        self.ll_listslice_minusone = ll_listslice_minusone
-##        self.ll_listsetslice = ll_listsetslice
-##        self.ll_listdelslice_startonly = ll_listdelslice_startonly
-##        self.ll_listdelslice = ll_listdelslice
-##        self.ll_listindex = ll_listindex
         self.list_builder = ListBuilder()
 
     def _setup_repr_final(self):

Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Fri Apr 21 00:17:24 2006
@@ -181,8 +181,38 @@
         StaticMethod.__init__(self, args, result)
 
 
-class List(OOType):
-    # placeholders
+class BuiltinType(OOType):
+
+    def _setup_methods(self, generic_types):
+        methods = {}
+        for name, meth in self._GENERIC_METHODS.iteritems():
+            args = [generic_types.get(arg, arg) for arg in meth.ARGS]
+            result = generic_types.get(meth.RESULT, meth.RESULT)            
+            methods[name] = Meth(args, result)
+        self._METHODS = frozendict(methods)
+
+    def _lookup(self, meth_name):
+        METH = self._METHODS.get(meth_name)
+        meth = None
+        if METH is not None:
+            cls = self._get_interp_class()
+            meth = _meth(METH, _name=meth_name, _callable=getattr(cls, meth_name))
+        return self, meth
+
+    def _example(self):
+        return new(self)
+
+    def _defl(self):
+        return self._null
+
+    def _get_interp_class(self):
+        raise NotImplementedError
+
+
+class List(BuiltinType):
+    # placeholders for types
+    # make sure that each derived class has his own SELFTYPE_T
+    # placeholder, because we want backends to distinguish that.
     SELFTYPE_T = object()
     ITEMTYPE_T = object()
 
@@ -209,9 +239,6 @@
             "_ll_resize_ge": Meth([Signed], Void),
             "_ll_resize_le": Meth([Signed], Void),
             "_ll_resize": Meth([Signed], Void),
-##            "append": Meth([self.ITEMTYPE_T], Void),            
-##            "extend": Meth([self.SELFTYPE_T], Void),
-##            "remove_range": Meth([Signed, Signed], Void), # remove_range(start, count)
         })
 
         self._setup_methods(generic_types)
@@ -223,14 +250,6 @@
         lst._ll_resize_ge(length)
         return lst
 
-    def _setup_methods(self, generic_types):
-        methods = {}
-        for name, meth in self._GENERIC_METHODS.iteritems():
-            args = [generic_types.get(arg, arg) for arg in meth.ARGS]
-            result = generic_types.get(meth.RESULT, meth.RESULT)            
-            methods[name] = Meth(args, result)
-        self._METHODS = frozendict(methods)
-
     # NB: We are expecting Lists of the same ITEMTYPE to compare/hash
     # equal. We don't redefine __eq__/__hash__ since the implementations
     # from LowLevelType work fine, especially in the face of recursive
@@ -241,19 +260,48 @@
         return '%s(%s)' % (self.__class__.__name__,
                 saferecursive(str, "...")(self._ITEMTYPE))
 
-    def _lookup(self, meth_name):
-        METH = self._METHODS.get(meth_name)
-        meth = None
-        if METH is not None:
-            meth = _meth(METH, _name=meth_name,
-                    _callable=getattr(_list, meth_name))
-        return self, meth
+    def _get_interp_class(self):
+        return _list
 
-    def _example(self):
-        return new(self)
 
-    def _defl(self):
-        return self._null
+class Dict(BuiltinType):
+    # placeholders for types
+    SELFTYPE_T = object()
+    KEYTYPE_T = object()
+    VALUETYPE_T = object()
+
+    def __init__(self, KEYTYPE, VALUETYPE):
+        self._KEYTYPE = KEYTYPE
+        self._VALUETYPE = VALUETYPE
+        self._null = _null_dict(self)
+
+        generic_types = {
+            self.SELFTYPE_T: self,
+            self.KEYTYPE_T: KEYTYPE,
+            self.VALUETYPE_T: VALUETYPE
+            }
+
+        self._GENERIC_METHODS = frozendict({
+            "ll_length": Meth([], Signed),
+            "ll_getitem": Meth([self.KEYTYPE_T], self.VALUETYPE_T),
+            "ll_setitem": Meth([self.KEYTYPE_T, self.VALUETYPE_T], Void),
+        })
+
+        self._setup_methods(generic_types)
+
+    # NB: We are expecting Dicts of the same KEYTYPE, VALUETYPE to
+    # compare/hash equal. We don't redefine __eq__/__hash__ since the
+    # implementations from LowLevelType work fine, especially in the
+    # face of recursive data structures. But it is important to make
+    # sure that attributes of supposedly equal Dicts compare/hash
+    # equal.
+
+    def __str__(self):
+        return '%s(%s)' % (self.__class__.__name__,
+                saferecursive(str, "...")(self._KEYTYPE, self._VALUETYPE))
+
+    def _get_interp_class(self):
+        return _dict
 
 
 class ForwardReference(OOType):
@@ -523,13 +571,7 @@
        callb, checked_args = self.meth._checkargs(args)
        return callb(self.inst, *checked_args)
 
-
-class _list(object):
-
-    def __init__(self, LIST):
-        self._TYPE = LIST
-        self._list = []
-
+class _builtin_type(object):
     def __getattribute__(self, name):
         TYPE = object.__getattribute__(self, "_TYPE")
         _, meth = TYPE._lookup(name)
@@ -537,6 +579,13 @@
             return meth._bound(TYPE, self)
 
         return object.__getattribute__(self, name)
+    
+
+class _list(_builtin_type):
+
+    def __init__(self, LIST):
+        self._TYPE = LIST
+        self._list = []
 
     # The following are implementations of the abstract list interface for
     # use by the llinterpreter and ootype tests. There are NOT_RPYTHON
@@ -580,30 +629,40 @@
         assert index >= 0
         self._list[index] = item
 
-##    def append(self, item):
-##        # NOT_RPYTHON
-##        assert typeOf(item) == self._TYPE._ITEMTYPE
-##        self._list.append(item)
-
-##    def extend(self, other):
-##        # NOT_RPYTHON
-##        assert typeOf(other) == typeOf(self)
-##        self._list.extend(other._list)
-
-##    def remove_range(self, start, count):
-##        # NOT_RPYTHON        
-##        del self._list[start:start+count]
-
 class _null_list(_null_mixin(_list), _list):
 
     def __init__(self, LIST):
         self.__dict__["_TYPE"] = LIST 
 
+class _dict(object):
+    def __init__(self, DICT):
+        self._TYPE = DICT
+        self._dict = {}
+
+    def ll_length(self):
+        # NOT_RPYTHON
+        return len(self._dict)
+
+    def ll_getitem(self, key):
+        assert typeOf(key) == self._TYPE._KEYTYPE
+        return self._dict[key]
+
+    def ll_setitem(self, key, value):
+        assert typeOf(key) == self._TYPE._KEYTYPE
+        assert typeOf(value) == self._TYPE._VALUETYPE
+        self._dict[key] = value
+
+class _null_dict(_null_mixin(_dict), _dict):
+
+    def __init__(self, DICT):
+        self.__dict__["_TYPE"] = DICT
+
+
 def new(TYPE):
     if isinstance(TYPE, Instance):
         return make_instance(TYPE)
-    elif isinstance(TYPE, List):
-        return _list(TYPE)
+    elif isinstance(TYPE, BuiltinType):
+        return TYPE._get_interp_class()(TYPE)
 
 def runtimenew(class_):
     assert isinstance(class_, _class)

Added: pypy/dist/pypy/rpython/ootypesystem/rdict.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/ootypesystem/rdict.py	Fri Apr 21 00:17:24 2006
@@ -0,0 +1 @@
+# TODO

Modified: pypy/dist/pypy/rpython/ootypesystem/rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rlist.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rlist.py	Fri Apr 21 00:17:24 2006
@@ -25,15 +25,6 @@
         self.lowleveltype = self.LIST
         self.listitem = listitem
         self.list_cache = {}
-##        self.ll_concat = ll_concat
-##        self.ll_extend = ll_extend
-##        self.ll_listslice_startonly = ll_listslice_startonly
-##        self.ll_listslice = ll_listslice
-##        self.ll_listslice_minusone = ll_listslice_minusone
-##        self.ll_listsetslice = ll_listsetslice
-##        self.ll_listdelslice_startonly = ll_listdelslice_startonly
-##        self.ll_listdelslice = ll_listdelslice
-##        self.ll_listindex = ll_listindex
         # setup() needs to be called to finish this initialization
 
     def _setup_repr(self):

Added: pypy/dist/pypy/rpython/ootypesystem/test/test_oodict.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_oodict.py	Fri Apr 21 00:17:24 2006
@@ -0,0 +1,20 @@
+import py
+from pypy.rpython.test.test_llinterp import interpret 
+from pypy.rpython.ootypesystem.ootype import Signed, Float, Dict, new, typeOf
+
+def test_new():
+    DT = Dict(Signed, Float)
+    d = new(DT)
+    assert typeOf(d) == DT
+
+def test_length():
+    DT = Dict(Signed, Float)
+    d = new(DT)
+    d.ll_setitem(42, 123.45)
+    assert d.ll_length() == 1
+
+def test_setitem_getitem():
+    DT = Dict(Signed, Float)
+    d = new(DT)
+    d.ll_setitem(42, 123.45)
+    assert d.ll_getitem(42) == 123.45

Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_oolist.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_oolist.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_oolist.py	Fri Apr 21 00:17:24 2006
@@ -31,20 +31,6 @@
     lst._ll_resize_le(10)
     assert lst.ll_length() <= 10
 
-##def test_append():
-##    LT = List(Signed)
-##    l = new(LT)
-##    l.append(1)
-##    assert l.ll_length() == 1
-
-##def test_extend():
-##    LT = List(Signed)
-##    l1 = new(LT)
-##    l2 = new(LT)
-##    l1.append(1)
-##    l2.append(2)
-##    l1.extend(l2)
-##    assert l1.ll_length() == 2
 
 def test_setitem_getitem():
     LT = List(Signed)

Modified: pypy/dist/pypy/rpython/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/rbuiltin.py	(original)
+++ pypy/dist/pypy/rpython/rbuiltin.py	Fri Apr 21 00:17:24 2006
@@ -9,7 +9,7 @@
 from pypy.rpython import rstr
 from pypy.rpython import rptr
 from pypy.rpython.robject import pyobj_repr
-from pypy.rpython.rdict import rtype_r_dict
+from pypy.rpython.lltypesystem.rdict import rtype_r_dict # TODO: typesystem?
 from pypy.tool import sourcetools
 from pypy.rpython import extregistry
 

Modified: pypy/dist/pypy/rpython/rdict.py
==============================================================================
--- pypy/dist/pypy/rpython/rdict.py	(original)
+++ pypy/dist/pypy/rpython/rdict.py	Fri Apr 21 00:17:24 2006
@@ -6,33 +6,8 @@
 from pypy.rpython.objectmodel import hlinvoke
 from pypy.rpython import robject
 from pypy.rpython import objectmodel
-from pypy.rpython import rmodel
+from pypy.rpython.rmodel import Repr
 
-# ____________________________________________________________
-#
-#  generic implementation of RPython dictionary, with parametric DICTKEY and
-#  DICTVALUE types.
-#
-#  XXX for immutable dicts, the array should be inlined and
-#      num_pristine_entries and everused are not needed.
-#
-#    struct dictentry {
-#        DICTKEY key;
-#        bool f_valid;      # (optional) the entry is filled
-#        bool f_everused;   # (optional) the entry is or has ever been filled
-#        DICTVALUE value;
-#        int f_hash;        # (optional) key hash, if hard to recompute
-#    }
-#    
-#    struct dicttable {
-#        int num_items;
-#        int num_pristine_entries;  # never used entries
-#        Array *entries;
-#        (Function DICTKEY, DICTKEY -> bool) *fnkeyeq;
-#        (Function DICTKEY -> int) *fnkeyhash;
-#    }
-#
-#
 
 class __extend__(annmodel.SomeDict):
     def rtyper_makerepr(self, rtyper):
@@ -49,572 +24,21 @@
                                           rtyper.getrepr(dictkey.s_rdict_hashfn))
             else:
                 custom_eq_hash = None
-            return DictRepr(rtyper,
-                            lambda: rtyper.getrepr(s_key),
-                            lambda: rtyper.getrepr(s_value),
-                            dictkey,
-                            dictvalue,
-                            custom_eq_hash)
+            return rtyper.type_system.rdict.DictRepr(rtyper,
+                                                     lambda: rtyper.getrepr(s_key),
+                                                     lambda: rtyper.getrepr(s_value),
+                                                     dictkey,
+                                                     dictvalue,
+                                                     custom_eq_hash)
 
     def rtyper_makekey(self):
         return (self.__class__, self.dictdef.dictkey, self.dictdef.dictvalue)
 
 
-class DictRepr(rmodel.Repr):
 
-    def __init__(self, rtyper, key_repr, value_repr, dictkey, dictvalue,
-                 custom_eq_hash=None):
-        self.rtyper = rtyper
-        self.DICT = lltype.GcForwardReference()
-        self.lowleveltype = lltype.Ptr(self.DICT)
-        self.custom_eq_hash = custom_eq_hash is not None
-        if not isinstance(key_repr, rmodel.Repr):  # not computed yet, done by setup()
-            assert callable(key_repr)
-            self._key_repr_computer = key_repr 
-        else:
-            self.external_key_repr, self.key_repr = self.pickkeyrepr(key_repr)
-        if not isinstance(value_repr, rmodel.Repr):  # not computed yet, done by setup()
-            assert callable(value_repr)
-            self._value_repr_computer = value_repr 
-        else:
-            self.external_value_repr, self.value_repr = self.pickrepr(value_repr)
-        self.dictkey = dictkey
-        self.dictvalue = dictvalue
-        self.dict_cache = {}
-        self._custom_eq_hash_repr = custom_eq_hash
-        # setup() needs to be called to finish this initialization
-        
-    def pickrepr(self, item_repr):
-        if self.custom_eq_hash:
-            return item_repr, item_repr
-        else:
-            return rmodel.externalvsinternal(self.rtyper, item_repr)
-
-    def pickkeyrepr(self, key_repr):
-        external, internal = self.pickrepr(key_repr)
-        if external != internal:
-            internal = external
-            while not self.rtyper.needs_hash_support(internal.classdef):
-                internal = internal.rbase
-        return external, internal
-        
-    def compact_repr(self):
-        return 'DictR %s %s' % (self.key_repr.compact_repr(), self.value_repr.compact_repr())
-
-    def _setup_repr(self):
-        if 'key_repr' not in self.__dict__:
-            key_repr = self._key_repr_computer()
-            self.external_key_repr, self.key_repr = self.pickkeyrepr(key_repr)
-        if 'value_repr' not in self.__dict__:
-            self.external_value_repr, self.value_repr = self.pickrepr(self._value_repr_computer())
-        if isinstance(self.DICT, lltype.GcForwardReference):
-            self.DICTKEY = self.key_repr.lowleveltype
-            self.DICTVALUE = self.value_repr.lowleveltype
-
-            # compute the shape of the DICTENTRY structure
-            entryfields = []
-            entrymeths = {
-                'must_clear_key':   (isinstance(self.DICTKEY, lltype.Ptr)
-                                     and self.DICTKEY._needsgc()),
-                'must_clear_value': (isinstance(self.DICTVALUE, lltype.Ptr)
-                                     and self.DICTVALUE._needsgc()),
-                }
-
-            # * the key
-            entryfields.append(("key", self.DICTKEY))
-
-            # * if NULL is not a valid ll value for the key or the value
-            #   field of the entry, it can be used as a marker for
-            #   never-used entries.  Otherwise, we need an explicit flag.
-            s_key   = self.dictkey.s_value
-            s_value = self.dictvalue.s_value
-            nullkeymarker = not self.key_repr.can_ll_be_null(s_key)
-            nullvaluemarker = not self.value_repr.can_ll_be_null(s_value)
-
-            if nullkeymarker:
-                entrymeths['everused'] = ll_everused_from_key
-            elif nullvaluemarker:
-                entrymeths['everused'] = ll_everused_from_value
-            else:
-                entryfields.append(("f_everused", lltype.Bool))
-                entrymeths['everused'] = ll_everused_from_flag
-
-            # * if the key or the value can also contain a "dummy" non-null
-            #   marker, we use it for deleted entries.
-            rtyper = self.rtyper
-            dummy_obj = self.key_repr.get_ll_dummyval_obj(rtyper, s_key)
-            if dummy_obj:
-                entrymeths['dummy_obj'] = dummy_obj
-                entrymeths['valid'] = ll_valid_from_key
-                entrymeths['mark_deleted'] = ll_mark_deleted_in_key
-                # the key is overwritten by 'dummy' when the entry is deleted
-                entrymeths['must_clear_key'] = False
-            else:
-                dummy_obj = self.value_repr.get_ll_dummyval_obj(rtyper,
-                                                                s_value)
-                if dummy_obj:
-                    entrymeths['dummy_obj'] = dummy_obj
-                    entrymeths['valid'] = ll_valid_from_value
-                    entrymeths['mark_deleted'] = ll_mark_deleted_in_value
-                    # value is overwritten by 'dummy' when entry is deleted
-                    entrymeths['must_clear_value'] = False
-                else:
-                    entryfields.append(("f_valid", lltype.Bool))
-                    entrymeths['valid'] = ll_valid_from_flag
-                    entrymeths['mark_deleted'] = ll_mark_deleted_in_flag
-
-            # * the value
-            entryfields.append(("value", self.DICTVALUE))
-
-            # * the hash, if needed
-            if self.custom_eq_hash:
-                fasthashfn = None
-            else:
-                fasthashfn = self.key_repr.get_ll_fasthash_function()
-            if fasthashfn is None:
-                entryfields.append(("f_hash", lltype.Signed))
-                entrymeths['hash'] = ll_hash_from_cache
-            else:
-                entrymeths['hash'] = ll_hash_recomputed
-                entrymeths['fasthashfn'] = fasthashfn
-
-            # Build the lltype data structures
-            self.DICTENTRY = lltype.Struct("dictentry", adtmeths=entrymeths,
-                                           *entryfields)
-            self.DICTENTRYARRAY = lltype.GcArray(self.DICTENTRY)
-            fields =          [ ("num_items", lltype.Signed),
-                                ("num_pristine_entries", lltype.Signed), 
-                                ("entries", lltype.Ptr(self.DICTENTRYARRAY)) ]
-            if self.custom_eq_hash:
-                self.r_rdict_eqfn, self.r_rdict_hashfn = self._custom_eq_hash_repr()
-                fields.extend([ ("fnkeyeq", self.r_rdict_eqfn.lowleveltype),
-                                ("fnkeyhash", self.r_rdict_hashfn.lowleveltype) ])
-                adtmeths = {
-                    'keyhash':        ll_keyhash_custom,
-                    'keyeq':          ll_keyeq_custom,
-                    'r_rdict_eqfn':   self.r_rdict_eqfn,
-                    'r_rdict_hashfn': self.r_rdict_hashfn,
-                    'paranoia':       True,
-                    }
-            else:
-                # figure out which functions must be used to hash and compare
-                ll_keyhash = self.key_repr.get_ll_hash_function()
-                ll_keyeq = self.key_repr.get_ll_eq_function()  # can be None
-                ll_keyhash = lltype.staticAdtMethod(ll_keyhash)
-                if ll_keyeq is not None:
-                    ll_keyeq = lltype.staticAdtMethod(ll_keyeq)
-                adtmeths = {
-                    'keyhash':  ll_keyhash,
-                    'keyeq':    ll_keyeq,
-                    'paranoia': False,
-                    }
-            self.DICT.become(lltype.GcStruct("dicttable", adtmeths=adtmeths,
-                                             *fields))
-
-    def recast_value(self, llops, v):
-        return llops.convertvar(v, self.value_repr, self.external_value_repr)
-
-    def recast_key(self, llops, v):
-        return llops.convertvar(v, self.key_repr, self.external_key_repr)
-
-    def convert_const(self, dictobj):
-        # get object from bound dict methods
-        #dictobj = getattr(dictobj, '__self__', dictobj) 
-        if dictobj is None:
-            return lltype.nullptr(self.DICT)
-        if not isinstance(dictobj, (dict, objectmodel.r_dict)):
-            raise TyperError("expected a dict: %r" % (dictobj,))
-        try:
-            key = Constant(dictobj)
-            return self.dict_cache[key]
-        except KeyError:
-            self.setup()
-            l_dict = ll_newdict_size(self.DICT, len(dictobj))
-            self.dict_cache[key] = l_dict 
-            r_key = self.key_repr
-            r_value = self.value_repr
-            if isinstance(dictobj, objectmodel.r_dict):
-                if self.r_rdict_eqfn.lowleveltype != lltype.Void:
-                    l_fn = self.r_rdict_eqfn.convert_const(dictobj.key_eq)
-                    l_dict.fnkeyeq = l_fn
-                if self.r_rdict_hashfn.lowleveltype != lltype.Void:
-                    l_fn = self.r_rdict_hashfn.convert_const(dictobj.key_hash)
-                    l_dict.fnkeyhash = l_fn
-
-                for dictkeycontainer, dictvalue in dictobj._dict.items():
-                    llkey = r_key.convert_const(dictkeycontainer.key)
-                    llvalue = r_value.convert_const(dictvalue)
-                    ll_dict_insertclean(l_dict, llkey, llvalue,
-                                        dictkeycontainer.hash)
-                return l_dict
-
-            else:
-                for dictkey, dictvalue in dictobj.items():
-                    llkey = r_key.convert_const(dictkey)
-                    llvalue = r_value.convert_const(dictvalue)
-                    ll_dict_insertclean(l_dict, llkey, llvalue,
-                                        l_dict.keyhash(llkey))
-                return l_dict
-
-    def rtype_len(self, hop):
-        v_dict, = hop.inputargs(self)
-        return hop.gendirectcall(ll_dict_len, v_dict)
-
-    def rtype_is_true(self, hop):
-        v_dict, = hop.inputargs(self)
-        return hop.gendirectcall(ll_dict_is_true, v_dict)
-
-    def make_iterator_repr(self, *variant):
-        return DictIteratorRepr(self, *variant)
-
-    def rtype_method_get(self, hop):
-        v_dict, v_key, v_default = hop.inputargs(self, self.key_repr,
-                                                 self.value_repr)
-        hop.exception_cannot_occur()
-        v_res = hop.gendirectcall(ll_get, v_dict, v_key, v_default)
-        return self.recast_value(hop.llops, v_res)
-
-    def rtype_method_setdefault(self, hop):
-        v_dict, v_key, v_default = hop.inputargs(self, self.key_repr,
-                                                 self.value_repr)
-        hop.exception_cannot_occur()
-        v_res = hop.gendirectcall(ll_setdefault, v_dict, v_key, v_default)
-        return self.recast_value(hop.llops, v_res)
-    
-    def rtype_method_copy(self, hop):
-        v_dict, = hop.inputargs(self)
-        hop.exception_cannot_occur()
-        return hop.gendirectcall(ll_copy, v_dict)
-
-    def rtype_method_update(self, hop):
-        v_dic1, v_dic2 = hop.inputargs(self, self)
-        hop.exception_cannot_occur()
-        return hop.gendirectcall(ll_update, v_dic1, v_dic2)
-
-    def _rtype_method_kvi(self, hop, spec):
-        v_dic, = hop.inputargs(self)
-        r_list = hop.r_result
-        v_func = hop.inputconst(lltype.Void, spec)
-        cLIST = hop.inputconst(lltype.Void, r_list.lowleveltype.TO)
-        hop.exception_cannot_occur()
-        return hop.gendirectcall(ll_kvi, v_dic, cLIST, v_func)
-
-    def rtype_method_keys(self, hop):
-        return self._rtype_method_kvi(hop, dum_keys)
-
-    def rtype_method_values(self, hop):
-        return self._rtype_method_kvi(hop, dum_values)
-
-    def rtype_method_items(self, hop):
-        return self._rtype_method_kvi(hop, dum_items)
-
-    def rtype_method_iterkeys(self, hop):
-        hop.exception_cannot_occur()
-        return DictIteratorRepr(self, "keys").newiter(hop)
-
-    def rtype_method_itervalues(self, hop):
-        hop.exception_cannot_occur()
-        return DictIteratorRepr(self, "values").newiter(hop)
-
-    def rtype_method_iteritems(self, hop):
-        hop.exception_cannot_occur()
-        return DictIteratorRepr(self, "items").newiter(hop)
-
-    def rtype_method_clear(self, hop):
-        v_dict, = hop.inputargs(self)
-        hop.exception_cannot_occur()
-        return hop.gendirectcall(ll_clear, v_dict)
-
-class __extend__(pairtype(DictRepr, rmodel.Repr)): 
-
-    def rtype_getitem((r_dict, r_key), hop):
-        v_dict, v_key = hop.inputargs(r_dict, r_dict.key_repr)
-        if not r_dict.custom_eq_hash:
-            hop.has_implicit_exception(KeyError)   # record that we know about it
-        hop.exception_is_here()
-        v_res = hop.gendirectcall(ll_dict_getitem, v_dict, v_key)
-        return r_dict.recast_value(hop.llops, v_res)
-
-    def rtype_delitem((r_dict, r_key), hop):
-        v_dict, v_key = hop.inputargs(r_dict, r_dict.key_repr)
-        if not r_dict.custom_eq_hash:
-            hop.has_implicit_exception(KeyError)   # record that we know about it        
-        hop.exception_is_here()
-        return hop.gendirectcall(ll_dict_delitem, v_dict, v_key)
-
-    def rtype_setitem((r_dict, r_key), hop):
-        v_dict, v_key, v_value = hop.inputargs(r_dict, r_dict.key_repr, r_dict.value_repr)
-        if r_dict.custom_eq_hash:
-            hop.exception_is_here()
-        else:
-            hop.exception_cannot_occur()
-        hop.gendirectcall(ll_dict_setitem, v_dict, v_key, v_value)
-
-    def rtype_contains((r_dict, r_key), hop):
-        v_dict, v_key = hop.inputargs(r_dict, r_dict.key_repr)
-        return hop.gendirectcall(ll_contains, v_dict, v_key)
-        
-class __extend__(pairtype(DictRepr, DictRepr)):
-    def convert_from_to((r_dict1, r_dict2), v, llops):
-        # check that we don't convert from Dicts with
-        # different key/value types 
-        if r_dict1.dictkey is None or r_dict2.dictkey is None:
-            return NotImplemented
-        if r_dict1.dictkey is not r_dict2.dictkey:
-            return NotImplemented
-        if r_dict1.dictvalue is None or r_dict2.dictvalue is None:
-            return NotImplemented
-        if r_dict1.dictvalue is not r_dict2.dictvalue:
-            return NotImplemented
-        return v
-
-# ____________________________________________________________
-#
-#  Low-level methods.  These can be run for testing, but are meant to
-#  be direct_call'ed from rtyped flow graphs, which means that they will
-#  get flowed and annotated, mostly with SomePtr.
-
-def ll_everused_from_flag(entry):
-    return entry.f_everused
-
-def ll_everused_from_key(entry):
-    return bool(entry.key)
-
-def ll_everused_from_value(entry):
-    return bool(entry.value)
+class AbstractDictRepr(Repr):
+    pass
 
-def ll_valid_from_flag(entry):
-    return entry.f_valid
-
-def ll_mark_deleted_in_flag(entry):
-    entry.f_valid = False
-
-def ll_valid_from_key(entry):
-    ENTRY = lltype.typeOf(entry).TO
-    dummy = ENTRY.dummy_obj.ll_dummy_value
-    return entry.everused() and entry.key != dummy
-
-def ll_mark_deleted_in_key(entry):
-    ENTRY = lltype.typeOf(entry).TO
-    dummy = ENTRY.dummy_obj.ll_dummy_value
-    entry.key = dummy
-
-def ll_valid_from_value(entry):
-    ENTRY = lltype.typeOf(entry).TO
-    dummy = ENTRY.dummy_obj.ll_dummy_value
-    return entry.everused() and entry.value != dummy
-
-def ll_mark_deleted_in_value(entry):
-    ENTRY = lltype.typeOf(entry).TO
-    dummy = ENTRY.dummy_obj.ll_dummy_value
-    entry.value = dummy
-
-def ll_hash_from_cache(entry):
-    return entry.f_hash
-
-def ll_hash_recomputed(entry):
-    ENTRY = lltype.typeOf(entry).TO
-    return ENTRY.fasthashfn(entry.key)
-
-def ll_keyhash_custom(d, key):
-    DICT = lltype.typeOf(d).TO
-    return hlinvoke(DICT.r_rdict_hashfn, d.fnkeyhash, key)
-
-def ll_keyeq_custom(d, key1, key2):
-    DICT = lltype.typeOf(d).TO
-    return hlinvoke(DICT.r_rdict_eqfn, d.fnkeyeq, key1, key2)
-
-def dum_keys(): pass
-def dum_values(): pass
-def dum_items():pass
-dum_variant = {"keys":   dum_keys,
-               "values": dum_values,
-               "items":  dum_items}
-
-def ll_dict_len(d):
-    return d.num_items 
-
-def ll_dict_is_true(d):
-    # check if a dict is True, allowing for None
-    return bool(d) and d.num_items != 0
-
-def ll_dict_getitem(d, key):
-    entry = ll_dict_lookup(d, key, d.keyhash(key))
-    if entry.valid():
-        return entry.value 
-    else: 
-        raise KeyError 
-
-def ll_dict_setitem(d, key, value):
-    hash = d.keyhash(key)
-    entry = ll_dict_lookup(d, key, hash)
-    everused = entry.everused()
-    valid    = entry.valid()
-    # set up the new entry
-    ENTRY = lltype.typeOf(entry).TO
-    entry.value = value
-    if valid:
-        return
-    entry.key = key
-    if hasattr(ENTRY, 'f_hash'):  entry.f_hash = hash
-    if hasattr(ENTRY, 'f_valid'): entry.f_valid = True
-    d.num_items += 1
-    if not everused:
-        if hasattr(ENTRY, 'f_everused'): entry.f_everused = True
-        d.num_pristine_entries -= 1
-        if d.num_pristine_entries <= len(d.entries) / 3:
-            ll_dict_resize(d)
-
-def ll_dict_insertclean(d, key, value, hash):
-    # Internal routine used by ll_dict_resize() to insert an item which is
-    # known to be absent from the dict.  This routine also assumes that
-    # the dict contains no deleted entries.  This routine has the advantage
-    # of never calling d.keyhash() and d.keyeq(), so it cannot call back
-    # to user code.  ll_dict_insertclean() doesn't resize the dict, either.
-    entry = ll_dict_lookup_clean(d, hash)
-    ENTRY = lltype.typeOf(entry).TO
-    entry.value = value
-    entry.key = key
-    if hasattr(ENTRY, 'f_hash'):     entry.f_hash = hash
-    if hasattr(ENTRY, 'f_valid'):    entry.f_valid = True
-    if hasattr(ENTRY, 'f_everused'): entry.f_everused = True
-    d.num_items += 1
-    d.num_pristine_entries -= 1
-
-def ll_dict_delitem(d, key):
-    entry = ll_dict_lookup(d, key, d.keyhash(key))
-    if not entry.valid():
-        raise KeyError
-    entry.mark_deleted()
-    d.num_items -= 1
-    # clear the key and the value if they are GC pointers
-    ENTRY = lltype.typeOf(entry).TO
-    if ENTRY.must_clear_key:
-        key = entry.key   # careful about destructor side effects:
-                          # keep key alive until entry.value has also
-                          # been zeroed (if it must be)
-        entry.key = lltype.nullptr(ENTRY.key.TO)
-    if ENTRY.must_clear_value:
-        entry.value = lltype.nullptr(ENTRY.value.TO)
-    num_entries = len(d.entries)
-    if num_entries > DICT_INITSIZE and d.num_items < num_entries / 4:
-        ll_dict_resize(d)
-
-def ll_dict_resize(d):
-    old_entries = d.entries
-    old_size = len(old_entries) 
-    # make a 'new_size' estimate and shrink it if there are many
-    # deleted entry markers
-    new_size = old_size * 2
-    while new_size > DICT_INITSIZE and d.num_items < new_size / 4:
-        new_size /= 2
-    d.entries = lltype.malloc(lltype.typeOf(old_entries).TO, new_size)
-    d.num_items = 0
-    d.num_pristine_entries = new_size
-    i = 0
-    while i < old_size:
-        entry = old_entries[i]
-        if entry.valid():
-            ll_dict_insertclean(d, entry.key, entry.value, entry.hash())
-        i += 1
-
-# ------- a port of CPython's dictobject.c's lookdict implementation -------
-PERTURB_SHIFT = 5
-
-def ll_dict_lookup(d, key, hash):
-    DICT = lltype.typeOf(d).TO
-    entries = d.entries
-    mask = len(entries) - 1
-    i = r_uint(hash & mask) 
-    # do the first try before any looping 
-    entry = entries[i]
-    if entry.valid():
-        checkingkey = entry.key
-        if checkingkey == key:
-            return entry   # found the entry
-        if d.keyeq is not None and entry.hash() == hash:
-            # correct hash, maybe the key is e.g. a different pointer to
-            # an equal object
-            found = d.keyeq(checkingkey, key)
-            if DICT.paranoia:
-                if (entries != d.entries or
-                    not entry.valid() or entry.key != checkingkey):
-                    # the compare did major nasty stuff to the dict: start over
-                    return ll_dict_lookup(d, key, hash)
-            if found:
-                return entry   # found the entry
-        freeslot = lltype.nullptr(lltype.typeOf(entry).TO)
-    elif entry.everused():
-        freeslot = entry
-    else:
-        return entry    # pristine entry -- lookup failed
-
-    # In the loop, a deleted entry (everused and not valid) is by far
-    # (factor of 100s) the least likely outcome, so test for that last.
-    perturb = r_uint(hash) 
-    while 1: 
-        i = ((i << 2) + i + perturb + 1) & mask
-        entry = entries[i]
-        if not entry.everused():
-            return freeslot or entry 
-        elif entry.valid():
-            checkingkey = entry.key
-            if checkingkey == key:
-                return entry
-            if d.keyeq is not None and entry.hash() == hash:
-                # correct hash, maybe the key is e.g. a different pointer to
-                # an equal object
-                found = d.keyeq(checkingkey, key)
-                if DICT.paranoia:
-                    if (entries != d.entries or
-                        not entry.valid() or entry.key != checkingkey):
-                        # the compare did major nasty stuff to the dict:
-                        # start over
-                        return ll_dict_lookup(d, key, hash)
-                if found:
-                    return entry   # found the entry
-        elif not freeslot:
-            freeslot = entry 
-        perturb >>= PERTURB_SHIFT
-
-def ll_dict_lookup_clean(d, hash):
-    # a simplified version of ll_dict_lookup() which assumes that the
-    # key is new, and the dictionary doesn't contain deleted entries.
-    # It only find the next free slot for the given hash.
-    entries = d.entries
-    mask = len(entries) - 1
-    i = r_uint(hash & mask) 
-    entry = entries[i]
-    perturb = r_uint(hash) 
-    while entry.everused():
-        i = ((i << 2) + i + perturb + 1) & mask
-        entry = entries[i]
-        perturb >>= PERTURB_SHIFT
-    return entry
-
-# ____________________________________________________________
-#
-#  Irregular operations.
-
-DICT_INITSIZE = 8
-
-def ll_newdict(DICT):
-    d = lltype.malloc(DICT)
-    d.entries = lltype.malloc(DICT.entries.TO, DICT_INITSIZE)
-    #d.num_items = 0    -- defaults
-    d.num_pristine_entries = DICT_INITSIZE
-    return d
-
-def ll_newdict_size(DICT, length_estimate):
-    length_estimate = (length_estimate // 2) * 3
-    n = DICT_INITSIZE
-    while n < length_estimate:
-        n *= 2
-    d = lltype.malloc(DICT)
-    d.entries = lltype.malloc(DICT.entries.TO, n)
-    #d.num_items = 0    -- defaults
-    d.num_pristine_entries = DICT_INITSIZE
-    return d
 
 def rtype_newdict(hop):
     hop.inputargs()    # no arguments expected
@@ -623,185 +47,5 @@
         cdict = hop.inputconst(robject.pyobj_repr, dict)
         return hop.genop('simple_call', [cdict], resulttype = robject.pyobj_repr)
     cDICT = hop.inputconst(lltype.Void, r_dict.DICT)
-    v_result = hop.gendirectcall(ll_newdict, cDICT)
-    return v_result
-
-def rtype_r_dict(hop):
-    r_dict = hop.r_result
-    if not r_dict.custom_eq_hash:
-        raise TyperError("r_dict() call does not return an r_dict instance")
-    v_eqfn, v_hashfn = hop.inputargs(r_dict.r_rdict_eqfn,
-                                     r_dict.r_rdict_hashfn)
-    cDICT = hop.inputconst(lltype.Void, r_dict.DICT)
-    hop.exception_cannot_occur()
-    v_result = hop.gendirectcall(ll_newdict, cDICT)
-    if r_dict.r_rdict_eqfn.lowleveltype != lltype.Void:
-        cname = hop.inputconst(lltype.Void, 'fnkeyeq')
-        hop.genop('setfield', [v_result, cname, v_eqfn])
-    if r_dict.r_rdict_hashfn.lowleveltype != lltype.Void:
-        cname = hop.inputconst(lltype.Void, 'fnkeyhash')
-        hop.genop('setfield', [v_result, cname, v_hashfn])
+    v_result = hop.gendirectcall(hop.rtyper.type_system.rdict.ll_newdict, cDICT)
     return v_result
-
-# ____________________________________________________________
-#
-#  Iteration.
-
-class DictIteratorRepr(rmodel.IteratorRepr):
-
-    def __init__(self, r_dict, variant="keys"):
-        self.r_dict = r_dict
-        self.variant = variant
-        self.lowleveltype = lltype.Ptr(lltype.GcStruct('dictiter',
-                                         ('dict', r_dict.lowleveltype),
-                                         ('index', lltype.Signed)))
-
-    def newiter(self, hop):
-        v_dict, = hop.inputargs(self.r_dict)
-        citerptr = hop.inputconst(lltype.Void, self.lowleveltype)
-        return hop.gendirectcall(ll_dictiter, citerptr, v_dict)
-
-    def rtype_next(self, hop):
-        variant = self.variant
-        v_iter, = hop.inputargs(self)
-        v_func = hop.inputconst(lltype.Void, dum_variant[self.variant])
-        if variant in ('keys', 'values'):
-            c1 = hop.inputconst(lltype.Void, None)
-        else:
-            c1 = hop.inputconst(lltype.Void, hop.r_result.lowleveltype)
-        hop.has_implicit_exception(StopIteration) # record that we know about it
-        hop.exception_is_here()
-        v = hop.gendirectcall(ll_dictnext, v_iter, v_func, c1)
-        if variant == 'keys':
-            return self.r_dict.recast_key(hop.llops, v)
-        elif variant == 'values':
-            return self.r_dict.recast_value(hop.llops, v)
-        else:
-            return v
-
-def ll_dictiter(ITERPTR, d):
-    iter = lltype.malloc(ITERPTR.TO)
-    iter.dict = d
-    iter.index = 0
-    return iter
-
-def ll_dictnext(iter, func, RETURNTYPE):
-    dict = iter.dict
-    if dict:
-        entries = dict.entries
-        index = iter.index
-        entries_len = len(entries)
-        while index < entries_len:
-            entry = entries[index]
-            index = index + 1
-            if entry.valid():
-                iter.index = index
-                if func is dum_items:
-                    r = lltype.malloc(RETURNTYPE.TO)
-                    r.item0 = recast(RETURNTYPE.TO.item0, entry.key)
-                    r.item1 = recast(RETURNTYPE.TO.item1, entry.value)
-                    return r
-                elif func is dum_keys:
-                    return entry.key
-                elif func is dum_values:
-                    return entry.value
-        # clear the reference to the dict and prevent restarts
-        iter.dict = lltype.nullptr(lltype.typeOf(iter).TO.dict.TO)
-    raise StopIteration
-
-# _____________________________________________________________
-# methods
-
-def ll_get(dict, key, default):
-    entry = ll_dict_lookup(dict, key, dict.keyhash(key))
-    if entry.valid():
-        return entry.value
-    else: 
-        return default
-
-def ll_setdefault(dict, key, default):
-    entry = ll_dict_lookup(dict, key, dict.keyhash(key))
-    if entry.valid():
-        return entry.value
-    else:
-        ll_dict_setitem(dict, key, default)
-        return default
-
-def ll_copy(dict):
-    DICT = lltype.typeOf(dict).TO
-    dictsize = len(dict.entries)
-    d = lltype.malloc(DICT)
-    d.entries = lltype.malloc(DICT.entries.TO, dictsize)
-    d.num_items = dict.num_items
-    d.num_pristine_entries = dict.num_pristine_entries
-    if hasattr(DICT, 'fnkeyeq'):   d.fnkeyeq   = dict.fnkeyeq
-    if hasattr(DICT, 'fnkeyhash'): d.fnkeyhash = dict.fnkeyhash
-    i = 0
-    while i < dictsize:
-        d_entry = d.entries[i]
-        entry = dict.entries[i]
-        ENTRY = lltype.typeOf(entry).TO
-        d_entry.key = entry.key
-        if hasattr(ENTRY, 'f_valid'):    d_entry.f_valid    = entry.f_valid
-        if hasattr(ENTRY, 'f_everused'): d_entry.f_everused = entry.f_everused
-        d_entry.value = entry.value
-        if hasattr(ENTRY, 'f_hash'):     d_entry.f_hash     = entry.f_hash
-        i += 1
-    return d
-
-def ll_clear(d):
-    if len(d.entries) == d.num_pristine_entries == DICT_INITSIZE:
-        return
-    DICT = lltype.typeOf(d).TO
-    d.entries = lltype.malloc(DICT.entries.TO, DICT_INITSIZE)
-    d.num_items = 0
-    d.num_pristine_entries = DICT_INITSIZE
-
-def ll_update(dic1, dic2):
-    entries = dic2.entries
-    d2len = len(entries)
-    i = 0
-    while i < d2len:
-        entry = entries[i]
-        if entry.valid():
-            ll_dict_setitem(dic1, entry.key, entry.value)
-        i += 1
-
-# this is an implementation of keys(), values() and items()
-# in a single function.
-# note that by specialization on func, three different
-# and very efficient functions are created.
-
-def recast(P, v):
-    if isinstance(P, lltype.Ptr):
-        return lltype.cast_pointer(P, v)
-    else:
-        return v
-
-def ll_kvi(dic, LIST, func):
-    res = LIST.ll_newlist(dic.num_items)
-    entries = dic.entries
-    dlen = len(entries)
-    items = res.ll_items()
-    i = 0
-    p = 0
-    while i < dlen:
-        entry = entries[i]
-        if entry.valid():
-            ELEM = lltype.typeOf(items).TO.OF
-            if func is dum_items:
-                r = lltype.malloc(ELEM.TO)
-                r.item0 = recast(ELEM.TO.item0, entry.key)
-                r.item1 = recast(ELEM.TO.item1, entry.value)
-                items[p] = r
-            elif func is dum_keys:
-                items[p] = recast(ELEM, entry.key)
-            elif func is dum_values:
-                items[p] = recast(ELEM, entry.value)
-            p += 1
-        i += 1
-    return res
-
-def ll_contains(d, key):
-    entry = ll_dict_lookup(d, key, d.keyhash(key))
-    return entry.valid()

Modified: pypy/dist/pypy/rpython/rtyper.py
==============================================================================
--- pypy/dist/pypy/rpython/rtyper.py	(original)
+++ pypy/dist/pypy/rpython/rtyper.py	Fri Apr 21 00:17:24 2006
@@ -522,7 +522,7 @@
         return self.type_system.rlist.rtype_newlist(hop)
 
     def translate_op_newdict(self, hop):
-        return rdict.rtype_newdict(hop)
+        return self.type_system.rdict.rtype_newdict(hop)
 
     def translate_op_alloc_and_set(self, hop):
         return self.type_system.rlist.rtype_alloc_and_set(hop)
@@ -860,7 +860,7 @@
 from pypy.rpython import robject
 from pypy.rpython import rint, rbool, rfloat
 from pypy.rpython import rslice, rrange
-from pypy.rpython import rstr, rdict 
+from pypy.rpython import rstr, rdict
 from pypy.rpython import rclass, rbuiltin, rpbc, rspecialcase
 from pypy.rpython import rexternalobj
 from pypy.rpython import rptr

Modified: pypy/dist/pypy/rpython/test/test_rdict.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rdict.py	(original)
+++ pypy/dist/pypy/rpython/test/test_rdict.py	Fri Apr 21 00:17:24 2006
@@ -1,7 +1,8 @@
 from pypy.translator.translator import TranslationContext
 from pypy.rpython.lltypesystem import lltype 
 from pypy.rpython.test.test_llinterp import interpret 
-from pypy.rpython import rstr, rint, rdict
+from pypy.rpython import rstr, rint
+from pypy.rpython.lltypesystem import rdict
 
 import py
 py.log.setconsumer("rtyper", py.log.STDOUT)

Modified: pypy/dist/pypy/rpython/typesystem.py
==============================================================================
--- pypy/dist/pypy/rpython/typesystem.py	(original)
+++ pypy/dist/pypy/rpython/typesystem.py	Fri Apr 21 00:17:24 2006
@@ -20,7 +20,7 @@
                                   None, None, ['__doc__'])
             except ImportError:
                 return None
-        if name in ('rclass', 'rpbc', 'rbuiltin', 'rtuple', 'rlist', 'rslice',
+        if name in ('rclass', 'rpbc', 'rbuiltin', 'rtuple', 'rlist', 'rslice', 'rdict',
                 'exceptiondata'):
             mod = load(name)
             if mod is not None:



More information about the Pypy-commit mailing list