~ubuntu-branches/ubuntu/karmic/pypy/karmic

« back to all changes in this revision

Viewing changes to pypy/rpython/lltypesystem/exceptiondata.py

  • Committer: Bazaar Package Importer
  • Author(s): Alexandre Fayolle
  • Date: 2007-04-13 09:33:09 UTC
  • Revision ID: james.westby@ubuntu.com-20070413093309-yoojh4jcoocu2krz
Tags: upstream-1.0.0
ImportĀ upstreamĀ versionĀ 1.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from pypy.annotation import model as annmodel
 
2
from pypy.rpython.lltypesystem import rclass
 
3
from pypy.rpython.lltypesystem.lltype import \
 
4
     Array, malloc, Ptr, PyObject, pyobjectptr, \
 
5
     FuncType, functionptr, Signed
 
6
from pypy.rpython.exceptiondata import AbstractExceptionData
 
7
from pypy.rpython.extfunctable import standardexceptions
 
8
from pypy.annotation.classdef import FORCE_ATTRIBUTES_INTO_CLASSES
 
9
 
 
10
class ExceptionData(AbstractExceptionData):
 
11
    """Public information for the code generators to help with exceptions."""
 
12
 
 
13
    def make_helpers(self, rtyper):
 
14
        # create helper functionptrs
 
15
        self.fn_exception_match  = self.make_exception_matcher(rtyper)
 
16
        self.fn_type_of_exc_inst = self.make_type_of_exc_inst(rtyper)
 
17
        self.fn_pyexcclass2exc   = self.make_pyexcclass2exc(rtyper)
 
18
        self.fn_raise_OSError    = self.make_raise_OSError(rtyper)
 
19
 
 
20
    def make_exception_matcher(self, rtyper):
 
21
        # ll_exception_matcher(real_exception_vtable, match_exception_vtable)
 
22
        s_typeptr = annmodel.SomePtr(self.lltype_of_exception_type)
 
23
        helper_fn = rtyper.annotate_helper_fn(rclass.ll_issubclass, [s_typeptr, s_typeptr])
 
24
        return helper_fn
 
25
 
 
26
 
 
27
    def make_type_of_exc_inst(self, rtyper):
 
28
        # ll_type_of_exc_inst(exception_instance) -> exception_vtable
 
29
        s_excinst = annmodel.SomePtr(self.lltype_of_exception_value)
 
30
        helper_fn = rtyper.annotate_helper_fn(rclass.ll_type, [s_excinst])
 
31
        return helper_fn
 
32
 
 
33
 
 
34
    def make_pyexcclass2exc(self, rtyper):
 
35
        # ll_pyexcclass2exc(python_exception_class) -> exception_instance
 
36
        table = {}
 
37
        Exception_def = rtyper.annotator.bookkeeper.getuniqueclassdef(Exception)
 
38
        for clsdef in rtyper.class_reprs:
 
39
            if (clsdef and clsdef is not Exception_def
 
40
                and clsdef.issubclass(Exception_def)):
 
41
                if not hasattr(clsdef.classdesc, 'pyobj'):
 
42
                    continue
 
43
                cls = clsdef.classdesc.pyobj
 
44
                if cls in self.standardexceptions and cls not in FORCE_ATTRIBUTES_INTO_CLASSES:
 
45
                    is_standard = True
 
46
                    assert not clsdef.attrs, (
 
47
                        "%r should not have grown attributes" % (cls,))
 
48
                else:
 
49
                    is_standard = (cls.__module__ == 'exceptions'
 
50
                                   and not clsdef.attrs)
 
51
                if is_standard:
 
52
                    example = self.get_standard_ll_exc_instance(rtyper, clsdef)
 
53
                    table[cls] = example
 
54
                #else:
 
55
                #    assert cls.__module__ != 'exceptions', (
 
56
                #        "built-in exceptions should not grow attributes")
 
57
        r_inst = rclass.getinstancerepr(rtyper, None)
 
58
        r_inst.setup()
 
59
        default_excinst = malloc(self.lltype_of_exception_value.TO,
 
60
                                 immortal=True)
 
61
        default_excinst.typeptr = r_inst.rclass.getvtable()
 
62
 
 
63
        # build the table in order base classes first, subclasses last
 
64
        sortedtable = []
 
65
        def add_class(cls):
 
66
            if cls in table:
 
67
                for base in cls.__bases__:
 
68
                    add_class(base)
 
69
                sortedtable.append((cls, table[cls]))
 
70
                del table[cls]
 
71
        for cls in table.keys():
 
72
            add_class(cls)
 
73
        assert table == {}
 
74
        #print sortedtable
 
75
 
 
76
        A = Array(('pycls', Ptr(PyObject)),
 
77
                  ('excinst', self.lltype_of_exception_value))
 
78
        pycls2excinst = malloc(A, len(sortedtable), immortal=True)
 
79
        for i in range(len(sortedtable)):
 
80
            cls, example = sortedtable[i]
 
81
            pycls2excinst[i].pycls   = pyobjectptr(cls)
 
82
            pycls2excinst[i].excinst = example
 
83
 
 
84
        FUNCTYPE = FuncType([Ptr(PyObject), Ptr(PyObject)], Signed)
 
85
        PyErr_GivenExceptionMatches = functionptr(
 
86
            FUNCTYPE, "PyErr_GivenExceptionMatches", external="C",
 
87
            _callable=lambda pyobj1, pyobj2:
 
88
                          int(issubclass(pyobj1._obj.value, pyobj2._obj.value)))
 
89
 
 
90
        initial_value_of_i = len(pycls2excinst)-1
 
91
 
 
92
        def ll_pyexcclass2exc(python_exception_class):
 
93
            """Return an RPython instance of the best approximation of the
 
94
            Python exception identified by its Python class.
 
95
            """
 
96
            i = initial_value_of_i
 
97
            while i >= 0:
 
98
                if PyErr_GivenExceptionMatches(python_exception_class,
 
99
                                               pycls2excinst[i].pycls):
 
100
                    return pycls2excinst[i].excinst
 
101
                i -= 1
 
102
            return default_excinst
 
103
 
 
104
        s_pyobj = annmodel.SomePtr(Ptr(PyObject))
 
105
        helper_fn = rtyper.annotate_helper_fn(ll_pyexcclass2exc, [s_pyobj])
 
106
        return helper_fn
 
107
 
 
108
    def get_standard_ll_exc_instance(self, rtyper, clsdef):
 
109
        r_inst = rclass.getinstancerepr(rtyper, clsdef)
 
110
        example = r_inst.get_reusable_prebuilt_instance()
 
111
        example = rclass.ll_cast_to_object(example)
 
112
        return example