def calculate_arg_defaults(builder: IRBuilder, fn_info: FuncInfo, env: Environment, func_reg: Optional[Value]) -> None: """Calculate default argument values and store them. They are stored in statics for top level functions and in the function objects for nested functions (while constants are still stored computed on demand). """ fitem = fn_info.fitem for arg in fitem.arguments: # Constant values don't get stored but just recomputed if arg.initializer and not is_constant(arg.initializer): value = builder.coerce( builder.accept(arg.initializer), env.lookup(arg.variable).type, arg.line ) if not fn_info.is_nested: name = fitem.fullname + '.' + arg.variable.name builder.add(InitStatic(value, name, builder.module_name)) else: assert func_reg is not None builder.add(SetAttr(func_reg, arg.variable.name, value, arg.line))
def generate_attr_defaults_init( builder: IRBuilder, cdef: ClassDef, default_assignments: List[AssignmentStmt]) -> None: """Generate an initialization method for default attr values (from class vars).""" if not default_assignments: return cls = builder.mapper.type_to_ir[cdef.info] if cls.builtin_base: return with builder.enter_method(cls, '__mypyc_defaults_setup', bool_rprimitive): self_var = builder.self() for stmt in default_assignments: lvalue = stmt.lvalues[0] assert isinstance(lvalue, NameExpr) if not stmt.is_final_def and not is_constant(stmt.rvalue): builder.warning('Unsupported default attribute value', stmt.rvalue.line) attr_type = cls.attr_type(lvalue.name) val = builder.coerce(builder.accept(stmt.rvalue), attr_type, stmt.line) init = SetAttr(self_var, lvalue.name, val, -1) init.mark_as_initializer() builder.add(init) builder.add(Return(builder.true()))
def generate_attr_defaults(builder: IRBuilder, cdef: ClassDef) -> None: """Generate an initialization method for default attr values (from class vars).""" cls = builder.mapper.type_to_ir[cdef.info] if cls.builtin_base: return # Pull out all assignments in classes in the mro so we can initialize them # TODO: Support nested statements default_assignments = [] for info in reversed(cdef.info.mro): if info not in builder.mapper.type_to_ir: continue for stmt in info.defn.defs.body: if (isinstance(stmt, AssignmentStmt) and isinstance(stmt.lvalues[0], NameExpr) and not is_class_var(stmt.lvalues[0]) and not isinstance(stmt.rvalue, TempNode)): name = stmt.lvalues[0].name if name == '__slots__': continue if name == '__deletable__': check_deletable_declaration(builder, cls, stmt.line) continue # Skip type annotated assignments in dataclasses if is_dataclass(cdef) and stmt.type: continue default_assignments.append(stmt) if not default_assignments: return builder.enter_method(cls, '__mypyc_defaults_setup', bool_rprimitive) self_var = builder.self() for stmt in default_assignments: lvalue = stmt.lvalues[0] assert isinstance(lvalue, NameExpr) if not stmt.is_final_def and not is_constant(stmt.rvalue): builder.warning('Unsupported default attribute value', stmt.rvalue.line) # If the attribute is initialized to None and type isn't optional, # don't initialize it to anything. attr_type = cls.attr_type(lvalue.name) if isinstance(stmt.rvalue, RefExpr) and stmt.rvalue.fullname == 'builtins.None': if (not is_optional_type(attr_type) and not is_object_rprimitive(attr_type) and not is_none_rprimitive(attr_type)): continue val = builder.coerce(builder.accept(stmt.rvalue), attr_type, stmt.line) builder.add(SetAttr(self_var, lvalue.name, val, -1)) builder.add(Return(builder.true())) builder.leave_method()
def get_default() -> Value: assert arg.initializer is not None # If it is constant, don't bother storing it if is_constant(arg.initializer): return builder.accept(arg.initializer) # Because gen_arg_defaults runs before calculate_arg_defaults, we # add the static/attribute to final_names/the class here. elif not builder.fn_info.is_nested: name = fitem.fullname + '.' + arg.variable.name builder.final_names.append((name, target.type)) return builder.add(LoadStatic(target.type, name, builder.module_name)) else: name = arg.variable.name builder.fn_info.callable_class.ir.attributes[name] = target.type return builder.add( GetAttr(builder.fn_info.callable_class.self_reg, name, arg.line))
def generate_attr_defaults(builder: IRBuilder, cdef: ClassDef) -> None: """Generate an initialization method for default attr values (from class vars).""" cls = builder.mapper.type_to_ir[cdef.info] if cls.builtin_base: return # Pull out all assignments in classes in the mro so we can initialize them # TODO: Support nested statements default_assignments = [] for info in reversed(cdef.info.mro): if info not in builder.mapper.type_to_ir: continue for stmt in info.defn.defs.body: if (isinstance(stmt, AssignmentStmt) and isinstance(stmt.lvalues[0], NameExpr) and not is_class_var(stmt.lvalues[0]) and not isinstance(stmt.rvalue, TempNode)): if stmt.lvalues[0].name == '__slots__': continue # Skip type annotated assignments in dataclasses if is_dataclass(cdef) and stmt.type: continue default_assignments.append(stmt) if not default_assignments: return builder.enter() builder.ret_types[-1] = bool_rprimitive rt_args = (RuntimeArg(SELF_NAME, RInstance(cls)), ) self_var = builder.read(add_self_to_env(builder.environment, cls), -1) for stmt in default_assignments: lvalue = stmt.lvalues[0] assert isinstance(lvalue, NameExpr) if not stmt.is_final_def and not is_constant(stmt.rvalue): builder.warning('Unsupported default attribute value', stmt.rvalue.line) # If the attribute is initialized to None and type isn't optional, # don't initialize it to anything. attr_type = cls.attr_type(lvalue.name) if isinstance(stmt.rvalue, RefExpr) and stmt.rvalue.fullname == 'builtins.None': if (not is_optional_type(attr_type) and not is_object_rprimitive(attr_type) and not is_none_rprimitive(attr_type)): continue val = builder.coerce(builder.accept(stmt.rvalue), attr_type, stmt.line) builder.add(SetAttr(self_var, lvalue.name, val, -1)) builder.add(Return(builder.true())) blocks, env, ret_type, _ = builder.leave() ir = FuncIR( FuncDecl('__mypyc_defaults_setup', cls.name, builder.module_name, FuncSignature(rt_args, ret_type)), blocks, env) builder.functions.append(ir) cls.methods[ir.name] = ir