[pypy-svn] r15821 - in pypy/dist/pypy: annotation rpython rpython/test
arigo at codespeak.net
arigo at codespeak.net
Tue Aug 9 16:32:29 CEST 2005
Author: arigo
Date: Tue Aug 9 16:32:17 2005
New Revision: 15821
Modified:
pypy/dist/pypy/annotation/binaryop.py
pypy/dist/pypy/rpython/annlowlevel.py
pypy/dist/pypy/rpython/rbuiltin.py
pypy/dist/pypy/rpython/rconstantdict.py
pypy/dist/pypy/rpython/rdict.py
pypy/dist/pypy/rpython/rint.py
pypy/dist/pypy/rpython/rlist.py
pypy/dist/pypy/rpython/robject.py
pypy/dist/pypy/rpython/rpbc.py
pypy/dist/pypy/rpython/rptr.py
pypy/dist/pypy/rpython/rrange.py
pypy/dist/pypy/rpython/rspecialcase.py
pypy/dist/pypy/rpython/rstr.py
pypy/dist/pypy/rpython/rtuple.py
pypy/dist/pypy/rpython/rtyper.py
pypy/dist/pypy/rpython/test/test_rlist.py
pypy/dist/pypy/rpython/test/test_rpbc.py
Log:
issue105 testing
Require explicit care about exception catching in the RTyper.
This is done with an extension of the interface of 'hop' --
which is already quite complicated :-(
* hop.has_implicit_exception(cls) checks if the current high-level
op is in the scope of a branch catching 'cls', as previously, but
now also records that the rtyper cares about this case.
* hop.exception_is_here() is called with no argument just before
a llop is generated. It means that the llop in question will be
the one that should be protected by the exception catching.
If has_implicit_exception() was called before, then
exception_is_here() verifies that *all* except links in the graph
have indeed been checked for with an has_implicit_exception().
This is not verified if has_implicit_exception() has never been
called -- useful for 'direct_call' and other operations that can
just raise any exception.
* hop.exception_cannot_occur() is a special case for override:ignore
meaning that there is, after all, no operation left that could raise
an exception. (The RTyper class normally verifies that
exception_is_here() was really called once for each high-level operation
that is in the scope of exception-catching links.)
This required adding the correct has_implicit_exception() and
exception_is_here() calls all over the place in the r*.py files. It's possible
that I have overlooked 1-2 untested places. Indeed, I found a couple of typos
looking around. It also required more precise 'can_only_throw' attributes in
annotation/binary.py, which is good (but again easy to overlook 1-2 places).
Modified: pypy/dist/pypy/annotation/binaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/binaryop.py (original)
+++ pypy/dist/pypy/annotation/binaryop.py Tue Aug 9 16:32:17 2005
@@ -379,15 +379,18 @@
def getitem((dic1, obj2)):
getbookkeeper().count("dict_getitem", dic1)
return dic1.dictdef.read_value()
+ getitem.can_only_throw = [KeyError]
def setitem((dic1, obj2), s_value):
getbookkeeper().count("dict_setitem", dic1)
dic1.dictdef.generalize_key(obj2)
dic1.dictdef.generalize_value(s_value)
+ setitem.can_only_throw = [KeyError]
def delitem((dic1, obj1)):
getbookkeeper().count("dict_delitem", dic1)
pass
+ delitem.can_only_throw = [KeyError]
class __extend__(pairtype(SomeSlice, SomeSlice)):
@@ -409,6 +412,7 @@
else:
getbookkeeper().count("tuple_random_getitem", tup1)
return unionof(*tup1.items)
+ getitem.can_only_throw = [IndexError]
class __extend__(pairtype(SomeList, SomeInteger)):
@@ -420,40 +424,48 @@
def getitem((lst1, int2)):
getbookkeeper().count("list_getitem", int2)
return lst1.listdef.read_item()
+ getitem.can_only_throw = [IndexError]
def setitem((lst1, int2), s_value):
getbookkeeper().count("list_setitem", int2)
lst1.listdef.mutate()
lst1.listdef.generalize(s_value)
+ setitem.can_only_throw = [IndexError]
def delitem((lst1, int2)):
getbookkeeper().count("list_delitem", int2)
lst1.listdef.resize()
+ delitem.can_only_throw = [IndexError]
class __extend__(pairtype(SomeList, SomeSlice)):
def getitem((lst, slic)):
#return getbookkeeper().newlist(lst.listdef.read_item())
return SomeList(lst.listdef)
+ getitem.can_only_throw = []
def setitem((lst, slic), s_iterable):
# we need the same unifying effect as the extend() method for
# the case lst1[x:y] = lst2.
lst.method_extend(s_iterable)
+ setitem.can_only_throw = []
def delitem((lst1, slic)):
lst1.listdef.resize()
+ delitem.can_only_throw = []
class __extend__(pairtype(SomeString, SomeSlice)):
def getitem((str1, slic)):
return SomeString()
+ getitem.can_only_throw = []
class __extend__(pairtype(SomeString, SomeInteger)):
def getitem((str1, int2)):
getbookkeeper().count("str_getitem", int2)
return SomeChar()
+ getitem.can_only_throw = [IndexError]
def mul((str1, int2)): # xxx do we want to support this
getbookkeeper().count("str_mul", str1, int2)
@@ -591,19 +603,21 @@
def getitem((p, int1)):
v = p.ll_ptrtype._example()[0]
return ll_to_annotation(v)
+ getitem.can_only_throw = []
def setitem((p, int1), s_value):
v_lltype = annotation_to_lltype(s_value)
p.ll_ptrtype._example()[0] = v_lltype._defl()
+ setitem.can_only_throw = []
class __extend__(pairtype(SomePtr, SomeObject)):
def union((p, obj)):
assert False, ("mixing pointer type %r with something else %r" % (p.ll_ptrtype, obj))
- def gettitem((p, obj)):
+ def getitem((p, obj)):
assert False,"ptr %r getitem index not an int: %r" % (p.ll_ptrtype, obj)
- def settitem((p, obj)):
+ def setitem((p, obj)):
assert False,"ptr %r setitem index not an int: %r" % (p.ll_ptrtype, obj)
class __extend__(pairtype(SomeObject, SomePtr)):
@@ -635,10 +649,12 @@
def getitem((s_taa, s_int)):
from pypy.annotation.model import lltype_or_address_to_annotation
return lltype_or_address_to_annotation(s_taa.type)
+ getitem.can_only_throw = []
def setitem((s_taa, s_int), s_value):
from pypy.annotation.model import annotation_to_lltype_or_address
assert annotation_to_lltype_or_address(s_value) is s_taa.type
+ setitem.can_only_throw = []
class __extend__(pairtype(SomeAddress, SomeInteger)):
Modified: pypy/dist/pypy/rpython/annlowlevel.py
==============================================================================
--- pypy/dist/pypy/rpython/annlowlevel.py (original)
+++ pypy/dist/pypy/rpython/annlowlevel.py Tue Aug 9 16:32:17 2005
@@ -30,6 +30,7 @@
return getattr(self.val, '__name__', repr(self.val)) + 'Const'
class LowLevelAnnotatorPolicy(BasicAnnotatorPolicy):
+ allow_someobjects = False
def specialize(pol, bookkeeper, spaceop, func, args, mono):
args_s, kwds_s = args.unpack()
Modified: pypy/dist/pypy/rpython/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/rbuiltin.py (original)
+++ pypy/dist/pypy/rpython/rbuiltin.py Tue Aug 9 16:32:17 2005
@@ -277,11 +277,13 @@
if extfuncinfo.ll_annotable:
def rtype_extfunc(hop):
vars = hop.inputargs(*hop.args_r)
+ hop.exception_is_here()
return hop.gendirectcall(ll_function, *vars)
else:
def rtype_extfunc(hop):
resulttype = hop.r_result
vars = hop.inputargs(*hop.args_r)
+ hop.exception_is_here()
return hop.llops.genexternalcall(ll_function.__name__, vars, resulttype=resulttype,
_callable = ll_function)
Modified: pypy/dist/pypy/rpython/rconstantdict.py
==============================================================================
--- pypy/dist/pypy/rpython/rconstantdict.py (original)
+++ pypy/dist/pypy/rpython/rconstantdict.py Tue Aug 9 16:32:17 2005
@@ -99,6 +99,8 @@
v_dict, v_key = hop.inputargs(r_dict, r_dict.key_repr)
hashcompute = r_dict.get_key_hash_function()
chashcompute = hop.inputconst(lltype.Void, hashcompute)
+ hop.has_implicit_exception(KeyError) # record that we know about it
+ hop.exception_is_here()
return hop.gendirectcall(ll_constantdict_getitem, v_dict, v_key,
chashcompute)
Modified: pypy/dist/pypy/rpython/rdict.py
==============================================================================
--- pypy/dist/pypy/rpython/rdict.py (original)
+++ pypy/dist/pypy/rpython/rdict.py Tue Aug 9 16:32:17 2005
@@ -141,10 +141,14 @@
def rtype_getitem((r_dict, r_string), hop):
v_dict, v_key = hop.inputargs(r_dict, rstr.string_repr)
+ hop.has_implicit_exception(KeyError) # record that we know about it
+ hop.exception_is_here()
return hop.gendirectcall(ll_strdict_getitem, v_dict, v_key)
def rtype_delitem((r_dict, r_string), hop):
v_dict, v_key = hop.inputargs(r_dict, rstr.string_repr)
+ hop.has_implicit_exception(KeyError) # record that we know about it
+ hop.exception_is_here()
return hop.gendirectcall(ll_strdict_delitem, v_dict, v_key)
def rtype_setitem((r_dict, r_string), hop):
@@ -320,6 +324,8 @@
def rtype_next(self, hop):
v_iter, = hop.inputargs(self)
+ hop.has_implicit_exception(StopIteration) # record that we know about it
+ hop.exception_is_here()
return hop.gendirectcall(ll_strdictnext, v_iter)
def ll_strdictiter(ITERPTR, d):
Modified: pypy/dist/pypy/rpython/rint.py
==============================================================================
--- pypy/dist/pypy/rpython/rint.py (original)
+++ pypy/dist/pypy/rpython/rint.py Tue Aug 9 16:32:17 2005
@@ -117,17 +117,20 @@
vlist = hop.inputargs(Unsigned, Unsigned, Void)[:2]
else:
vlist = hop.inputargs(Unsigned, Unsigned, Unsigned)
+ hop.exception_is_here()
return hop.genop('uint_pow' + suffix, vlist, resulttype=Unsigned)
else:
if s_int3.is_constant() and s_int3.const is None:
vlist = hop.inputargs(Signed, Signed, Void)[:2]
else:
vlist = hop.inputargs(Signed, Signed, Signed)
+ hop.exception_is_here()
return hop.genop('int_pow' + suffix, vlist, resulttype=Signed)
def rtype_pow_ovf(_, hop):
if hop.s_result.unsigned:
raise TyperError("forbidden uint_pow_ovf")
+ hop.has_implicit_exception(OverflowError) # record that we know about it
return self.rtype_pow(_, hop, suffix='_ovf')
def rtype_inplace_pow(_, hop):
@@ -167,9 +170,13 @@
if func1.endswith('_ovf'):
raise TyperError("forbidden uint_" + func)
vlist = hop.inputargs(Unsigned, Unsigned)
+ hop.exception_is_here()
return hop.genop('uint_'+func, vlist, resulttype=Unsigned)
else:
+ if func1.endswith('_ovf'): # record that we know about it
+ hop.has_implicit_exception(OverflowError)
vlist = hop.inputargs(Signed, Signed)
+ hop.exception_is_here()
return hop.genop('int_'+func, vlist, resulttype=Signed)
#Helper functions for comparisons
@@ -233,6 +240,8 @@
raise TyperError("forbidden uint_abs_ovf")
else:
vlist = hop.inputargs(Signed)
+ hop.has_implicit_exception(OverflowError) # record we know about it
+ hop.exception_is_here()
return hop.genop('int_abs_ovf', vlist, resulttype=Signed)
def rtype_invert(_, hop):
@@ -256,6 +265,8 @@
raise TyperError("forbidden uint_neg_ovf")
else:
vlist = hop.inputargs(Signed)
+ hop.has_implicit_exception(OverflowError) # record we know about it
+ hop.exception_is_here()
return hop.genop('int_neg_ovf', vlist, resulttype=Signed)
def rtype_pos(_, hop):
Modified: pypy/dist/pypy/rpython/rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/rlist.py (original)
+++ pypy/dist/pypy/rpython/rlist.py Tue Aug 9 16:32:17 2005
@@ -107,6 +107,8 @@
def rtype_method_index(self, hop):
v_lst, v_value = hop.inputargs(self, self.item_repr)
+ hop.has_implicit_exception(ValueError) # record that we know about it
+ hop.exception_is_here()
return hop.gendirectcall(ll_listindex, v_lst, v_value, self.get_eqfunc())
def rtype_method_insert(self, hop):
@@ -190,6 +192,7 @@
llfn = ll_getitem_nonneg
else:
llfn = ll_getitem
+ hop.exception_is_here()
return hop.gendirectcall(llfn, v_lst, v_index)
def rtype_setitem((r_lst, r_int), hop):
@@ -204,6 +207,7 @@
llfn = ll_setitem_nonneg
else:
llfn = ll_setitem
+ hop.exception_is_here()
return hop.gendirectcall(llfn, v_lst, v_index, v_item)
def rtype_delitem((r_lst, r_int), hop):
@@ -218,6 +222,7 @@
llfn = ll_delitem_nonneg
else:
llfn = ll_delitem
+ hop.exception_is_here()
return hop.gendirectcall(llfn, v_lst, v_index)
def rtype_mul((r_lst, r_int), hop):
@@ -465,7 +470,7 @@
if i < 0:
i += len(l.items)
if i >= len(l.items) or i < 0:
- raise IndexErrror
+ raise IndexError
ll_delitem_nonneg(l, i)
def ll_concat(l1, l2):
@@ -716,6 +721,8 @@
def rtype_next(self, hop):
v_iter, = hop.inputargs(self)
+ hop.has_implicit_exception(StopIteration) # record that we know about it
+ hop.exception_is_here()
return hop.gendirectcall(ll_listnext, v_iter)
def ll_listiter(ITERPTR, lst):
Modified: pypy/dist/pypy/rpython/robject.py
==============================================================================
--- pypy/dist/pypy/rpython/robject.py (original)
+++ pypy/dist/pypy/rpython/robject.py Tue Aug 9 16:32:17 2005
@@ -51,6 +51,7 @@
def make_operation(opname, cls=PyObjRepr):
def rtype_op(_, hop):
vlist = hop.inputargs(*([pyobj_repr]*hop.nb_args))
+ hop.exception_is_here()
if isinstance(hop.r_result, VoidRepr):
hop.genop(opname, vlist)
else:
Modified: pypy/dist/pypy/rpython/rpbc.py
==============================================================================
--- pypy/dist/pypy/rpython/rpbc.py (original)
+++ pypy/dist/pypy/rpython/rpbc.py Tue Aug 9 16:32:17 2005
@@ -403,6 +403,7 @@
if self.lowleveltype == Void:
assert len(self.function_signatures()) == 1
vlist[0] = hop.inputconst(typeOf(f), f)
+ hop.exception_is_here()
v = hop.genop('direct_call', vlist, resulttype = rresult)
return hop.llops.convertvar(v, rresult, hop.r_result)
Modified: pypy/dist/pypy/rpython/rptr.py
==============================================================================
--- pypy/dist/pypy/rpython/rptr.py (original)
+++ pypy/dist/pypy/rpython/rptr.py Tue Aug 9 16:32:17 2005
@@ -55,6 +55,7 @@
if not isinstance(self.lowleveltype.TO, FuncType):
raise TyperError("calling a non-function %r", self.lowleveltype.TO)
vlist = hop.inputargs(*hop.args_r)
+ hop.exception_is_here()
return hop.genop('direct_call', vlist,
resulttype = self.lowleveltype.TO.RESULT)
Modified: pypy/dist/pypy/rpython/rrange.py
==============================================================================
--- pypy/dist/pypy/rpython/rrange.py (original)
+++ pypy/dist/pypy/rpython/rrange.py Tue Aug 9 16:32:17 2005
@@ -43,6 +43,7 @@
llfn = ll_rangeitem_nonneg
else:
llfn = ll_rangeitem
+ hop.exception_is_here()
return hop.gendirectcall(llfn, v_lst, v_index, cstep)
# ____________________________________________________________
@@ -120,6 +121,8 @@
llfn = ll_rangenext_up
else:
llfn = ll_rangenext_down
+ hop.has_implicit_exception(StopIteration) # record that we know about it
+ hop.exception_is_here()
return hop.gendirectcall(llfn, v_iter, cstep)
def ll_rangeiter(ITERPTR, rng):
Modified: pypy/dist/pypy/rpython/rspecialcase.py
==============================================================================
--- pypy/dist/pypy/rpython/rspecialcase.py (original)
+++ pypy/dist/pypy/rpython/rspecialcase.py Tue Aug 9 16:32:17 2005
@@ -25,4 +25,5 @@
def rtype_override_ignore(hop, clsdef): # ignore works for methods too
+ hop.exception_cannot_occur()
return inputconst(hop.r_result, None)
Modified: pypy/dist/pypy/rpython/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/rstr.py (original)
+++ pypy/dist/pypy/rpython/rstr.py Tue Aug 9 16:32:17 2005
@@ -157,13 +157,16 @@
return hop.gendirectcall(ll_replace_chr_chr, v_str, v_c1, v_c2)
def rtype_int(_, hop):
+ hop.has_implicit_exception(ValueError) # record that we know about it
if hop.nb_args == 1:
v_str, = hop.inputargs(string_repr)
c_base = inputconst(Signed, 10)
+ hop.exception_is_here()
return hop.gendirectcall(ll_int, v_str, c_base)
if not hop.args_r[1] == rint.signed_repr:
raise TyperError, 'base needs to be an int'
v_str, v_base= hop.inputargs(string_repr, rint.signed_repr)
+ hop.exception_is_here()
return hop.gendirectcall(ll_int, v_str, v_base)
def ll_str(s, r):
@@ -189,6 +192,7 @@
llfn = ll_stritem_nonneg
else:
llfn = ll_stritem
+ hop.exception_is_here()
return hop.gendirectcall(llfn, v_str, v_index)
def rtype_mod(_, hop):
@@ -936,6 +940,8 @@
def rtype_next(self, hop):
v_iter, = hop.inputargs(self)
+ hop.has_implicit_exception(StopIteration) # record that we know about it
+ hop.exception_is_here()
return hop.gendirectcall(ll_strnext, v_iter)
string_iterator_repr = StringIteratorRepr()
Modified: pypy/dist/pypy/rpython/rtuple.py
==============================================================================
--- pypy/dist/pypy/rpython/rtuple.py (original)
+++ pypy/dist/pypy/rpython/rtuple.py Tue Aug 9 16:32:17 2005
@@ -196,6 +196,8 @@
def rtype_next(self, hop):
v_iter, = hop.inputargs(self)
+ hop.has_implicit_exception(StopIteration) # record that we know about it
+ hop.exception_is_here()
return hop.gendirectcall(ll_tuplenext, v_iter)
def ll_tupleiter(ITERPTR, tuple):
Modified: pypy/dist/pypy/rpython/rtyper.py
==============================================================================
--- pypy/dist/pypy/rpython/rtyper.py (original)
+++ pypy/dist/pypy/rpython/rtyper.py Tue Aug 9 16:32:17 2005
@@ -261,6 +261,33 @@
block.operations[:] = newops
block.renamevariables(varmapping)
+
+ pos = newops.llop_raising_exceptions
+ if (pos is not None and pos != len(newops)-1):
+ # this is for the case where the llop that raises the exceptions
+ # is not the last one in the list.
+ assert block.exitswitch == Constant(last_exception)
+ noexclink = block.exits[0]
+ assert noexclink.exitcase is None
+ if pos == "removed":
+ # the exception cannot actually occur at all.
+ # See for example rspecialcase.rtype_call_specialcase().
+ # We just remove all exception links.
+ block.exitswitch = None
+ block.exits = block.exits[:1]
+ else:
+ # We have to split the block in two, with the exception-catching
+ # exitswitch after the llop at 'pos', and the extra operations
+ # in the new part of the block, corresponding to the
+ # no-exception case. See for example test_rlist.test_indexerror
+ # or test_rpbc.test_multiple_ll_one_hl_op.
+ assert 0 <= pos < len(newops) - 1
+ extraops = block.operations[pos+1:]
+ del block.operations[pos+1:]
+ insert_empty_block(self.annotator.translator,
+ noexclink,
+ newops = extraops)
+
self.insert_link_conversions(block)
def insert_link_conversions(self, block):
@@ -346,6 +373,11 @@
def translate_hl_to_ll(self, hop, varmapping):
log.translating(hop.spaceop.opname, hop.args_s)
resultvar = hop.dispatch()
+ if hop.exceptionlinks and hop.llops.llop_raising_exceptions is None:
+ raise TyperError("the graph catches %s, but the rtyper did not "
+ "take exceptions into account "
+ "(exception_is_here() not called)" % (
+ [link.exitcase.__name__ for link in hop.exceptionlinks],))
op = hop.spaceop
if resultvar is None:
# no return value
@@ -590,17 +622,54 @@
self.args_r[0], self.args_r[1] = self.args_r[1], self.args_r[0]
def has_implicit_exception(self, exc_cls):
+ if self.llops.llop_raising_exceptions is not None:
+ raise TyperError("already generated the llop that raises the "
+ "exception")
+ if not self.exceptionlinks:
+ return False # don't record has_implicit_exception checks on
+ # high-level ops before the last one in the block
+ if self.llops.implicit_exceptions_checked is None:
+ self.llops.implicit_exceptions_checked = []
for link in self.exceptionlinks:
if issubclass(exc_cls, link.exitcase):
+ self.llops.implicit_exceptions_checked.append(link.exitcase)
return True
return False
+ def exception_is_here(self):
+ if self.llops.llop_raising_exceptions is not None:
+ raise TyperError("cannot catch an exception at more than one llop")
+ if not self.exceptionlinks:
+ return # ignored for high-level ops before the last one in the block
+ if self.llops.implicit_exceptions_checked is not None:
+ # sanity check: complain if an has_implicit_exception() check is
+ # missing in the rtyper.
+ for link in self.exceptionlinks:
+ if link.exitcase not in self.llops.implicit_exceptions_checked:
+ raise TyperError("the graph catches %s, but the rtyper "
+ "did not explicitely handle it" % (
+ link.exitcase.__name__,))
+ self.llops.llop_raising_exceptions = len(self.llops)
+
+ def exception_cannot_occur(self):
+ if self.llops.llop_raising_exceptions is not None:
+ raise TyperError("cannot catch an exception at more than one llop")
+ if not self.exceptionlinks:
+ return # ignored for high-level ops before the last one in the block
+ self.llops.llop_raising_exceptions = "removed"
+
# ____________________________________________________________
class LowLevelOpList(list):
"""A list with gen*() methods to build and append low-level
operations to it.
"""
+ # NB. the following two attributes are here instead of on HighLevelOp
+ # because we want them to be shared between a HighLevelOp and its
+ # copy()es.
+ llop_raising_exceptions = None
+ implicit_exceptions_checked = None
+
def __init__(self, rtyper):
self.rtyper = rtyper
Modified: pypy/dist/pypy/rpython/test/test_rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rlist.py (original)
+++ pypy/dist/pypy/rpython/test/test_rlist.py Tue Aug 9 16:32:17 2005
@@ -382,3 +382,19 @@
for arg in (1, 9, 0, -1, -27):
res = interpret(fn, [arg])
assert res == fn(arg)
+
+def test_indexerror():
+ def fn(i):
+ l = [5, 8, 3]
+ try:
+ del l[i]
+ except IndexError:
+ pass
+ try:
+ return l[2] # implicit int->PyObj conversion here
+ except IndexError:
+ return "oups"
+ res = interpret(fn, [6])
+ assert res._obj.value == 3
+ res = interpret(fn, [-2])
+ assert res._obj.value == "oups"
Modified: pypy/dist/pypy/rpython/test/test_rpbc.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rpbc.py (original)
+++ pypy/dist/pypy/rpython/test/test_rpbc.py Tue Aug 9 16:32:17 2005
@@ -790,7 +790,7 @@
assert res == 3*2+11*7
-def test_mulitple_ll_one_hl_op():
+def test_multiple_ll_one_hl_op():
class E(Exception):
pass
class A(object):
@@ -822,9 +822,4 @@
return c.method(x + 1)
except E:
return None
- try:
- res = interpret(call, [0])
- except:
- py.test.skip("this test shows the problem with rtyping exceptions")
-
-
+ res = interpret(call, [0])
More information about the Pypy-commit
mailing list