[pypy-svn] r26266 - in pypy/dist/pypy/rpython: . lltypesystem ootypesystem ootypesystem/test test
antocuni at codespeak.net
antocuni at codespeak.net
Mon Apr 24 16:31:50 CEST 2006
Author: antocuni
Date: Mon Apr 24 16:31:40 2006
New Revision: 26266
Modified:
pypy/dist/pypy/rpython/lltypesystem/rdict.py
pypy/dist/pypy/rpython/ootypesystem/ootype.py
pypy/dist/pypy/rpython/ootypesystem/rdict.py
pypy/dist/pypy/rpython/ootypesystem/test/test_oodict.py
pypy/dist/pypy/rpython/rdict.py
pypy/dist/pypy/rpython/test/test_rdict.py
Log:
- The signature of ootype.Dict.ll_get has been changed
- some code has been factored out from lltypesystem.rlist.DictIteratorRepr
to rlist.AbstractDictIteratorRepr
- added support for iteration and iter* methods to ootypesystem.rdict.
The current implementation of itervalues() and iteritems() is far from
optimal because it does a dict lookup at every iteration. Probabily we
will need a refactoring to get rid of this.
Modified: pypy/dist/pypy/rpython/lltypesystem/rdict.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rdict.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/rdict.py Mon Apr 24 16:31:40 2006
@@ -1,7 +1,8 @@
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.rdict import AbstractDictRepr, AbstractDictIteratorRepr,\
+ rtype_newdict, dum_variant, dum_keys, dum_values, dum_items
from pypy.rpython.lltypesystem import lltype
from pypy.rpython.rarithmetic import r_uint
from pypy.rpython.objectmodel import hlinvoke
@@ -377,13 +378,6 @@
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
@@ -591,7 +585,7 @@
#
# Iteration.
-class DictIteratorRepr(rmodel.IteratorRepr):
+class DictIteratorRepr(AbstractDictIteratorRepr):
def __init__(self, r_dict, variant="keys"):
self.r_dict = r_dict
@@ -599,29 +593,9 @@
self.lowleveltype = lltype.Ptr(lltype.GcStruct('dictiter',
('dict', r_dict.lowleveltype),
('index', lltype.Signed)))
+ self.ll_dictiter = ll_dictiter
+ self.ll_dictnext = ll_dictnext
- 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)
Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py (original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py Mon Apr 24 16:31:40 2006
@@ -297,7 +297,7 @@
self._GENERIC_METHODS = frozendict({
"ll_length": Meth([], Signed),
- "ll_get": Meth([self.KEYTYPE_T, self.VALUETYPE_T], self.VALUETYPE_T), # ll_get(key, default)
+ "ll_get": Meth([self.KEYTYPE_T], self.VALUETYPE_T),
"ll_set": Meth([self.KEYTYPE_T, self.VALUETYPE_T], Void),
"ll_remove": Meth([self.KEYTYPE_T], Bool), # return False is key was not present
"ll_contains": Meth([self.KEYTYPE_T], Bool),
@@ -664,11 +664,11 @@
# NOT_RPYTHON
return len(self._dict)
- def ll_get(self, key, default):
+ def ll_get(self, key):
# NOT_RPYTHON
assert typeOf(key) == self._TYPE._KEYTYPE
- assert typeOf(key) == self._TYPE._VALUETYPE
- return self._dict.get(key, default)
+ assert key in self._dict
+ return self._dict[key]
def ll_set(self, key, value):
# NOT_RPYTHON
Modified: pypy/dist/pypy/rpython/ootypesystem/rdict.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rdict.py (original)
+++ pypy/dist/pypy/rpython/ootypesystem/rdict.py Mon Apr 24 16:31:40 2006
@@ -1,17 +1,17 @@
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.rdict import AbstractDictRepr, AbstractDictIteratorRepr,\
+ rtype_newdict, dum_variant, dum_keys, dum_values, dum_items
from pypy.rpython.ootypesystem import ootype
from pypy.rpython.ootypesystem.rlist import ll_newlist
+from pypy.rpython.ootypesystem.riterable import iterator_type
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
-def dum_values(): pass
-def dum_items():pass
class DictRepr(AbstractDictRepr):
def __init__(self, rtyper, key_repr, value_repr, dictkey, dictvalue,
@@ -65,6 +65,9 @@
return hop.genop("oosend", [c_name] + v_args,
resulttype=hop.r_result.lowleveltype)
+ def make_iterator_repr(self, *variant):
+ return DictIteratorRepr(self, *variant)
+
def rtype_len(self, hop):
v_dict, = hop.inputargs(self)
return self.send_message(hop, 'll_length')
@@ -77,8 +80,7 @@
v_dict, v_key, v_default = hop.inputargs(self, self.key_repr,
self.value_repr)
hop.exception_cannot_occur()
- v_res = self.send_message(hop, 'll_get')
- #v_res = hop.gendirectcall(ll_get, v_dict, v_key, v_default)
+ v_res = hop.gendirectcall(ll_dict_get, v_dict, v_key, v_default)
return self.recast_value(hop.llops, v_res)
def rtype_method_setdefault(self, hop):
@@ -103,14 +105,19 @@
r_list = hop.r_result
cLIST = hop.inputconst(ootype.Void, r_list.lowleveltype)
c_func = hop.inputconst(ootype.Void, spec)
- c_dummy_default = hop.inputconst(self.value_repr.lowleveltype,
- self.value_repr.ll_dummy_value)
- return hop.gendirectcall(ll_dict_values_items, v_dict, cLIST, c_func, c_dummy_default)
-
-## def rtype_method_items(self, hop):
-## v_dict, = hop.inputargs(self)
-## return hop.gendirectcall(ll_dict_items, v_dict)
+ return hop.gendirectcall(ll_dict_values_items, v_dict, cLIST, c_func)
+ 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)
class __extend__(pairtype(DictRepr, rmodel.Repr)):
@@ -120,8 +127,7 @@
if not r_dict.custom_eq_hash: # TODO: why only in this case?
hop.has_implicit_exception(KeyError) # record that we know about it
hop.exception_is_here()
- c_dummy_default = hop.inputconst(r_dict.value_repr.lowleveltype, r_dict.value_repr.ll_dummy_value)
- v_res = hop.gendirectcall(ll_dict_getitem, v_dict, v_key, c_dummy_default)
+ 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):
@@ -153,10 +159,10 @@
# check if a dict is True, allowing for None
return bool(d) and d.ll_length() != 0
-def ll_dict_getitem(d, key, dummy_default):
+def ll_dict_getitem(d, key):
# TODO: this is inefficient because it does two lookups
if d.ll_contains(key):
- return d.ll_get(key, dummy_default) # dummy_default is never returned
+ return d.ll_get(key)
else:
raise KeyError
@@ -164,21 +170,28 @@
if not d.ll_remove(key):
raise KeyError
+def ll_dict_get(d, key, default):
+ # TODO: this is inefficient because it does two lookups
+ if d.ll_contains(key):
+ return d.ll_get(key)
+ else:
+ return default
+
def ll_dict_setdefault(d, key, default):
try:
- return ll_dict_getitem(d, key, default)
+ return ll_dict_getitem(d, key)
except KeyError:
d.ll_set(key, default)
return default
-def ll_dict_values_items(d, LIST, func, dummy_default):
+def ll_dict_values_items(d, LIST, func):
keys = d.ll_keys()
length = keys.ll_length()
result = ll_newlist(LIST, length)
i = 0
while i < length:
key = keys.ll_getitem_fast(i)
- value = d.ll_get(key, dummy_default) # dummy_default is never returned
+ value = d.ll_get(key)
if func is dum_items:
r = ootype.new(LIST._ITEMTYPE)
r.item0 = key # TODO: do we need casting?
@@ -189,3 +202,45 @@
i += 1
return result
+
+
+# ____________________________________________________________
+#
+# Iteration.
+
+class DictIteratorRepr(AbstractDictIteratorRepr):
+
+ def __init__(self, r_dict, variant="keys"):
+ self.r_dict = r_dict
+ self.variant = variant
+ self.lowleveltype = iterator_type(r_dict, r_dict.key_repr)
+ self.ll_dictiter = ll_dictiter
+ self.ll_dictnext = ll_dictnext
+
+def ll_dictiter(ITER, d):
+ iter = ootype.new(ITER)
+ iter.iterable = d
+ iter.index = 0
+ return iter
+
+# TODO: this is very inefficient for values and items because it does
+# a dict lookup at every iteration. Need to be refactored.
+def ll_dictnext(iter, func, RETURNTYPE):
+ d = iter.iterable
+ keys = d.ll_keys()
+ index = iter.index
+ if index >= keys.ll_length():
+ raise StopIteration
+ iter.index = index + 1
+
+ key = keys.ll_getitem_fast(index)
+ if func is dum_keys:
+ return key
+ elif func is dum_values:
+ return d.ll_get(key)
+ elif func is dum_items:
+ res = ootype.new(RETURNTYPE)
+ res.item0 = key
+ res.item1 = d.ll_get(key)
+ return res
+
Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_oodict.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_oodict.py (original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_oodict.py Mon Apr 24 16:31:40 2006
@@ -17,5 +17,4 @@
DT = Dict(Signed, Float)
d = new(DT)
d.ll_set(42, 123.45)
- assert d.ll_get(42, 0.0) == 123.45
- assert d.ll_get(43, 0.0) == 0.0
+ assert d.ll_get(42) == 123.45
Modified: pypy/dist/pypy/rpython/rdict.py
==============================================================================
--- pypy/dist/pypy/rpython/rdict.py (original)
+++ pypy/dist/pypy/rpython/rdict.py Mon Apr 24 16:31:40 2006
@@ -8,6 +8,13 @@
from pypy.rpython import objectmodel
from pypy.rpython import rmodel
+def dum_keys(): pass
+def dum_values(): pass
+def dum_items():pass
+dum_variant = {"keys": dum_keys,
+ "values": dum_values,
+ "items": dum_items}
+
class __extend__(annmodel.SomeDict):
def rtyper_makerepr(self, rtyper):
@@ -71,3 +78,29 @@
cDICT = hop.inputconst(lltype.Void, r_dict.DICT)
v_result = hop.gendirectcall(hop.rtyper.type_system.rdict.ll_newdict, cDICT)
return v_result
+
+
+class AbstractDictIteratorRepr(rmodel.IteratorRepr):
+ def newiter(self, hop):
+ v_dict, = hop.inputargs(self.r_dict)
+ citerptr = hop.inputconst(lltype.Void, self.lowleveltype)
+ return hop.gendirectcall(self.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(self.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
+
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 Mon Apr 24 16:31:40 2006
@@ -819,3 +819,41 @@
res = [self.ll_to_tuple(item, 2) for item in res]
assert res == [(42, 43), (13, 14)] or res == [(13, 14), (42, 43)]
+ def test_iteration(self):
+ def func(x, y):
+ d = {x: x+1, y: y+1}
+ tot = 0
+ for key in d:
+ tot += key
+ return tot
+ assert self.interpret(func, [42, 13]) == 55
+
+ def test_iterkeys(self):
+ def func(x, y):
+ d = {x: x+1, y: y+1}
+ tot = 0
+ for key in d.iterkeys():
+ tot += key
+ return tot
+ assert self.interpret(func, [42, 13]) == 55
+
+ def test_itervalues(self):
+ def func(x, y):
+ d = {x: x+1, y: y+1}
+ tot = 0
+ for value in d.itervalues():
+ tot += value
+ return tot
+ assert self.interpret(func, [42, 13]) == 57
+
+ def test_iteritems(self):
+ def func(x, y):
+ d = {x: x+1, y: y+1}
+ tot1 = 0
+ tot2 = 0
+ for key, value in d.iteritems():
+ tot1 += key
+ tot2 += value
+ return tot1, tot2
+ res = self.ll_to_tuple(self.interpret(func, [42, 13]), 2)
+ assert res == (55, 57)
More information about the Pypy-commit
mailing list