def test_obj_obj_add(): def f(x,y): return x+y _1L = pyobjectptr(1L) _2L = pyobjectptr(2L) res = interpret(f, [_1L, _2L], someobjects=True) assert res._obj.value == 3L
def test_isinstance_obj(self): _1 = lltype.pyobjectptr(1) def f(x): return isinstance(x, int) res = self.interpret(f, [_1], someobjects=True) assert res is True _1_0 = lltype.pyobjectptr(1.0) res = self.interpret(f, [_1_0], someobjects=True) assert res is False
class __extend__(pairtype(FloatRepr, PyObjRepr)): def convert_from_to((r_from, r_to), v, llops): if r_from.lowleveltype == Float: return llops.gencapicall('PyFloat_FromDouble', [v], resulttype=pyobj_repr, _callable=lambda x: pyobjectptr(x)) return NotImplemented
def test_obj_obj_is(): def f(x, y): return x is y o = pyobjectptr(object()) res = interpret(f, [o, o], someobjects=True) assert res is True
def predeclare_exception_data(db, rtyper): # Exception-related types and constants exceptiondata = rtyper.getexceptiondata() exctransformer = db.exctransformer yield ('RPYTHON_EXCEPTION_VTABLE', exceptiondata.lltype_of_exception_type) yield ('RPYTHON_EXCEPTION', exceptiondata.lltype_of_exception_value) yield ('RPYTHON_EXCEPTION_MATCH', exceptiondata.fn_exception_match) yield ('RPYTHON_TYPE_OF_EXC_INST', exceptiondata.fn_type_of_exc_inst) yield ('RPYTHON_RAISE_OSERROR', exceptiondata.fn_raise_OSError) if not db.standalone: yield ('RPYTHON_PYEXCCLASS2EXC', exceptiondata.fn_pyexcclass2exc) yield ('RPyExceptionOccurred1', exctransformer.rpyexc_occured_ptr.value) yield ('RPyFetchExceptionType', exctransformer.rpyexc_fetch_type_ptr.value) yield ('RPyFetchExceptionValue', exctransformer.rpyexc_fetch_value_ptr.value) yield ('RPyClearException', exctransformer.rpyexc_clear_ptr.value) yield ('RPyRaiseException', exctransformer.rpyexc_raise_ptr.value) for pyexccls in exceptiondata.standardexceptions: exc_llvalue = exceptiondata.fn_pyexcclass2exc( lltype.pyobjectptr(pyexccls)) # strange naming here because the macro name must be # a substring of PyExc_%s name = pyexccls.__name__ if pyexccls.__module__ != 'exceptions': name = '%s_%s' % (pyexccls.__module__.replace('.', '__'), name) yield ('RPyExc_%s' % name, exc_llvalue)
def predeclare_exception_data(db, rtyper): # Exception-related types and constants exceptiondata = rtyper.getexceptiondata() exctransformer = db.exctransformer yield ('RPYTHON_EXCEPTION_VTABLE', exceptiondata.lltype_of_exception_type) yield ('RPYTHON_EXCEPTION', exceptiondata.lltype_of_exception_value) yield ('RPYTHON_EXCEPTION_MATCH', exceptiondata.fn_exception_match) yield ('RPYTHON_TYPE_OF_EXC_INST', exceptiondata.fn_type_of_exc_inst) yield ('RPYTHON_RAISE_OSERROR', exceptiondata.fn_raise_OSError) if db.cpython_extension: yield ('RPYTHON_PYEXCCLASS2EXC', exceptiondata.fn_pyexcclass2exc) yield ('RPyExceptionOccurred1', exctransformer.rpyexc_occured_ptr.value) yield ('RPyFetchExceptionType', exctransformer.rpyexc_fetch_type_ptr.value) yield ('RPyFetchExceptionValue', exctransformer.rpyexc_fetch_value_ptr.value) yield ('RPyClearException', exctransformer.rpyexc_clear_ptr.value) yield ('RPyRaiseException', exctransformer.rpyexc_raise_ptr.value) for pyexccls in exceptiondata.standardexceptions: exc_llvalue = exceptiondata.fn_pyexcclass2exc( lltype.pyobjectptr(pyexccls)) # strange naming here because the macro name must be # a substring of PyExc_%s name = pyexccls.__name__ if pyexccls.__module__ != 'exceptions': name = '%s_%s' % (pyexccls.__module__.replace('.', '__'), name) yield ('RPyExc_%s' % name, exc_llvalue)
def initialize_const(self, p, value): if isinstance(value, self.ctype): value = value.value if extregistry.is_registered(value): entry = extregistry.lookup(value) if hasattr(entry, 'get_ll_pyobjectptr'): p.c_data[0] = entry.get_ll_pyobjectptr(self.rtyper) return p.c_data[0] = lltype.pyobjectptr(value)
class __extend__(pairtype(AbstractStringRepr, PyObjRepr)): def convert_from_to((r_from, r_to), v, llops): string_repr = llops.rtyper.type_system.rstr.string_repr v = llops.convertvar(v, r_from, string_repr) cchars = inputconst(Void, "chars") # xxx put in table return llops.gencapicall( 'PyString_FromRPyString', [v], resulttype=pyobj_repr, _callable=lambda v: pyobjectptr(''.join(v.chars)))
def find_exception(self, exc): assert isinstance(exc, LLException) klass, inst = exc.args[0], exc.args[1] exdata = self.typer.getexceptiondata() frame = self.frame_class(None, [], self) for cls in enumerate_exceptions_top_down(): evalue = frame.op_direct_call(exdata.fn_pyexcclass2exc, lltype.pyobjectptr(cls)) etype = frame.op_direct_call(exdata.fn_type_of_exc_inst, evalue) if etype == klass: return cls raise ValueError, "couldn't match exception"
def build(cache, typedef): if typedef in (Function.typedef, GetSetProperty.typedef): raise ValueError("cannot wrap at run-time an interpreter object " "of type %r" % (typedef.name,)) space = cache.space objects = {} for name, value in typedef.rawdict.items(): #if name.startswith('__') and name.endswith('__'): # raise NotImplementedError("missing support for special " # "attributes in TypeDef-to-CPython " # "converter (%s.%s)" % ( # typedef.name, name)) w_value = space.wrap(value) objects[name] = lltype.pyobjectptr(w_value.value) typeintf = CPyTypeInterface(typedef.name, objects, typedef.acceptable_as_base_class) return typeintf
def llvalue_from_constant(c): try: T = c.concretetype except AttributeError: T = PyObjPtr if T == PyObjPtr and not isinstance(c.value, lltype._ptr): return lltype.pyobjectptr(c.value) else: if T == lltype.Void: return None else: ACTUAL_TYPE = lltype.typeOf(c.value) # If the type is still uncomputed, we can't make this # check. Something else will blow up instead, probably # very confusingly. if not is_pointer_to_forward_ref(ACTUAL_TYPE): assert ACTUAL_TYPE == T return c.value
def nameof(self, obj, debug=None): if debug: stackentry = debug, obj else: stackentry = obj self.debugstack = (self.debugstack, stackentry) try: try: self.translator.rtyper # check for presence entry = extregistry.lookup(obj) getter = entry.get_ll_pyobjectptr except (KeyError, AttributeError): # common case: 'p' is a _pyobject p = pyobjectptr(obj) else: # 'p' should be a PyStruct pointer, i.e. a _pyobjheader p = getter(self.translator.rtyper) node = self.db.getcontainernode(p._obj) finally: self.debugstack, x = self.debugstack assert x is stackentry return node.exported_name
# # _________________________ Conversions _________________________ py_to_ll_conversion_functions = { UnsignedLongLong: ('RPyLong_AsUnsignedLongLong', lambda pyo: r_ulonglong(pyo._obj.value)), SignedLongLong: ('RPyLong_AsLongLong', lambda pyo: r_longlong(pyo._obj.value)), Unsigned: ('RPyLong_AsUnsignedLong', lambda pyo: r_uint(pyo._obj.value)), Signed: ('PyInt_AsLong', lambda pyo: int(pyo._obj.value)) } ll_to_py_conversion_functions = { UnsignedLongLong: ('PyLong_FromUnsignedLongLong', lambda i: pyobjectptr(i)), SignedLongLong: ('PyLong_FromLongLong', lambda i: pyobjectptr(i)), Unsigned: ('PyLong_FromUnsignedLong', lambda i: pyobjectptr(i)), Signed: ('PyInt_FromLong', lambda i: pyobjectptr(i)), } class __extend__(pairtype(PyObjRepr, IntegerRepr)): def convert_from_to((r_from, r_to), v, llops): tolltype = r_to.lowleveltype fnname, callable = py_to_ll_conversion_functions[tolltype] return llops.gencapicall(fnname, [v], resulttype=r_to, _callable=callable)
def getentrypointptr(self, obj=None): if obj is None: obj = self.entrypoint return lltype.pyobjectptr(obj)
def make_pyexcclass2exc(self, rtyper): # ll_pyexcclass2exc(python_exception_class) -> exception_instance table = {} Exception_def = rtyper.annotator.bookkeeper.getuniqueclassdef( Exception) for clsdef in rtyper.class_reprs: if (clsdef and clsdef is not Exception_def and clsdef.issubclass(Exception_def)): if not hasattr(clsdef.classdesc, 'pyobj'): continue cls = clsdef.classdesc.pyobj if cls in self.standardexceptions and cls not in FORCE_ATTRIBUTES_INTO_CLASSES: is_standard = True assert not clsdef.attrs, ( "%r should not have grown attributes" % (cls, )) else: is_standard = (cls.__module__ == 'exceptions' and not clsdef.attrs) if is_standard: example = self.get_standard_ll_exc_instance(rtyper, clsdef) table[cls] = example #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, immortal=True) default_excinst.typeptr = r_inst.rclass.getvtable() # build the table in order base classes first, subclasses last sortedtable = [] def add_class(cls): if cls in table: for base in cls.__bases__: add_class(base) sortedtable.append((cls, table[cls])) del table[cls] for cls in table.keys(): add_class(cls) assert table == {} #print sortedtable A = Array(('pycls', Ptr(PyObject)), ('excinst', self.lltype_of_exception_value)) pycls2excinst = malloc(A, len(sortedtable), immortal=True) for i in range(len(sortedtable)): cls, example = sortedtable[i] pycls2excinst[i].pycls = pyobjectptr(cls) pycls2excinst[i].excinst = example FUNCTYPE = FuncType([Ptr(PyObject), Ptr(PyObject)], Signed) PyErr_GivenExceptionMatches = functionptr( FUNCTYPE, "PyErr_GivenExceptionMatches", external="C", _callable=lambda pyobj1, pyobj2: int( issubclass(pyobj1._obj.value, pyobj2._obj.value))) initial_value_of_i = len(pycls2excinst) - 1 def ll_pyexcclass2exc(python_exception_class): """Return an RPython instance of the best approximation of the Python exception identified by its Python class. """ i = initial_value_of_i while i >= 0: if PyErr_GivenExceptionMatches(python_exception_class, pycls2excinst[i].pycls): return pycls2excinst[i].excinst i -= 1 return default_excinst s_pyobj = annmodel.SomePtr(Ptr(PyObject)) helper_fn = rtyper.annotate_helper_fn(ll_pyexcclass2exc, [s_pyobj]) return helper_fn
def translator2database(translator, entrypoint): pf = lltype.pyobjectptr(entrypoint) db = LowLevelDatabase(translator) db.get(pf) db.complete() return db, pf
def interpret(self, t, graph, *args): interp = LLInterpreter(t.rtyper) result = interp.eval_graph(graph, [lltype.pyobjectptr(arg) for arg in args]) return result._obj.value
else: raise ValueError # # _________________________ Conversions _________________________ py_to_ll_conversion_functions = { UnsignedLongLong: ('RPyLong_AsUnsignedLongLong', lambda pyo: r_ulonglong(pyo._obj.value)), SignedLongLong: ('RPyLong_AsLongLong', lambda pyo: r_longlong(pyo._obj.value)), Unsigned: ('RPyLong_AsUnsignedLong', lambda pyo: r_uint(pyo._obj.value)), Signed: ('PyInt_AsLong', lambda pyo: int(pyo._obj.value)) } ll_to_py_conversion_functions = { UnsignedLongLong: ('PyLong_FromUnsignedLongLong', lambda i: pyobjectptr(i)), SignedLongLong: ('PyLong_FromLongLong', lambda i: pyobjectptr(i)), Unsigned: ('PyLong_FromUnsignedLong', lambda i: pyobjectptr(i)), Signed: ('PyInt_FromLong', lambda i: pyobjectptr(i)), } class __extend__(pairtype(PyObjRepr, IntegerRepr)): def convert_from_to((r_from, r_to), v, llops): tolltype = r_to.lowleveltype fnname, callable = py_to_ll_conversion_functions[tolltype] return llops.gencapicall(fnname, [v], resulttype=r_to, _callable=callable) class __extend__(pairtype(IntegerRepr, PyObjRepr)): def convert_from_to((r_from, r_to), v, llops):
def convert_const(self, value): return pyobjectptr(value)
def make_pyexcclass2exc(self, rtyper): # ll_pyexcclass2exc(python_exception_class) -> exception_instance table = {} Exception_def = rtyper.annotator.bookkeeper.getuniqueclassdef(Exception) for clsdef in rtyper.class_reprs: if clsdef and clsdef is not Exception_def and clsdef.issubclass(Exception_def): if not hasattr(clsdef.classdesc, "pyobj"): continue cls = clsdef.classdesc.pyobj if cls in self.standardexceptions and cls not in FORCE_ATTRIBUTES_INTO_CLASSES: is_standard = True assert not clsdef.attrs, "%r should not have grown attributes" % (cls,) else: is_standard = cls.__module__ == "exceptions" and not clsdef.attrs if is_standard: example = self.get_standard_ll_exc_instance(rtyper, clsdef) table[cls] = example # 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, immortal=True) default_excinst.typeptr = r_inst.rclass.getvtable() # build the table in order base classes first, subclasses last sortedtable = [] def add_class(cls): if cls in table: for base in cls.__bases__: add_class(base) sortedtable.append((cls, table[cls])) del table[cls] for cls in table.keys(): add_class(cls) assert table == {} # print sortedtable A = Array(("pycls", Ptr(PyObject)), ("excinst", self.lltype_of_exception_value)) pycls2excinst = malloc(A, len(sortedtable), immortal=True) for i in range(len(sortedtable)): cls, example = sortedtable[i] pycls2excinst[i].pycls = pyobjectptr(cls) pycls2excinst[i].excinst = example FUNCTYPE = FuncType([Ptr(PyObject), Ptr(PyObject)], Signed) PyErr_GivenExceptionMatches = functionptr( FUNCTYPE, "PyErr_GivenExceptionMatches", external="C", _callable=lambda pyobj1, pyobj2: int(issubclass(pyobj1._obj.value, pyobj2._obj.value)), ) initial_value_of_i = len(pycls2excinst) - 1 def ll_pyexcclass2exc(python_exception_class): """Return an RPython instance of the best approximation of the Python exception identified by its Python class. """ i = initial_value_of_i while i >= 0: if PyErr_GivenExceptionMatches(python_exception_class, pycls2excinst[i].pycls): return pycls2excinst[i].excinst i -= 1 return default_excinst s_pyobj = annmodel.SomePtr(Ptr(PyObject)) helper_fn = rtyper.annotate_helper_fn(ll_pyexcclass2exc, [s_pyobj]) return helper_fn
def build_pytypeobject(r_inst): rtyper = r_inst.rtyper cache = rtyper.classdef_to_pytypeobject try: return cache[r_inst.classdef] except KeyError: for parentdef in r_inst.classdef.getmro(): cpytype = parentdef._cpy_exported_type_ if cpytype is not None: break else: # for classes that cannot be exported at all return lltype.nullptr(lltype.PyObject) from pypy.rpython.lltypesystem.rclass import CPYOBJECTPTR from pypy.rpython.rtyper import LowLevelOpList typetype = lltype.pyobjectptr(type) # XXX default tp_new should go away # make the graph of tp_new manually v1 = Variable('tp'); v1.concretetype = lltype.Ptr(PY_TYPE_OBJECT) v2 = Variable('args'); v2.concretetype = PyObjPtr v3 = Variable('kwds'); v3.concretetype = PyObjPtr block = Block([v1, v2, v3]) llops = LowLevelOpList(None) v4 = r_inst.new_instance(llops, v_cpytype = v1) v5 = llops.genop('cast_pointer', [v4], resulttype = PyObjPtr) block.operations = list(llops) tp_new_graph = FunctionGraph('ll_tp_new', block) block.closeblock(Link([v5], tp_new_graph.returnblock)) tp_new_graph.getreturnvar().concretetype = v5.concretetype # build the PyTypeObject structure pytypeobj = lltype.malloc(PY_TYPE_OBJECT, flavor='cpy', extra_args=(typetype,)) name = cpytype.name T = lltype.FixedSizeArray(lltype.Char, len(name)+1) p = lltype.malloc(T, immortal=True) for i in range(len(name)): p[i] = name[i] p[len(name)] = '\x00' pytypeobj.c_tp_name = lltype.direct_arrayitems(p) pytypeobj.c_tp_basicsize = llmemory.sizeof(r_inst.lowleveltype.TO) if cpytype.subclassable and False: # XXX deallocation of subclass object segfaults! pytypeobj.c_tp_flags = CDefinedIntSymbolic('''(Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES | Py_TPFLAGS_BASETYPE)''') else: pytypeobj.c_tp_flags = CDefinedIntSymbolic('''(Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES)''') pytypeobj.c_tp_new = rtyper.type_system.getcallable(tp_new_graph) pytypeobj.c_tp_dealloc = rtyper.annotate_helper_fn(ll_tp_dealloc, [PyObjPtr]) pytypeobj.c_tp_as_number = lltype.malloc(PyNumberMethods, immortal=True) pytypeobj.c_tp_as_sequence = lltype.malloc(PySequenceMethods, immortal=True) pytypeobj.c_tp_as_mapping = lltype.malloc(PyMappingMethods, immortal=True) result = lltype.cast_pointer(PyObjPtr, pytypeobj) # the llsetup function that will store the 'objects' into the # type's tp_dict Py_TPFLAGS_HEAPTYPE = CDefinedIntSymbolic('Py_TPFLAGS_HEAPTYPE') if cpytype.objects: objects = [(lltype.pyobjectptr(name), value) for name, value in cpytype.objects.items() if name != '__new__'] if '__new__' in cpytype.objects: new = cpytype.objects['__new__']._obj.value objects.append((lltype.pyobjectptr('__new__'), lltype.pyobjectptr(staticmethod(new)))) def ll_type_setup(p): tp = lltype.cast_pointer(lltype.Ptr(PY_TYPE_OBJECT), p) old_flags = tp.c_tp_flags tp.c_tp_flags |= Py_TPFLAGS_HEAPTYPE for name, value in objects: llop.setattr(PyObjPtr, tp, name, value) tp.c_tp_flags = old_flags result._obj.setup_fnptr = rtyper.annotate_helper_fn(ll_type_setup, [PyObjPtr]) cache[r_inst.classdef] = result return result