def make_class_constructor(self, tdef: ClassDef) -> None: # Do we have a non-empty __init__? init = cast(FuncDef, tdef.info.get_method('__init__')) init_argc = len(init.args) - 1 if init.info.fullname() == 'builtins.object': init = None self.enter() if init: args = [] # type: List[int] for arg in init.args[1:]: args.append(self.add_local(arg)) target = self.alloc_register() self.add(Construct(target, tdef.info)) # Inititalize data attributes to default values. for name, node in sorted(tdef.info.names.items()): if isinstance(node.node, Var): var = cast(Var, node.node) temp = self.alloc_register() vtype = var.type if is_named_instance(vtype, 'builtins.int'): self.add(SetRI(temp, 0)) else: self.add(SetRNone(temp)) self.add(SetAttr(target, name, temp, tdef.info)) if init: self.add(CallMethod(self.alloc_register(), target, '__init__', init.info, args, static=True)) self.add(Return(target)) self.generated[tdef.name] = FuncIcode(init_argc, self.blocks, self.register_types) self.leave()
def visit_mypy_file(self, mfile: MypyFile) -> int: if mfile.fullname() in ('typing', 'abc'): # These module are special; their contents are currently all # built-in primitives. return -1 self.enter() # Initialize non-int global variables. for name in sorted(mfile.names): node = mfile.names[name].node if (isinstance(node, Var) and name not in nodes.implicit_module_attrs): v = cast(Var, node) if (not is_named_instance(v.type, 'builtins.int') and v.fullname() != 'typing.Undefined'): tmp = self.alloc_register() self.add(SetRNone(tmp)) self.add(SetGR(v.fullname(), tmp)) for d in mfile.defs: d.accept(self) self.add_implicit_return() self.generated['__init'] = FuncIcode(0, self.blocks, self.register_types) # TODO leave? return -1
def add_local(self, node: Var) -> int: type = REF if is_named_instance(node.type, 'builtins.int'): type = INT reg = self.alloc_register(type) self.lvar_regs[node] = reg return reg
def make_class_constructor(self, tdef): # Do we have a non-empty __init__? init = tdef.info.get_method('__init__') init_argc = len(init.args) - 1 if init.info.full_name() == 'builtins.object': init = None self.enter() if init: args = [] for arg in init.args[1:]: args.append(self.add_local(arg)) target = self.alloc_register() self.add(Construct(target, tdef.info)) # Inititalize data attributes to default values. for var in sorted(tdef.info.vars.keys()): temp = self.alloc_register() vtype = tdef.info.vars[var].type if is_named_instance(vtype, 'builtins.int'): self.add(SetRI(temp, 0)) else: self.add(SetRNone(temp)) self.add(SetAttr(target, var, temp, tdef.info)) if init: self.add(CallMethod(self.alloc_register(), target, '__init__', init.info, args, static=True)) self.add(Return(target)) self.generated[tdef.name] = FuncIcode(init_argc, self.blocks, self.register_types) self.leave()
def visit_coerce_expr(self, e: CoerceExpr) -> int: if is_named_instance(e.source_type, "builtins.int") and isinstance(e.target_type, AnyType): # This is a no-op currently. # TODO perhaps should do boxing in some cases... return e.expr.accept(self) else: # Non-trivial coercions not supported yet. raise NotImplementedError()
def add_implicit_return(self, sig: FunctionLike = None) -> None: if not self.current.ops or not isinstance(self.current.ops[-1], Return): r = self.alloc_register() if sig and is_named_instance((cast(Callable, sig)).ret_type, "builtins.int"): self.add(SetRI(r, 0)) else: self.add(SetRNone(r)) self.add(Return(r))
def visit_coerce_expr(self, e: CoerceExpr) -> int: if (is_named_instance(e.source_type, 'builtins.int') and isinstance(e.target_type, AnyType)): # This is a no-op currently. # TODO perhaps should do boxing in some cases... return e.expr.accept(self) else: # Non-trivial coercions not supported yet. raise NotImplementedError()
def visit_instance(self, template: Instance) -> List[Constraint]: actual = self.actual res = [] # type: List[Constraint] if isinstance(actual, Instance): instance = cast(Instance, actual) if (self.direction == SUBTYPE_OF and template.type.has_base(instance.type.fullname())): mapped = map_instance_to_supertype(template, instance.type) for i in range(len(instance.args)): # The constraints for generic type parameters are # invariant. Include the default constraint and its # negation to achieve the effect. cb = infer_constraints(mapped.args[i], instance.args[i], self.direction) res.extend(cb) res.extend(negate_constraints(cb)) return res elif (self.direction == SUPERTYPE_OF and instance.type.has_base(template.type.fullname())): mapped = map_instance_to_supertype(instance, template.type) for j in range(len(template.args)): # The constraints for generic type parameters are # invariant. cb = infer_constraints(template.args[j], mapped.args[j], self.direction) res.extend(cb) res.extend(negate_constraints(cb)) return res if isinstance(actual, AnyType): # IDEA: Include both ways, i.e. add negation as well? return self.infer_against_any(template.args) if (isinstance(actual, TupleType) and (is_named_instance(template, 'typing.Iterable') or is_named_instance(template, 'typing.Sequence') or is_named_instance(template, 'typing.Reversible')) and self.direction == SUPERTYPE_OF): actual = cast(TupleType, actual) for item in actual.items: cb = infer_constraints(template.args[0], item, SUPERTYPE_OF) res.extend(cb) return res else: return []
def add_implicit_return(self, sig=None): if not self.current.ops or not isinstance(self.current.ops[-1], Return): r = self.alloc_register() if sig and is_named_instance((sig).ret_type, 'builtins.int'): self.add(SetRI(r, 0)) else: self.add(SetRNone(r)) self.add(Return(r))
def add_implicit_return(self, sig: FunctionLike = None) -> None: if not self.current.ops or not isinstance(self.current.ops[-1], Return): r = self.alloc_register() if sig and is_named_instance( (cast(Callable, sig)).ret_type, 'builtins.int'): self.add(SetRI(r, 0)) else: self.add(SetRNone(r)) self.add(Return(r))
def visit_op_expr(self, e: OpExpr) -> int: # TODO arbitrary operand types left_type = self.types[e.left] right_type = self.types[e.right] if is_named_instance(left_type, "builtins.int") and is_named_instance(right_type, "builtins.int"): # Primitive operation left, left_kind = self.get_operand(e.left) right, right_kind = self.get_operand(e.right) target = self.target_register() self.add(BinOp(target, left, left_kind, right, right_kind, e.op)) else: # Generate method call inst = cast(Instance, left_type) left = self.accept(e.left) right = self.accept(e.right) target = self.target_register() method = nodes.op_methods[e.op] if e.op == "in": left, right = right, left inst = cast(Instance, right_type) self.add(CallMethod(target, left, method, inst.type, [right])) return target
def visit_op_expr(self, e: OpExpr) -> int: # TODO arbitrary operand types left_type = self.types[e.left] right_type = self.types[e.right] if (is_named_instance(left_type, 'builtins.int') and is_named_instance(right_type, 'builtins.int')): # Primitive operation left, left_kind = self.get_operand(e.left) right, right_kind = self.get_operand(e.right) target = self.target_register() self.add(BinOp(target, left, left_kind, right, right_kind, e.op)) else: # Generate method call inst = cast(Instance, left_type) left = self.accept(e.left) right = self.accept(e.right) target = self.target_register() method = nodes.op_methods[e.op] if e.op == 'in': left, right = right, left inst = cast(Instance, right_type) self.add(CallMethod(target, left, method, inst.type, [right])) return target
def visit_unary_expr(self, e: UnaryExpr) -> int: operand_type = self.types[e.expr] operand = self.accept(e.expr) target = self.target_register() if is_named_instance(operand_type, 'builtins.int'): self.add(UnaryOp(target, operand, e.op)) else: if e.op == '-': method = '__neg__' elif e.op == '~': method = '__invert__' else: raise NotImplementedError() inst = cast(Instance, operand_type) # TODO more flexible self.add(CallMethod(target, operand, method, inst.type, [])) return target
def visit_mypy_file(self, mfile): self.enter() # Initialize non-int global variables. for name in sorted(mfile.names): node = mfile.names[name].node if isinstance(node, Var) and name != '__name__': v = node if not is_named_instance(v.type, 'builtins.int'): tmp = self.alloc_register() self.add(SetRNone(tmp)) self.add(SetGR(v.full_name(), tmp)) for d in mfile.defs: d.accept(self) self.add_implicit_return() self.generated['__init'] = FuncIcode(0, self.blocks, self.register_types) # TODO leave? return -1
def make_class_constructor(self, tdef: ClassDef) -> None: # Do we have a non-empty __init__? init = cast(FuncDef, tdef.info.get_method('__init__')) init_argc = len(init.args) - 1 if init.info.fullname() == 'builtins.object': init = None self.enter() if init: args = [] # type: List[int] for arg in init.args[1:]: args.append(self.add_local(arg)) target = self.alloc_register() self.add(Construct(target, tdef.info)) # Inititalize data attributes to default values. for name, node in sorted(tdef.info.names.items()): if isinstance(node.node, Var): var = cast(Var, node.node) temp = self.alloc_register() vtype = var.type if is_named_instance(vtype, 'builtins.int'): self.add(SetRI(temp, 0)) else: self.add(SetRNone(temp)) self.add(SetAttr(target, name, temp, tdef.info)) if init: self.add( CallMethod(self.alloc_register(), target, '__init__', init.info, args, static=True)) self.add(Return(target)) self.generated[tdef.name] = FuncIcode(init_argc, self.blocks, self.register_types) self.leave()