[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