[pypy-svn] r14396 - in pypy/dist/pypy: annotation rpython rpython/test translator

arigo at codespeak.net arigo at codespeak.net
Thu Jul 7 19:18:03 CEST 2005


Author: arigo
Date: Thu Jul  7 19:17:56 2005
New Revision: 14396

Modified:
   pypy/dist/pypy/annotation/builtin.py
   pypy/dist/pypy/annotation/classdef.py
   pypy/dist/pypy/rpython/exceptiondata.py
   pypy/dist/pypy/rpython/rbuiltin.py
   pypy/dist/pypy/rpython/rpbc.py
   pypy/dist/pypy/rpython/rtyper.py
   pypy/dist/pypy/rpython/test/test_exception.py
   pypy/dist/pypy/translator/unsimplify.py
Log:
Add support for instance variables in standard exception classes.
Implemented OSError.errno.

This required some bugfixes in insert_link_conversion().



Modified: pypy/dist/pypy/annotation/builtin.py
==============================================================================
--- pypy/dist/pypy/annotation/builtin.py	(original)
+++ pypy/dist/pypy/annotation/builtin.py	Thu Jul  7 19:17:56 2005
@@ -265,6 +265,7 @@
 BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.intmask] = rarith_intmask
 
 BUILTIN_ANALYZERS[Exception.__init__.im_func] = exception_init
+BUILTIN_ANALYZERS[OSError.__init__.im_func] = exception_init
 # this one is needed otherwise when annotating assert in a test we may try to annotate 
 # py.test AssertionError.__init__ .
 BUILTIN_ANALYZERS[AssertionError.__init__.im_func] = exception_init

Modified: pypy/dist/pypy/annotation/classdef.py
==============================================================================
--- pypy/dist/pypy/annotation/classdef.py	(original)
+++ pypy/dist/pypy/annotation/classdef.py	Thu Jul  7 19:17:56 2005
@@ -5,6 +5,7 @@
 from __future__ import generators
 from types import FunctionType
 from pypy.annotation.model import SomeImpossibleValue, SomePBC, tracking_unionof
+from pypy.annotation.model import SomeInteger
 
 
 # The main purpose of a ClassDef is to collect information about class/instance
@@ -167,6 +168,12 @@
                     value.class_ = cls # remember that this is really a method
             self.add_source_for_attribute(name, sources.get(name, cls), self)
 
+        # forced attributes
+        if cls in FORCE_ATTRIBUTES_INTO_CLASSES:
+            for name, s_value in FORCE_ATTRIBUTES_INTO_CLASSES[cls].items():
+                self.generalize_attr(name, s_value)
+                self.find_attribute(name).readonly = False
+
     def add_source_for_attribute(self, attr, source, clsdef=None):
         """Adds information about a constant source for an attribute.
         """
@@ -375,3 +382,9 @@
 
 def isclassdef(x):
     return isinstance(x, ClassDef)
+
+# ____________________________________________________________
+
+FORCE_ATTRIBUTES_INTO_CLASSES = {
+    OSError: {'errno': SomeInteger()},
+    }

Modified: pypy/dist/pypy/rpython/exceptiondata.py
==============================================================================
--- pypy/dist/pypy/rpython/exceptiondata.py	(original)
+++ pypy/dist/pypy/rpython/exceptiondata.py	Thu Jul  7 19:17:56 2005
@@ -69,9 +69,9 @@
                     example = rclass.ll_cast_to_object(example)
                     example.typeptr = r_inst.rclass.getvtable()
                     table[cls] = example
-                else:
-                    assert cls.__module__ != 'exceptions', (
-                        "built-in exceptions should not grow attributes")
+                #else:
+                #    assert cls.__module__ != 'exceptions', (
+                #        "built-in exceptions should not grow attributes")
         r_inst = rclass.getinstancerepr(rtyper, None)
         r_inst.setup()
         default_excinst = malloc(self.lltype_of_exception_value.TO,

Modified: pypy/dist/pypy/rpython/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/rbuiltin.py	(original)
+++ pypy/dist/pypy/rpython/rbuiltin.py	Thu Jul  7 19:17:56 2005
@@ -155,6 +155,19 @@
         return i1
     return i2
 
+def rtype_Exception__init__(hop):
+    pass
+
+def rtype_OSError__init__(hop):
+    if hop.nb_args == 2:
+        raise TyperError("OSError() should not be called with "
+                         "a single argument")
+    if hop.nb_args >= 3:
+        v_self = hop.args_v[0]
+        r_self = hop.args_r[0]
+        v_errno = hop.inputarg(lltype.Signed, arg=1)
+        r_self.setfield(v_self, 'errno', v_errno, hop.llops)
+
 def rtype_math_floor(hop):
     vlist = hop.inputargs(lltype.Float)
     return hop.genop('float_floor', vlist, resulttype=lltype.Float)
@@ -176,6 +189,8 @@
         BUILTIN_TYPER[original] = value
 BUILTIN_TYPER[math.floor] = rtype_math_floor
 BUILTIN_TYPER[math.fmod] = rtype_math_fmod
+BUILTIN_TYPER[Exception.__init__.im_func] = rtype_Exception__init__
+BUILTIN_TYPER[OSError.__init__.im_func] = rtype_OSError__init__
 # annotation of low-level types
 
 def rtype_malloc(hop):

Modified: pypy/dist/pypy/rpython/rpbc.py
==============================================================================
--- pypy/dist/pypy/rpython/rpbc.py	(original)
+++ pypy/dist/pypy/rpython/rpbc.py	Thu Jul  7 19:17:56 2005
@@ -450,10 +450,8 @@
             assert hop.nb_args == 1, ("arguments passed to __init__, "
                                       "but no __init__!")
         else:
-            if initfunc == Exception.__init__.im_func:
-                return v_instance    # ignore __init__ and arguments completely
             s_instance = rclass.instance_annotation_for_cls(self.rtyper, klass)
-            s_init = annmodel.SomePBC({initfunc: True})
+            s_init = self.rtyper.annotator.bookkeeper.immutablevalue(initfunc)
             hop2 = hop.copy()
             hop2.r_s_popfirstarg()   # discard the class pointer argument
             hop2.v_s_insertfirstarg(v_instance, s_instance)  # add 'instance'

Modified: pypy/dist/pypy/rpython/rtyper.py
==============================================================================
--- pypy/dist/pypy/rpython/rtyper.py	(original)
+++ pypy/dist/pypy/rpython/rtyper.py	Thu Jul  7 19:17:56 2005
@@ -211,33 +211,43 @@
                     a, using_repr=self.exceptiondata.r_exception_value)
 
             inputargs_reprs = self.setup_block_entry(link.target)
+            newops = LowLevelOpList(self)
+            newlinkargs = {}
             for i in range(len(link.args)):
                 a1 = link.args[i]
                 r_a2 = inputargs_reprs[i]
                 if isinstance(a1, Constant):
                     link.args[i] = self.typedconstant(a1, using_repr=r_a2)
                     continue   # the Constant was typed, done
-                r_a1 = self.bindingrepr(a1)
+                if a1 is link.last_exception:
+                    r_a1 = self.exceptiondata.r_exception_type
+                elif a1 is link.last_exc_value:
+                    r_a1 = self.exceptiondata.r_exception_value
+                else:
+                    r_a1 = self.bindingrepr(a1)
                 if r_a1 == r_a2:
                     continue   # no conversion needed
-                newops = LowLevelOpList(self)
                 try:
-                    a1 = newops.convertvar(a1, r_a1, r_a2)
+                    new_a1 = newops.convertvar(a1, r_a1, r_a2)
                 except TyperError, e:
                     self.gottypererror(e, block, link, newops)
+                if new_a1 != a1:
+                    newlinkargs[i] = new_a1
 
-                if newops and not can_insert_here:
+            if newops:
+                if can_insert_here:
+                    block.operations.extend(newops)
+                else:
                     # cannot insert conversion operations around a single
                     # link, unless it is the only exit of this block.
                     # create a new block along the link...
-                    newblock = insert_empty_block(self.annotator.translator,
-                                                  link)
-                    # ...and do the conversions there.
-                    self.insert_link_conversions(newblock)
-                    break   # done with this link
-                else:
-                    block.operations.extend(newops)
-                    link.args[i] = a1
+                    block = insert_empty_block(self.annotator.translator,
+                                               link,
+                    # ...and store the conversions there.
+                                               newops=newops)
+                    link = block.exits[0]
+            for i, new_a1 in newlinkargs.items():
+                link.args[i] = new_a1
 
     def highlevelops(self, block, llops):
         # enumerate the HighLevelOps in a block.

Modified: pypy/dist/pypy/rpython/test/test_exception.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_exception.py	(original)
+++ pypy/dist/pypy/rpython/test/test_exception.py	Thu Jul  7 19:17:56 2005
@@ -1,6 +1,7 @@
 from pypy.translator.translator import Translator
 from pypy.rpython.lltype import *
 from pypy.rpython.rtyper import RPythonTyper
+from pypy.rpython.test.test_llinterp import interpret
 
 
 class MyException(Exception):
@@ -50,3 +51,15 @@
 
     strgerr_inst = data.ll_pyexcclass2exc(pyobjectptr(MyStrangeException))
     assert strgerr_inst.typeptr == t.rtyper.class_reprs[None].getvtable()
+
+
+def test_exception_with_arg():
+    def g(n):
+        raise OSError(n, "?")
+    def f(n):
+        try:
+            g(n)
+        except OSError, e:
+            return e.errno
+    res = interpret(f, [42])
+    assert res == 42

Modified: pypy/dist/pypy/translator/unsimplify.py
==============================================================================
--- pypy/dist/pypy/translator/unsimplify.py	(original)
+++ pypy/dist/pypy/translator/unsimplify.py	Thu Jul  7 19:17:56 2005
@@ -12,13 +12,14 @@
         newvar.concretetype = v.concretetype
     return newvar
 
-def insert_empty_block(translator, link):
+def insert_empty_block(translator, link, newops=[]):
     """Insert and return a new block along the given link."""
     vars = uniqueitems([v for v in link.args if isinstance(v, Variable)])
     mapping = {}
     for v in vars:
         mapping[v] = copyvar(translator, v)
     newblock = Block(vars)
+    newblock.operations.extend(newops)
     newblock.closeblock(Link(link.args, link.target))
     newblock.renamevariables(mapping)
     link.args[:] = vars



More information about the Pypy-commit mailing list