def setUp(self) -> None: self.env = Environment() self.n = self.env.add_local(Var('n'), int_rprimitive) self.m = self.env.add_local(Var('m'), int_rprimitive) self.k = self.env.add_local(Var('k'), int_rprimitive) self.l = self.env.add_local(Var('l'), list_rprimitive) # noqa self.ll = self.env.add_local(Var('ll'), list_rprimitive) self.o = self.env.add_local(Var('o'), object_rprimitive) self.o2 = self.env.add_local(Var('o2'), object_rprimitive) self.d = self.env.add_local(Var('d'), dict_rprimitive) self.b = self.env.add_local(Var('b'), bool_rprimitive) self.t = self.env.add_local(Var('t'), RTuple([int_rprimitive, bool_rprimitive])) self.tt = self.env.add_local( Var('tt'), RTuple( [RTuple([int_rprimitive, bool_rprimitive]), bool_rprimitive])) ir = ClassIR('A', 'mod') ir.attributes = OrderedDict([('x', bool_rprimitive), ('y', int_rprimitive)]) compute_vtable(ir) ir.mro = [ir] self.r = self.env.add_local(Var('r'), RInstance(ir)) self.context = EmitterContext(NameGenerator([['mod']])) self.emitter = Emitter(self.context, self.env) self.declarations = Emitter(self.context, self.env) self.visitor = FunctionEmitterVisitor(self.emitter, self.declarations, 'prog.py', 'prog')
def test_names(self) -> None: assert RTuple([int_rprimitive, int_rprimitive]).unique_id == "T2II" assert RTuple([list_rprimitive, object_rprimitive, self.inst_a]).unique_id == "T3OOO" assert RTuple([list_rprimitive, object_rprimitive, self.inst_b]).unique_id == "T3OOO" assert RTuple([]).unique_id == "T0" assert RTuple([RTuple([]), RTuple([int_rprimitive, int_rprimitive])]).unique_id == "T2T0T2II" assert RTuple( [bool_rprimitive, RUnion([bool_rprimitive, int_rprimitive])]).unique_id == "T2CO"
# Like next_raw_op, don't swallow StopIteration, # but also don't propagate an error. # Can return NULL: see next_op. send_op = custom_op(name='send', arg_types=[object_rprimitive, object_rprimitive], result_type=object_rprimitive, error_kind=ERR_NEVER, emit=call_emit('CPyIter_Send')) # This is sort of unfortunate but oh well: yield_from_except performs most of the # error handling logic in `yield from` operations. It returns a bool and a value. # If the bool is true, then a StopIteration was received and we should return. # If the bool is false, then the value should be yielded. # The normal case is probably that it signals an exception, which gets # propagated. yield_from_rtuple = RTuple([bool_rprimitive, object_rprimitive]) yield_from_except_op = custom_op( name='yield_from_except', arg_types=[object_rprimitive], result_type=yield_from_rtuple, error_kind=ERR_MAGIC, emit=simple_emit( '{dest}.f0 = CPy_YieldFromErrorHandle({args[0]}, &{dest}.f1);')) method_new_op = custom_op(name='method_new', arg_types=[object_rprimitive, object_rprimitive], result_type=object_rprimitive, error_kind=ERR_MAGIC, emit=call_emit('PyMethod_New'))
def type_to_rtype(self, typ: Optional[Type]) -> RType: if typ is None: return object_rprimitive typ = get_proper_type(typ) if isinstance(typ, Instance): if typ.type.fullname == 'builtins.int': return int_rprimitive elif typ.type.fullname == 'builtins.float': return float_rprimitive elif typ.type.fullname == 'builtins.str': return str_rprimitive elif typ.type.fullname == 'builtins.bool': return bool_rprimitive elif typ.type.fullname == 'builtins.list': return list_rprimitive # Dict subclasses are at least somewhat common and we # specifically support them, so make sure that dict operations # get optimized on them. elif any(cls.fullname == 'builtins.dict' for cls in typ.type.mro): return dict_rprimitive elif typ.type.fullname == 'builtins.set': return set_rprimitive elif typ.type.fullname == 'builtins.tuple': return tuple_rprimitive # Varying-length tuple elif typ.type in self.type_to_ir: return RInstance(self.type_to_ir[typ.type]) else: return object_rprimitive elif isinstance(typ, TupleType): # Use our unboxed tuples for raw tuples but fall back to # being boxed for NamedTuple. if typ.partial_fallback.type.fullname == 'builtins.tuple': return RTuple([self.type_to_rtype(t) for t in typ.items]) else: return tuple_rprimitive elif isinstance(typ, CallableType): return object_rprimitive elif isinstance(typ, NoneTyp): return none_rprimitive elif isinstance(typ, UnionType): return RUnion([self.type_to_rtype(item) for item in typ.items]) elif isinstance(typ, AnyType): return object_rprimitive elif isinstance(typ, TypeType): return object_rprimitive elif isinstance(typ, TypeVarType): # Erase type variable to upper bound. # TODO: Erase to union if object has value restriction? return self.type_to_rtype(typ.upper_bound) elif isinstance(typ, PartialType): assert typ.var.type is not None return self.type_to_rtype(typ.var.type) elif isinstance(typ, Overloaded): return object_rprimitive elif isinstance(typ, TypedDictType): return dict_rprimitive elif isinstance(typ, LiteralType): return self.type_to_rtype(typ.fallback) elif isinstance(typ, (UninhabitedType, UnboundType)): # Sure, whatever! return object_rprimitive # I think we've covered everything that is supposed to # actually show up, so anything else is a bug somewhere. assert False, 'unexpected type %s' % type(typ)