[pypy-svn] r33152 - in pypy/dist/pypy/rpython: . ootypesystem test
antocuni at codespeak.net
antocuni at codespeak.net
Wed Oct 11 13:21:37 CEST 2006
Author: antocuni
Date: Wed Oct 11 13:21:35 2006
New Revision: 33152
Modified:
pypy/dist/pypy/rpython/ootypesystem/ootype.py
pypy/dist/pypy/rpython/ootypesystem/rdict.py
pypy/dist/pypy/rpython/rdict.py
pypy/dist/pypy/rpython/test/test_rdict.py
Log:
Make DictItemsIterator.ll_go_next raise RuntimeError if the dictionary
we are iterating over has been changed.
Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py (original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py Wed Oct 11 13:21:35 2006
@@ -552,17 +552,9 @@
self.VALUETYPE_T: VALUETYPE
}
- # some words about the interface of the iterator: we can't
- # write the next() method directly in the backend because of
- # two reasons:
- # 1) tuples aren't BuiltinType, yet, so we can't make them
- # generic; moreover, they are constructed on-the-fly, so the
- # two-item tuple type that an hypotetic next() would return
- # isn't available at this time.
- # 2) StopIteration is generated at translation time too, so
- # this would prevent backends to do a precompilation of
- # support code.
-
+ # Dictionaries are not allowed to be changed during an
+ # iteration. The ll_go_next method should check this condition
+ # and raise RuntimeError in that case.
self._GENERIC_METHODS = frozendict({
"ll_go_next": Meth([], Bool), # move forward; return False is there is no more data available
"ll_current_key": Meth([], self.KEYTYPE_T),
@@ -1043,6 +1035,7 @@
def __init__(self, DICT):
self._TYPE = DICT
self._dict = {}
+ self._stamp = 0
def ll_length(self):
# NOT_RPYTHON
@@ -1059,12 +1052,14 @@
assert typeOf(key) == self._TYPE._KEYTYPE
assert typeOf(value) == self._TYPE._VALUETYPE
self._dict[key] = value
+ self._stamp += 1
def ll_remove(self, key):
# NOT_RPYTHON
assert typeOf(key) == self._TYPE._KEYTYPE
try:
del self._dict[key]
+ self._stamp += 1
return True
except KeyError:
return False
@@ -1076,12 +1071,14 @@
def ll_clear(self):
self._dict.clear()
+ self._stamp += 1
def ll_get_items_iterator(self):
# NOT_RPYTHON
ITER = DictItemsIterator(self._TYPE._KEYTYPE, self._TYPE._VALUETYPE)
iter = _dict_items_iterator(ITER)
- iter._items = self._dict.items()
+ iter._set_dict(self)
+ #print 'ITERATOR created with stamp', self._stamp
return iter
class _null_dict(_null_mixin(_dict), _dict):
@@ -1112,11 +1109,20 @@
class _dict_items_iterator(_builtin_type):
def __init__(self, ITER):
self._TYPE = ITER
- self._items = []
self._index = -1
+ def _set_dict(self, d):
+ self._dict = d
+ self._items = d._dict.items()
+ self._stamp = d._stamp
+
+ def _check_stamp(self):
+ if self._stamp != self._dict._stamp:
+ raise RuntimeError, 'Dictionary changed during iteration'
+
def ll_go_next(self):
# NOT_RPYTHON
+ self._check_stamp()
self._index += 1
if self._index >= len(self._items):
return False
@@ -1125,11 +1131,13 @@
def ll_current_key(self):
# NOT_RPYTHON
+ self._check_stamp()
assert 0 <= self._index < len(self._items)
return self._items[self._index][0]
def ll_current_value(self):
# NOT_RPYTHON
+ self._check_stamp()
assert 0 <= self._index < len(self._items)
return self._items[self._index][1]
Modified: pypy/dist/pypy/rpython/ootypesystem/rdict.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rdict.py (original)
+++ pypy/dist/pypy/rpython/ootypesystem/rdict.py Wed Oct 11 13:21:35 2006
@@ -362,6 +362,9 @@
ITER = ootype.DictItemsIterator(KEYTYPE, VALUETYPE)
return ootype.Record({"iterator": ITER})
+ def _next_implicit_exceptions(self, hop):
+ hop.has_implicit_exception(StopIteration)
+ hop.has_implicit_exception(RuntimeError)
def ll_dictiter(ITER, d):
iter = ootype.new(ITER)
Modified: pypy/dist/pypy/rpython/rdict.py
==============================================================================
--- pypy/dist/pypy/rpython/rdict.py (original)
+++ pypy/dist/pypy/rpython/rdict.py Wed Oct 11 13:21:35 2006
@@ -89,6 +89,9 @@
citerptr = hop.inputconst(lltype.Void, self.lowleveltype)
return hop.gendirectcall(self.ll_dictiter, citerptr, v_dict)
+ def _next_implicit_exceptions(self, hop):
+ hop.has_implicit_exception(StopIteration)
+
def rtype_next(self, hop):
variant = self.variant
v_iter, = hop.inputargs(self)
@@ -97,7 +100,7 @@
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
+ self._next_implicit_exceptions(hop) # record that we know about it
hop.exception_is_here()
v = hop.gendirectcall(self.ll_dictnext, v_iter, v_func, c1)
if variant == 'keys':
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 Wed Oct 11 13:21:35 2006
@@ -749,6 +749,13 @@
res = self.interpret(func, [5])
assert res.ll_get(5) is res
-
-
-
+ def test_invalid_iterator(self):
+ def func():
+ try:
+ d = {'a': 1, 'b': 2}
+ for key in d:
+ d[key] = 0
+ return True
+ except RuntimeError:
+ return False
+ assert self.interpret(func, []) == False
More information about the pypy-svn
mailing list