Commits

Andrei Homescu committed 3cdecd1

Changed happy_hash dictionary keys to instances of HashTableKey class, to make type inference happy later

  • Participants
  • Parent commits bff1960
  • Branches rewrite

Comments (0)

Files changed (1)

 
-from pypy.rlib.objectmodel import r_dict
+from pypy.rlib.objectmodel import r_dict, compute_hash
 
 import functools
 from objects import *
 
 class HashTableKey:
-    def __init__(self):
-        pass
+    pass
 
 class HashTableStringKey(HashTableKey):
     def __init__(self, strval):
-        HashTableKey.__init__(self)
         self.strval = strval
 
+    def get_hash(self):
+        return compute_hash(self.strval)
+
 class HashTableIntKey(HashTableKey):
     def __init__(self, intval):
-        HashTableKey.__init__(self)
         self.intval = intval
 
+    def get_hash(self):
+        return compute_hash(self.intval)
+
 class Bucket:
     def __init__(self, h):
         self.h = h
 FAILURE = -1
 SUCCESS = 0
 
+def _ht_key_eq(key1, key2):
+    if (isinstance(key1, HashTableIntKey) and
+            isinstance(key2, HashTableIntKey)):
+        return key1.intval == key2.intval
+    if (isinstance(key1, HashTableStringKey) and
+            isinstance(key2, HashTableStringKey)):
+        return key1.strval == key2.strval
+    return False
+
+def _ht_key_hash(key):
+    return key.get_hash()
+
 class HashTable:
     def __init__(self, pDestructor, persistent, bApplyProtection):
         self.pDestructor = pDestructor
             self.dict[next_key] = prev_data, prev_key, next_next_key
 
     def reset(self):
-        # TODO: use r_dict
-        self.dict = {}
+        self.dict = r_dict(_ht_key_eq, _ht_key_hash)
         self.first_key = None
         self.last_key = None
         self.next_free = 0
     if nKeyLength <= 0:
         return FAILURE
     is_add = flag is _HASH_ADD
-    if arKey in ht.dict:
+    key = HashTableStringKey(arKey)
+    if key in ht.dict:
         if is_add:
             return FAILURE
-        ht.update(arKey, pData)
+        ht.update(key, pData)
         if not pDest.is_null():
             pDest.assign(pData)
         return SUCCESS
-    ht.add(arKey, pData)
+    ht.add(key, pData)
     if not pDest.is_null():
         pDest.assign(pData)
     return SUCCESS
 def _zend_hash_index_update_or_next_insert(ht, h, pData, nDataSize, pDest, flag):
     if flag & _HASH_NEXT_INSERT:
         h = ht.next_free
-    if h in ht.dict:
+    key = HashTableIntKey(h)
+    if key in ht.dict:
         if (flag & _HASH_NEXT_INSERT) or (flag & _HASH_ADD):
             return FAILURE
 
-        ht.update(h, pData)
+        ht.update(key, pData)
         if h >= ht.next_free:
             # TODO: clamp at LONG_MAX
             ht.next_free = h + 1
             pDest.assign(pData)
         return SUCCESS
 
-    ht.add(h, pData)
+    ht.add(key, pData)
     if h >= ht.next_free:
         # TODO: clamp at LONG_MAX
         ht.next_free = h + 1
     return zend_hash_add(ht, arKey, nKeyLength, None, 0, None)
 
 def zend_hash_graceful_destroy(ht):
+    # TODO: later
     pass
 
 def zend_hash_graceful_reverse_destroy(ht):
+    # TODO: later
     pass
 
 ZEND_HASH_APPLY_KEEP   = 0
 HASH_DEL_KEY_QUICK = 2
 
 def zend_hash_del_key_or_index(ht, arKey, nKeyLength, h, flag):
-    key = h if nKeyLength is 0 else arKey
+    key = HashTableIntKey(h) if nKeyLength is 0 else HashTableStringKey(arKey)
     if key not in ht.dict:
         return FAILURE
     ht.delete(key)
     pass
 
 def zend_hash_find(ht, arKey, nKeyLength, pData):
-    if arKey not in ht.dict:
+    key = HashTableStringKey(arKey)
+    if key not in ht.dict:
         return FAILURE
     if not pData.is_null():
-        data, _, _ = ht.dict[arKey]
+        data, _, _ = ht.dict[key]
         pData.assign(data)
     return SUCCESS
 
     return zend_hash_find(ht, arKey, nKeyLength, pData)
 
 def zend_hash_index_find(ht, h, pData):
-    if h not in ht.dict:
+    key = HashTableIntKey(h)
+    if key not in ht.dict:
         return FAILURE
     if not pData.is_null():
-        data, _, _ = ht.dict[h]
+        data, _, _ = ht.dict[key]
         pData.assign(data)
     return SUCCESS
 
 def zend_hash_exists(ht, arKey, nKeyLength):
-    return arKey in ht.dict
+    return HashTableStringKey(arKey) in ht.dict
 
 def zend_hash_quick_exists(ht, arKey, nKeyLength, h):
-    if nKeyLength is 0:
-        return h in ht.dict
-    return arKey in ht.dict
+    key = HashTableIntKey(h) if nKeyLength is 0 else HashTableStringKey(arKey)
+    return key in ht.dict
 
 def zend_hash_index_exists(ht, h):
-    return h in ht.dict
+    return HashTableIntKey(h) in ht.dict
 
 def zend_hash_next_free_element(ht):
     return ht.next_free