def test_call_classes(): class A: pass class B(A): pass def f(i): if i == 1: cls = B else: cls = A return cls() res = interpret(f, [0], type_system='ootype') assert ootype.dynamicType(res)._name.split(".")[-1] == 'A' res = interpret(f, [1], type_system='ootype') assert ootype.dynamicType(res)._name.split(".")[-1] == 'B'
def declare_constant_instance(self, const): # const.concretetype is Instance if const in self.declarations: return self.declarations[const][0] name = "+const" + str(self.constcount) + "+" INST = dynamicType(const.value) self.declare_class(INST) inst = oodowncast(INST, const.value) cls = clrepr(INST) const_declaration = [] const_declaration.append("(defvar %s nil)" % clrepr(name, True)) const_declaration.append("(setf %s (make-instance %s))" % (clrepr(name, True), clrepr(cls, True))) fields = INST._allfields() for fieldname in fields: fieldvalue = getattr(inst, fieldname) if isinstance(fieldvalue, _class): self.declare_any(fieldvalue._INSTANCE) fieldvaluerepr = clrepr(getattr(inst, fieldname)) ### XXX const_declaration.append("(setf (slot-value %s '%s) %s)" % (clrepr(name, True), clrepr(fieldname, True), clrepr(fieldvaluerepr, True))) const_declaration = "\n".join(const_declaration) self.declarations[const] = (name, const_declaration) self.constcount += 1 return name
def _find_exception_type(block): #XXX slightly brittle: find the exception type for simple cases #(e.g. if you do only raise XXXError) by doing pattern matching currvar = block.exits[0].args[1] ops = block.operations i = len(ops) - 1 while True: if isinstance(currvar, Constant): value = currvar.value if isinstance(typeOf(value), ootype.Instance): TYPE = ootype.dynamicType(value) else: TYPE = typeOf(normalizeptr(value)) return TYPE, block.exits[0] if i < 0: return None, None op = ops[i] i -= 1 if op.opname in ("same_as", "cast_pointer", "ooupcast", "oodowncast") and op.result is currvar: currvar = op.args[0] elif op.opname == "malloc" and op.result is currvar: return Ptr(op.args[0].value), block.exits[0] elif op.opname == "new" and op.result is currvar: return op.args[0].value, block.exits[0]
def render(self): codef = CodeFormatter(self.gen) # XXX use CodeFormatter throughout here yield self.render_fileout_header( "%s class" % self._class_name, "internals") message = Message("setupConstants") yield codef.format(message.with_args([])) yield " Constants := Dictionary new." for const, const_id in self.constants.iteritems(): INST = dynamicType(const.value) inst = oodowncast(INST, const.value) field_names = INST._allfields().keys() field_values = [getattr(inst, f) for f in field_names] new = Message("new").send_to(INST, []) init_message = Message("fieldInit").send_to(new, field_values) yield " Constants at: '%s' put: %s." \ % (const_id, codef.format(init_message)) yield "! !" yield "" yield self.render_fileout_header( "%s class" % self._class_name, "internals") arg = CustomVariable("constId") get_message = Message("getConstant") yield codef.format(get_message.with_args([arg])) yield " ^ Constants at: constId" yield "! !"
def _find_exception_type(block): #XXX slightly brittle: find the exception type for simple cases #(e.g. if you do only raise XXXError) by doing pattern matching currvar = block.exits[0].args[1] ops = block.operations i = len(ops)-1 while True: if isinstance(currvar, Constant): value = currvar.value if isinstance(typeOf(value), ootype.Instance): TYPE = ootype.dynamicType(value) else: TYPE = typeOf(normalizeptr(value)) return TYPE, block.exits[0] if i < 0: return None, None op = ops[i] i -= 1 if op.opname in ("same_as", "cast_pointer", "ooupcast", "oodowncast") and op.result is currvar: currvar = op.args[0] elif op.opname == "malloc" and op.result is currvar: return Ptr(op.args[0].value), block.exits[0] elif op.opname == "new" and op.result is currvar: return op.args[0].value, block.exits[0]
def read_attr(self, value, attr): value = ootype.oodowncast(ootype.dynamicType(value), value) return getattr(value, "o" + attr)
def class_name(self, value): return ootype.dynamicType(value)._name.split(".")[-1]
def dependencies(self): # Important: Field initializers for the *runtime* type return [FieldInitializerNode(self.gen, dynamicType(c.value)) for c in self.constants.iterkeys()] + \ [ClassNode(self.gen, self.CONSTANTS, class_vars=["Constants"])]
def render_block(self, block): if self.loops.has_key(block): if not self.loops[block]: yield '"skip1"' return yield "[" if block.exitswitch is c_last_exception: yield "[" formatter = OpFormatter(self.gen, self) for op in block.operations: yield "%s." % formatter.format(op) if len(block.exits) == 0: for line in self.render_return(block.inputargs): yield line return elif block.exitswitch is None: # single-exit block assert len(block.exits) == 1 for line in self.render_link(block.exits[0]): yield line elif block.exitswitch is c_last_exception: # exception branching # wuah. ugly! codef = formatter.codef exc_var = self.gen.unique_name(("var", "exception"), "exception") yield "] on: %s do: [:%s |" \ % (codef.format(self.OPERATION_ERROR), exc_var) exc_exits = [] non_exc_exit = None for exit in block.exits: if exit.exitcase is None: non_exc_exit = exit else: exc_exits.append(exit) for exit in exc_exits: yield "(%s type isKindOf: %s) ifTrue: [" \ % (exc_var, codef.format(dynamicType(exit.llexitcase))) if exit.last_exception is not None: yield "%s := %s type." \ % (codef.format(exit.last_exception), exc_var) if exit.last_exc_value is not None: yield "%s := %s value." \ % (codef.format(exit.last_exc_value), exc_var) for line in self.render_link(exit): yield line yield "] ifFalse: [" for exit in exc_exits: yield "]" yield "]." for line in self.render_link(non_exc_exit): yield line else: #exitswitch if self.loops.has_key(block): if self.loops[block]: self.loops[block] = False yield "%s] whileTrue: [" % self.codef.format(block.exitswitch) for line in self.render_link(block.exits[True]): yield " %s" % line yield "]." for line in self.render_link(block.exits[False]): yield "%s" % line else: yield "%s ifTrue: [" % self.codef.format(block.exitswitch) for line in self.render_link(block.exits[True]): yield " %s" % line yield "] ifFalse: [" for line in self.render_link(block.exits[False]): yield " %s" % line yield "]"