def get_attr(self, obj: Value, attr: str, result_type: RType, line: int) -> Value: if (isinstance(obj.type, RInstance) and obj.type.class_ir.is_ext_class and obj.type.class_ir.has_attr(attr)): return self.add(GetAttr(obj, attr, line)) elif isinstance(obj.type, RUnion): return self.union_get_attr(obj, obj.type, attr, result_type, line) else: return self.py_get_attr(obj, attr, line)
def gen_method_call( self, base: Value, name: str, arg_values: List[Value], result_type: Optional[RType], line: int, arg_kinds: Optional[List[int]] = None, arg_names: Optional[List[Optional[str]]] = None) -> Value: # If arg_kinds contains values other than arg_pos and arg_named, then fallback to # Python method call. if (arg_kinds is not None and not all(kind in (ARG_POS, ARG_NAMED) for kind in arg_kinds)): return self.py_method_call(base, name, arg_values, base.line, arg_kinds, arg_names) # If the base type is one of ours, do a MethodCall if (isinstance(base.type, RInstance) and base.type.class_ir.is_ext_class and not base.type.class_ir.builtin_base): if base.type.class_ir.has_method(name): decl = base.type.class_ir.method_decl(name) if arg_kinds is None: assert arg_names is None, "arg_kinds not present but arg_names is" arg_kinds = [ARG_POS for _ in arg_values] arg_names = [None for _ in arg_values] else: assert arg_names is not None, "arg_kinds present but arg_names is not" # Normalize args to positionals. assert decl.bound_sig arg_values = self.native_args_to_positional( arg_values, arg_kinds, arg_names, decl.bound_sig, line) return self.add(MethodCall(base, name, arg_values, line)) elif base.type.class_ir.has_attr(name): function = self.add(GetAttr(base, name, line)) return self.py_call(function, arg_values, line, arg_kinds=arg_kinds, arg_names=arg_names) elif isinstance(base.type, RUnion): return self.union_method_call(base, base.type, name, arg_values, result_type, line, arg_kinds, arg_names) # Try to do a special-cased method call if not arg_kinds or arg_kinds == [ARG_POS] * len(arg_values): target = self.translate_special_method_call( base, name, arg_values, result_type, line) if target: return target # Fall back to Python method call return self.py_method_call(base, name, arg_values, line, arg_kinds, arg_names)
def visit_member_expr(self, expr: MemberExpr) -> Register: if self.is_module_member_expr(expr): return self.load_static_module_attr(expr) else: obj_reg = self.accept(expr.expr) attr_type = self.node_type(expr) target = self.alloc_target(attr_type) obj_type = self.node_type(expr.expr) assert isinstance( obj_type, UserRType), 'Attribute access not supported: %s' % obj_type self.add(GetAttr(target, obj_reg, expr.name, obj_type)) return target
def test_get_attr(self) -> None: self.assert_emit( GetAttr(self.r, 'y', 1), """cpy_r_r0 = native_A_gety((AObject *)cpy_r_r); /* y */""")
def test_get_attr(self) -> None: ir = ClassIR('A', [('x', BoolRType()), ('y', IntRType())]) rtype = UserRType(ir) self.assert_emit( GetAttr(self.n, self.m, 'y', rtype), """cpy_r_n = CPY_GET_ATTR(cpy_r_m, 2, AObject, CPyTagged);""")
def test_get_attr(self) -> None: self.assert_emit( GetAttr(self.r, 'y', 1), """cpy_r_r0 = CPY_GET_ATTR(cpy_r_r, &CPyType_A, 2, AObject, CPyTagged);""")