Author: Armin Rigo <[email protected]>
Branch: keys_with_hash
Changeset: r79326:d81cb45a927e
Date: 2015-08-31 17:13 +0200
http://bitbucket.org/pypy/pypy/changeset/d81cb45a927e/
Log: iterkeys_with_hash()
diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py
--- a/rpython/annotator/unaryop.py
+++ b/rpython/annotator/unaryop.py
@@ -11,7 +11,7 @@
SomeString, SomeChar, SomeList, SomeDict, SomeTuple, SomeImpossibleValue,
SomeUnicodeCodePoint, SomeInstance, SomeBuiltin, SomeBuiltinMethod,
SomeFloat, SomeIterator, SomePBC, SomeNone, SomeType, s_ImpossibleValue,
- s_Bool, s_None, unionof, add_knowntypedata,
+ s_Bool, s_None, s_Int, unionof, add_knowntypedata,
HarmlesslyBlocked, SomeWeakRef, SomeUnicodeString, SomeByteArray)
from rpython.annotator.bookkeeper import getbookkeeper, immutablevalue
from rpython.annotator import builtin
@@ -409,6 +409,8 @@
return s_ImpossibleValue
else:
return SomeTuple((s_key, s_value))
+ if variant == 'keys_with_hash':
+ return SomeTuple((self.dictdef.read_key(), s_Int))
else:
raise ValueError
diff --git a/rpython/rlib/objectmodel.py b/rpython/rlib/objectmodel.py
--- a/rpython/rlib/objectmodel.py
+++ b/rpython/rlib/objectmodel.py
@@ -788,6 +788,27 @@
d = d.keys()
return reversed(d)
+def iterkeys_with_hash(d):
+ """Iterates (key, hash) pairs without recomputing the hash."""
+ assert not we_are_translated() # this code is only before translation
+ for k in d:
+ yield k, compute_hash(k)
+
+class Entry(ExtRegistryEntry):
+ _about_ = iterkeys_with_hash
+
+ def compute_result_annotation(self, s_d):
+ from rpython.annotator.model import SomeDict, SomeIterator, s_None
+ if isinstance(s_d, SomeDict):
+ return SomeIterator(s_d, 'keys_with_hash')
+ if s_None.contains(s_d):
+ return None
+ raise Exception("iterkeys_with_hash(x): x not a dict")
+
+ def specialize_call(self, hop):
+ from rpython.rtyper.lltypesystem.rdict import DictIteratorRepr
+ hop.exception_cannot_occur()
+ return DictIteratorRepr(hop.args_r[0], "keys_with_hash").newiter(hop)
# ____________________________________________________________
diff --git a/rpython/rlib/test/test_objectmodel.py
b/rpython/rlib/test/test_objectmodel.py
--- a/rpython/rlib/test/test_objectmodel.py
+++ b/rpython/rlib/test/test_objectmodel.py
@@ -592,6 +592,22 @@
r = interpret(f, [29])
assert r == 1
+def test_iterkeys_with_hash():
+ def f(i):
+ d = {i+.0: 5, i+.5: 6}
+ total = 0
+ for k, h in iterkeys_with_hash(d):
+ print k, h
+ print compute_hash(k)
+ total += k * h
+ total -= (i + 0.0) * compute_hash(i + 0.0)
+ total -= (i + 0.5) * compute_hash(i + 0.5)
+ return total
+
+ assert f(29) == 0.0
+ r = interpret(f, [29])
+ assert r == 0.0
+
def test_import_from_mixin():
class M: # old-style
def f(self): pass
diff --git a/rpython/rtyper/rdict.py b/rpython/rtyper/rdict.py
--- a/rpython/rtyper/rdict.py
+++ b/rpython/rtyper/rdict.py
@@ -79,7 +79,8 @@
hop.has_implicit_exception(RuntimeError)
hop.exception_is_here()
v_index = hop.gendirectcall(self._ll_dictnext, v_iter)
- if variant == 'items' and hop.r_result.lowleveltype != lltype.Void:
+ if ((variant == 'items' and hop.r_result.lowleveltype != lltype.Void)
or
+ variant == 'keys_with_hash'):
# this allocates the tuple for the result, directly in the function
# where it will be used (likely). This will let it be removed.
c1 = hop.inputconst(lltype.Void, hop.r_result.lowleveltype.TO)
@@ -98,11 +99,14 @@
c_key = hop.inputconst(lltype.Void, 'key')
v_key = hop.genop('getinteriorfield', [v_entries, v_index, c_key],
resulttype=KEY)
- if variant != 'keys' and variant != 'reversed':
+ if variant == 'values' or variant == 'items':
VALUE = ENTRIES.TO.OF.value
c_value = hop.inputconst(lltype.Void, 'value')
v_value = hop.genop('getinteriorfield',
[v_entries,v_index,c_value],
resulttype=VALUE)
+ elif variant == 'keys_with_hash':
+ v_value = hop.gendirectcall(ENTRIES.TO.hash, v_entries, v_index)
+ #
if variant == 'keys' or variant == 'reversed':
return self.r_dict.recast_key(hop.llops, v_key)
elif variant == 'values':
@@ -110,7 +114,7 @@
elif hop.r_result.lowleveltype == lltype.Void:
return hop.inputconst(lltype.Void, None)
else:
- assert variant == 'items'
+ assert variant == 'items' or variant == 'keys_with_hash'
ITEM0 = v_result.concretetype.TO.item0
ITEM1 = v_result.concretetype.TO.item1
if ITEM0 != v_key.concretetype:
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit