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
10
class ExceptionData(AbstractExceptionData):
11
"""Public information for the code generators to help with exceptions."""
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)
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])
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])
34
def make_pyexcclass2exc(self, rtyper):
35
# ll_pyexcclass2exc(python_exception_class) -> exception_instance
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'):
43
cls = clsdef.classdesc.pyobj
44
if cls in self.standardexceptions and cls not in FORCE_ATTRIBUTES_INTO_CLASSES:
46
assert not clsdef.attrs, (
47
"%r should not have grown attributes" % (cls,))
49
is_standard = (cls.__module__ == 'exceptions'
52
example = self.get_standard_ll_exc_instance(rtyper, clsdef)
55
# assert cls.__module__ != 'exceptions', (
56
# "built-in exceptions should not grow attributes")
57
r_inst = rclass.getinstancerepr(rtyper, None)
59
default_excinst = malloc(self.lltype_of_exception_value.TO,
61
default_excinst.typeptr = r_inst.rclass.getvtable()
63
# build the table in order base classes first, subclasses last
67
for base in cls.__bases__:
69
sortedtable.append((cls, table[cls]))
71
for cls in table.keys():
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
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)))
90
initial_value_of_i = len(pycls2excinst)-1
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.
96
i = initial_value_of_i
98
if PyErr_GivenExceptionMatches(python_exception_class,
99
pycls2excinst[i].pycls):
100
return pycls2excinst[i].excinst
102
return default_excinst
104
s_pyobj = annmodel.SomePtr(Ptr(PyObject))
105
helper_fn = rtyper.annotate_helper_fn(ll_pyexcclass2exc, [s_pyobj])
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)