def do_inline(self, block, index_operation): splitlink = split_block(None, block, index_operation) afterblock = splitlink.target # these variables have to be passed along all the links in the inlined # graph because the original function needs them in the blocks after # the inlined function # for every inserted block we need a new copy of these variables, # this copy is created with the method passon_vars self.original_passon_vars = [arg for arg in block.exits[0].args if isinstance(arg, Variable)] assert afterblock.operations[0].opname == self.op.opname self.op = afterblock.operations.pop(0) #vars that need to be passed through the blocks of the inlined function linktoinlined = splitlink copiedstartblock = self.copy_block(self.graph_to_inline.startblock) copiedstartblock.isstartblock = False #find args passed to startblock of inlined function passon_args = [] for arg in self.op.args[1:]: if isinstance(arg, Constant): passon_args.append(arg) else: index = afterblock.inputargs.index(arg) passon_args.append(linktoinlined.args[index]) passon_args += self.original_passon_vars if self.op.opname == 'oosend' and not isinstance(self.op.args[1], Constant): # if we try to inline a graph defined in a superclass, the # type of 'self' on the graph differs from the current linkv = passon_args[0] inputv = copiedstartblock.inputargs[0] LINK_SELF = linkv.concretetype INPUT_SELF = inputv.concretetype if LINK_SELF != INPUT_SELF: # need to insert an upcast if ootype.isSubclass(LINK_SELF, INPUT_SELF): opname = 'ooupcast' else: assert ootype.isSubclass(INPUT_SELF, LINK_SELF) opname = 'oodowncast' v = Variable() v.concretetype = INPUT_SELF upcast = SpaceOperation(opname, [linkv], v) block.operations.append(upcast) passon_args[0] = v #rewire blocks linktoinlined.target = copiedstartblock linktoinlined.args = passon_args afterblock.inputargs = [self.op.result] + afterblock.inputargs if self.graph_to_inline.returnblock in self.entrymap: self.rewire_returnblock(afterblock) if self.graph_to_inline.exceptblock in self.entrymap: self.rewire_exceptblock(afterblock) if self.exception_guarded: assert afterblock.exits[0].exitcase is None afterblock.recloseblock(afterblock.exits[0]) afterblock.exitswitch = None self.search_for_calls(afterblock) self.search_for_calls(block)
def fromclasstype(self, vclass, llops): assert ootype.isSubclass(vclass.concretetype, META) if self.lowleveltype == ootype.Class: c_class_ = inputconst(ootype.Void, 'class_') return llops.genop('oogetfield', [vclass, c_class_], resulttype=ootype.Class) else: assert ootype.isSubclass(self.lowleveltype, vclass.concretetype) return llops.genop('oodowncast', [vclass], resulttype=self.lowleveltype)
def attach_methods_to_subclasses(self): # in ootype, it might happen that a method is defined in the # superclass but the annotator discovers that it's always called # through instances of a subclass (e.g. because of specialization, see # test_rclass.test_method_specialized_with_subclass). In that cases, # we copy the method also in the ootype.Instance of the subclass, so # that the type of v_self coincides with the type returned by # _lookup(). assert self.type_system.name == 'ootypesystem' def allclasses(TYPE, seen): '''Yield TYPE and all its subclasses''' if TYPE in seen: return seen.add(TYPE) yield TYPE for SUB in TYPE._subclasses: for T in allclasses(SUB, seen): yield T for TYPE in allclasses(ootype.ROOT, set()): for methname, meth in TYPE._methods.iteritems(): try: graph = meth.graph except AttributeError: continue SELF = graph.getargs()[0].concretetype if TYPE != SELF and ootype.isSubclass(SELF, TYPE): # the annotator found that this method has a more precise # type. Attach it to the proper subclass, so that the type # of 'self' coincides with the type returned by _lookup(), # else we might have type errors if methname not in SELF._methods: ootype.addMethods(SELF, {methname: meth})
def match_virtualizable_type(TYPE, VTYPEPTR): if isinstance(TYPE, ootype.Instance): # ootype only: any subtype may be used return ootype.isSubclass(TYPE, VTYPEPTR) else: # lltype, or ootype with a TYPE that is e.g. an ootype.Record return TYPE == VTYPEPTR
def do_inline(self, block, index_operation): splitlink = split_block(None, block, index_operation) afterblock = splitlink.target # these variables have to be passed along all the links in the inlined # graph because the original function needs them in the blocks after # the inlined function # for every inserted block we need a new copy of these variables, # this copy is created with the method passon_vars self.original_passon_vars = [arg for arg in block.exits[0].args if isinstance(arg, Variable)] n = 0 while afterblock.operations[n].opname == 'keepalive': n += 1 assert afterblock.operations[n].opname == self.op.opname self.op = afterblock.operations.pop(n) #vars that need to be passed through the blocks of the inlined function linktoinlined = splitlink copiedstartblock = self.copy_block(self.graph_to_inline.startblock) copiedstartblock.isstartblock = False #find args passed to startblock of inlined function passon_args = [] for arg in self.op.args[1:]: if isinstance(arg, Constant): passon_args.append(arg) else: index = afterblock.inputargs.index(arg) passon_args.append(linktoinlined.args[index]) passon_args += self.original_passon_vars if self.op.opname == 'oosend' and not isinstance(self.op.args[1], Constant): # if we try to inline a graph defined in a superclass, the # type of 'self' on the graph differs from the current linkv = passon_args[0] inputv = copiedstartblock.inputargs[0] LINK_SELF = linkv.concretetype INPUT_SELF = inputv.concretetype if LINK_SELF != INPUT_SELF: # need to insert an upcast assert ootype.isSubclass(LINK_SELF, INPUT_SELF) v = Variable() v.concretetype = INPUT_SELF upcast = SpaceOperation('ooupcast', [linkv], v) block.operations.append(upcast) passon_args[0] = v #rewire blocks linktoinlined.target = copiedstartblock linktoinlined.args = passon_args afterblock.inputargs = [self.op.result] + afterblock.inputargs if self.graph_to_inline.returnblock in self.entrymap: self.rewire_returnblock(afterblock) if self.graph_to_inline.exceptblock in self.entrymap: self.rewire_exceptblock(afterblock) if self.exception_guarded: assert afterblock.exits[0].exitcase is None afterblock.recloseblock(afterblock.exits[0]) afterblock.exitswitch = None self.search_for_calls(afterblock) self.search_for_calls(block)
def _translate_instance(self, OOTYPE): assert isinstance(OOTYPE, ootype.Instance) assert OOTYPE is not ootype.ROOT # Create class object if it does not already exist: if OOTYPE in self._classes: return self._classes[OOTYPE] # Create the class object first clsnm = self._pkg(self._uniq(OOTYPE._name)) clsobj = node.Class(clsnm) self._classes[OOTYPE] = clsobj # Resolve super class assert OOTYPE._superclass supercls = self._translate_superclass_of(OOTYPE) clsobj.set_super_class(supercls) # TODO --- mangle field and method names? Must be # deterministic, or use hashtable to avoid conflicts between # classes? # Add fields: self._translate_class_fields(clsobj, OOTYPE) # Add methods: for mname, mimpl in OOTYPE._methods.iteritems(): if not hasattr(mimpl, 'graph'): # Abstract method METH = mimpl._TYPE arglist = [ self.lltype_to_cts(ARG) for ARG in METH.ARGS if ARG is not ootype.Void ] returntype = self.lltype_to_cts(METH.RESULT) clsobj.add_abstract_method( jvm.Method.v(clsobj, mname, arglist, returntype)) else: # if the first argument's type is not a supertype of # this class it means that this method this method is # not really used by the class: don't render it, else # there would be a type mismatch. args = mimpl.graph.getargs() SELF = args[0].concretetype if not ootype.isSubclass(OOTYPE, SELF): continue mobj = self._function_for_graph(clsobj, mname, False, mimpl.graph) graphs = OOTYPE._lookup_graphs(mname) if len(graphs) == 1: mobj.is_final = True clsobj.add_method(mobj) # currently, we always include a special "dump" method for debugging # purposes dump_method = node.InstanceDumpMethod(self, OOTYPE, clsobj) clsobj.add_method(dump_method) self.pending_node(clsobj) return clsobj
def compute_result_annotation(self, s_value, s_type): if isinstance(s_type.const, ootype.OOType): TYPE = s_type.const else: cliClass = s_type.const TYPE = cliClass._INSTANCE assert ootype.isSubclass(s_value.ootype, TYPE) return SomeOOInstance(TYPE)
def compute_result_annotation(self, s_value, s_type): if isinstance(s_type.const, ootype.OOType): TYPE = s_type.const else: cliClass = s_type.const TYPE = cliClass._INSTANCE assert ootype.isSubclass(TYPE, s_value.ootype) return SomeOOInstance(TYPE)
def getruntime(self, expected_type): if expected_type == ootype.Class: rinstance = getinstancerepr(self.rtyper, self.classdef) return ootype.runtimeClass(rinstance.lowleveltype) else: assert ootype.isSubclass(expected_type, META) meta = self.get_meta_instance(cast_to_root_meta=False) return ootype.ooupcast(expected_type, meta)
def _toString(self): if ootype.isSubclass(self.INSTANCE, self.db.genoo.EXCEPTION): return # don't override the default ToString, which prints a traceback self.ilasm.begin_function('ToString', [], 'string', False, 'virtual', 'instance', 'default') self.ilasm.opcode('ldarg.0') self.ilasm.call('string class [pypylib]pypy.test.Result::InstanceToPython(object)') self.ilasm.ret() self.ilasm.end_function()
def render(self, ilasm): if self.is_root(self.INSTANCE): return self.ilasm = ilasm self.gen = CLIBaseGenerator(self.db, ilasm) if self.namespace: ilasm.begin_namespace(self.namespace) ilasm.begin_class(self.name, self.get_base_class(), abstract=self.is_abstract()) for f_name, (f_type, f_default) in self.INSTANCE._fields.iteritems(): cts_type = self.cts.lltype_to_cts(f_type) f_name = self.cts.escape_name(f_name) if cts_type != CTS.types.void: ilasm.field(f_name, cts_type) self._ctor() self._toString() for m_name, m_meth in self.INSTANCE._methods.iteritems(): if hasattr(m_meth, 'graph'): # if the first argument's type is not a supertype of # this class it means that this method this method is # not really used by the class: don't render it, else # there would be a type mismatch. args = m_meth.graph.getargs() SELF = args[0].concretetype if not ootype.isSubclass(self.INSTANCE, SELF): continue f = self.db.genoo.Function(self.db, m_meth.graph, m_name, is_method=True) f.render(ilasm) else: # abstract method METH = m_meth._TYPE arglist = [(self.cts.lltype_to_cts(ARG), 'v%d' % i) for i, ARG in enumerate(METH.ARGS) if ARG is not ootype.Void] returntype = self.cts.lltype_to_cts(METH.RESULT) ilasm.begin_function(m_name, arglist, returntype, False, 'virtual') #, 'abstract') ilasm.add_comment('abstract method') if isinstance(METH.RESULT, ootype.OOType): ilasm.opcode('ldnull') else: push_constant(self.db, METH.RESULT, 0, self.gen) ilasm.opcode('ret') ilasm.end_function() ilasm.end_class() if self.namespace: ilasm.end_namespace()
def simple_call(self, *s_args): from pypy.translator.cli.query import get_cli_class DELEGATE = get_cli_class('System.Delegate')._INSTANCE if ootype.isSubclass(self.ootype, DELEGATE): s_invoke = self.getattr(immutablevalue('Invoke')) return s_invoke.simple_call(*s_args) else: # cannot call a non-delegate return SomeObject.simple_call(self, *s_args)
def _translate_instance(self, OOTYPE): assert isinstance(OOTYPE, ootype.Instance) assert OOTYPE is not ootype.ROOT # Create class object if it does not already exist: if OOTYPE in self._classes: return self._classes[OOTYPE] # Create the class object first clsnm = self._pkg(self._uniq(OOTYPE._name)) clsobj = node.Class(clsnm) self._classes[OOTYPE] = clsobj # Resolve super class assert OOTYPE._superclass supercls = self._translate_superclass_of(OOTYPE) clsobj.set_super_class(supercls) # TODO --- mangle field and method names? Must be # deterministic, or use hashtable to avoid conflicts between # classes? # Add fields: self._translate_class_fields(clsobj, OOTYPE) # Add methods: for mname, mimpl in OOTYPE._methods.iteritems(): if not hasattr(mimpl, 'graph'): # Abstract method METH = mimpl._TYPE arglist = [self.lltype_to_cts(ARG) for ARG in METH.ARGS if ARG is not ootype.Void] returntype = self.lltype_to_cts(METH.RESULT) clsobj.add_abstract_method(jvm.Method.v( clsobj, mname, arglist, returntype)) else: # if the first argument's type is not a supertype of # this class it means that this method this method is # not really used by the class: don't render it, else # there would be a type mismatch. args = mimpl.graph.getargs() SELF = args[0].concretetype if not ootype.isSubclass(OOTYPE, SELF): continue mobj = self._function_for_graph( clsobj, mname, False, mimpl.graph) graphs = OOTYPE._lookup_graphs(mname) if len(graphs) == 1: mobj.is_final = True clsobj.add_method(mobj) # currently, we always include a special "dump" method for debugging # purposes dump_method = node.InstanceDumpMethod(self, OOTYPE, clsobj) clsobj.add_method(dump_method) self.pending_node(clsobj) return clsobj
def render(self, ilasm): if self.is_root(self.INSTANCE): return self.ilasm = ilasm self.gen = CLIBaseGenerator(self.db, ilasm) if self.namespace: ilasm.begin_namespace(self.namespace) ilasm.begin_class(self.name, self.get_base_class(), abstract=self.is_abstract()) for f_name, (f_type, f_default) in self.INSTANCE._fields.iteritems(): cts_type = self.cts.lltype_to_cts(f_type) f_name = self.cts.escape_name(f_name) if cts_type != CTS.types.void: ilasm.field(f_name, cts_type) self._ctor() self._toString() for m_name, m_meth in self.INSTANCE._methods.iteritems(): if hasattr(m_meth, 'graph'): # if the first argument's type is not a supertype of # this class it means that this method this method is # not really used by the class: don't render it, else # there would be a type mismatch. args = m_meth.graph.getargs() SELF = args[0].concretetype if not ootype.isSubclass(self.INSTANCE, SELF): continue f = self.db.genoo.Function(self.db, m_meth.graph, m_name, is_method = True) f.render(ilasm) else: # abstract method METH = m_meth._TYPE arglist = [(self.cts.lltype_to_cts(ARG), 'v%d' % i) for i, ARG in enumerate(METH.ARGS) if ARG is not ootype.Void] returntype = self.cts.lltype_to_cts(METH.RESULT) ilasm.begin_function(m_name, arglist, returntype, False, 'virtual') #, 'abstract') ilasm.add_comment('abstract method') if isinstance(METH.RESULT, ootype.OOType): ilasm.opcode('ldnull') else: push_constant(self.db, METH.RESULT, 0, self.gen) ilasm.opcode('ret') ilasm.end_function() ilasm.end_class() if self.namespace: ilasm.end_namespace()
class __extend__(pairtype(SomeOOInstance, SomeInteger)): def getitem((ooinst, index)): if ooinst.ootype._isArray: return SomeOOInstance(ooinst.ootype._ELEMENT) return s_ImpossibleValue def setitem((ooinst, index), s_value): if ooinst.ootype._isArray: if s_value is annmodel.s_None: return s_None ELEMENT = ooinst.ootype._ELEMENT VALUE = s_value.ootype assert ootype.isSubclass(VALUE, ELEMENT) return s_None return s_ImpossibleValue
def oodowncast(I, i): assert isinstance(I.const, ootype.Instance) if ootype.isSubclass(I.const, i.ootype): return SomeOOInstance(I.const) else: raise AnnotatorError, 'Cannot cast %s to %s' % (i.ootype, I.const)
def is_exception_instance(self, INSTANCE): return ootype.isSubclass(INSTANCE, self._EXCEPTION_INST)
def castable(self, TO, var): return ootype.isSubclass(lltype.typeOf(var), TO)