def make_instance_tvar_initializer(self, creat: FuncDef) -> None: """Add type variable member initialization code to a constructor. Modify the constructor body directly. """ for n in range(num_slots(creat.info)): rvalue = self.make_tvar_init_expression(creat.info, n) init = AssignmentStmt([MemberExpr(self_expr(), tvar_slot_name(n), direct=True)], rvalue) self.tf.set_type(init.lvalues[0], AnyType()) self.tf.set_type(init.rvalue, AnyType()) creat.body.body.insert(n, init)
def make_instance_tvar_initializer(self, creat): """Add type variable member initialization code to a constructor. Modify the constructor body directly. """ for n in range(num_slots(creat.info)): rvalue = self.make_tvar_init_expression(creat.info, n) init = AssignmentStmt([MemberExpr(self_expr(), tvar_slot_name(n), direct=True)], rvalue) self.tf.set_type(init.lvalues[0], Any()) self.tf.set_type(init.rvalue, Any()) creat.body.body.insert(n, init)
def make_generic_wrapper_init(self, info: TypeInfo) -> FuncDef: """Build constructor of a generic wrapper class.""" nslots = num_slots(info) cdefs = [] # type: List[Node] # Build superclass constructor call. base = info.mro[1] if base.fullname() != 'builtins.object' and self.tf.is_java: s = SuperExpr('__init__') cargs = [NameExpr('__o')] # type: List[Node] for n in range(num_slots(base)): cargs.append(NameExpr(tvar_arg_name(n + 1))) for n in range(num_slots(base)): cargs.append(NameExpr(tvar_arg_name(n + 1, BOUND_VAR))) c = CallExpr(s, cargs, [nodes.ARG_POS] * len(cargs)) cdefs.append(ExpressionStmt(c)) # Create initialization of the wrapped object. cdefs.append(AssignmentStmt([MemberExpr( self_expr(), self.object_member_name(info), direct=True)], NameExpr('__o'))) # Build constructor arguments. args = [Var('self'), Var('__o')] init = [None, None] # type: List[Node] for alt in [False, BOUND_VAR]: for n in range(nslots): args.append(Var(tvar_arg_name(n + 1, alt))) init.append(None) nargs = nslots * 2 + 2 fdef = FuncDef('__init__', args, [nodes.ARG_POS] * nargs, init, Block(cdefs), Callable( [AnyType()] * nargs, [nodes.ARG_POS] * nargs, [None] * nargs, Void(), is_type_obj=False)) fdef.info = info self.make_wrapper_slot_initializer(fdef) return fdef
def make_wrapper_slot_initializer(self, creat): """Add type variable member initializations to a wrapper constructor. The function must be a constructor of a generic wrapper class. Modify the constructor body directly. """ for alt in [BOUND_VAR, False]: for n in range(num_slots(creat.info)): rvalue = TypeExpr( RuntimeTypeVar(NameExpr(tvar_slot_name(n, alt)))) init = AssignmentStmt( [MemberExpr(self_expr(), tvar_slot_name(n, alt), direct=True)], rvalue) self.tf.set_type(init.lvalues[0], Any()) self.tf.set_type(init.rvalue, Any()) creat.body.body.insert(n, init)
def make_wrapper_slot_initializer(self, creat: FuncDef) -> None: """Add type variable member initializations to a wrapper constructor. The function must be a constructor of a generic wrapper class. Modify the constructor body directly. """ for alt in [BOUND_VAR, False]: for n in range(num_slots(creat.info)): rvalue = TypeExpr( RuntimeTypeVar(NameExpr(tvar_slot_name(n, alt)))) init = AssignmentStmt( [MemberExpr(self_expr(), tvar_slot_name(n, alt), direct=True)], rvalue) self.tf.set_type(init.lvalues[0], AnyType()) self.tf.set_type(init.rvalue, AnyType()) creat.body.body.insert(n, init)
def call_wrapper(self, fdef: FuncDef, is_dynamic: bool, is_wrapper_class: bool, target_ann: Callable, cur_ann: Callable, target_suffix: str, bound_sig: Callable) -> Node: """Return the body of wrapper method. The body contains only a call to the wrapped method and a return statement (if the call returns a value). Arguments are coerced to the target signature. """ args = self.call_args(fdef.args, target_ann, cur_ann, is_dynamic, is_wrapper_class, bound_sig, ismethod=fdef.is_method()) selfarg = args[0] args = args[1:] member = fdef.name() + target_suffix if not is_wrapper_class: callee = MemberExpr(selfarg, member) else: callee = MemberExpr( MemberExpr(self_expr(), self.tf.object_member_name()), member) call = CallExpr(callee, args, [nodes.ARG_POS] * len(args), [None] * len(args)) # type: Node if bound_sig: call = self.tf.coerce(call, bound_sig.ret_type, target_ann.ret_type, self.tf.type_context(), is_wrapper_class) call = self.tf.coerce(call, cur_ann.ret_type, bound_sig.ret_type, self.tf.type_context(), is_wrapper_class) else: call = self.tf.coerce(call, cur_ann.ret_type, target_ann.ret_type, self.tf.type_context(), is_wrapper_class) if not isinstance(target_ann.ret_type, Void): return ReturnStmt(call) else: return ExpressionStmt(call)
def get_tvar_access_expression(typ: TypeInfo, tvindex: int, alt: Any, is_java: Any) -> RuntimeTypeVar: """Return a type expression that maps from runtime type variable slots to the type variable in the given class with the given index. For example, assuming class A(Generic[T, S]): ... and class B(A[X, Y[U]], Generic[U]): ...: get_tvar_access_expression(<B>, 1) == RuntimeTypeVar(<self.__tv2.args[0]>) (with <...> represented as nodes) """ # First get the description of how to get from supertype type variables to # a subtype type variable. mapping = get_tvar_access_path(typ, tvindex) # The type checker should have noticed if there is no mapping. Be defensive # and make sure there is one. if mapping is None: raise RuntimeError('Could not find a typevar mapping') # Build the expression for getting at the subtype type variable # progressively. # First read the value of a supertype runtime type variable slot. s = self_expr() # type: Node if alt == OBJECT_VAR: o = '__o' if is_java: o = '__o_{}'.format(typ.name) s = MemberExpr(s, o) expr = MemberExpr(s, tvar_slot_name(mapping[0] - 1, alt)) # type: Node # Then, optionally look into arguments based on the description. for i in mapping[1:]: expr = MemberExpr(expr, 'args') expr = IndexExpr(expr, IntExpr(i - 1)) # Than add a final wrapper so that we have a valid type. return RuntimeTypeVar(expr)
def make_dynamic_setter_wrapper(self, name, typ): """Create a dynamically-typed setter wrapper for a data attribute. The setter will be of this form: . void set$name*(C self, any name): . self.name! = {typ name} """ lvalue = MemberExpr(self_expr(), name, direct=True) name_expr = NameExpr(name) rvalue = coerce(name_expr, typ, Any(), self.tf.type_context()) ret = AssignmentStmt([lvalue], rvalue) wrapper_name = 'set$' + name + self.tf.dynamic_suffix() selft = self_type(self.tf.type_context()) sig = Callable([selft, Any()], [nodes.ARG_POS, nodes.ARG_POS], [None, None], Void(), False) return FuncDef(wrapper_name, [Var('self'), Var(name)], [nodes.ARG_POS, nodes.ARG_POS], [None, None], Block([ret]), sig)
def make_dynamic_setter_wrapper(self, name: str, typ: Type) -> FuncDef: """Create a dynamically-typed setter wrapper for a data attribute. The setter will be of this form: . def set$name*(self: C, name; Any) -> None: . self.name! = {typ name} """ lvalue = MemberExpr(self_expr(), name, direct=True) name_expr = NameExpr(name) rvalue = coerce(name_expr, typ, AnyType(), self.tf.type_context()) ret = AssignmentStmt([lvalue], rvalue) wrapper_name = 'set$' + name + self.tf.dynamic_suffix() selft = self_type(self.tf.type_context()) sig = Callable([selft, AnyType()], [nodes.ARG_POS, nodes.ARG_POS], [None, None], Void(), False) return FuncDef(wrapper_name, [Var('self'), Var(name)], [nodes.ARG_POS, nodes.ARG_POS], [None, None], Block([ret]), sig)
[selfv, namev], [nodes.ARG_POS, nodes.ARG_POS], [None, None], Block([ret]), sig) fdef.info = self.tf.type_context() return fdef FuncDef make_dynamic_setter_wrapper(self, str name, Type typ): """Create a dynamically-typed setter wrapper for a data attribute. The setter will be of this form: . void set$name*(C self, any name): . self.name! = {typ name} """ lvalue = MemberExpr(self_expr(), name, direct=True) name_expr = NameExpr(name) rvalue = coerce(name_expr, typ, Any(), self.tf.type_context()) ret = AssignmentStmt([lvalue], rvalue) wrapper_name = 'set$' + name + self.tf.dynamic_suffix() selft = self_type(self.tf.type_context()) sig = Callable([selft, Any()], [nodes.ARG_POS, nodes.ARG_POS], [None, None], Void(), False) return FuncDef(wrapper_name, [Var('self'), Var(name)], [nodes.ARG_POS, nodes.ARG_POS], [None, None], Block([ret]), sig)
RuntimeTypeVar(<self.__tv2.args[0]>) (with <...> represented as nodes) """ # First get the description of how to get from supertype type variables to # a subtype type variable. mapping = get_tvar_access_path(typ, tvindex) # The type checker should have noticed if there is no mapping. Be defensive # and make sure there is one. if mapping is None: raise RuntimeError('Could not find a typevar mapping') # Build the expression for getting at the subtype type variable # progressively. # First read the value of a supertype runtime type variable slot. Node s = self_expr() if alt == OBJECT_VAR: o = '__o' if is_java: o = '__o_{}'.format(typ.name) s = MemberExpr(s, o) Node expr = MemberExpr(s, tvar_slot_name(mapping[0] - 1, alt)) # Then, optionally look into arguments based on the description. for i in mapping[1:]: expr = MemberExpr(expr, 'args') expr = IndexExpr(expr, IntExpr(i - 1)) # Than add a final wrapper so that we have a valid type. return RuntimeTypeVar(expr)
The body contains only a call to the wrapped method and a return statement (if the call returns a value). Arguments are coerced to the target signature. """ args = self.call_args(fdef.args, target_ann, cur_ann, is_dynamic, is_wrapper_class, bound_sig, ismethod=fdef.is_method()) selfarg = args[0] args = args[1:] member = fdef.name() + target_suffix if not is_wrapper_class: callee = MemberExpr(selfarg, member) else: callee = MemberExpr( MemberExpr(self_expr(), self.tf.object_member_name()), member) Node call = CallExpr(callee, args, [nodes.ARG_POS] * len(args), <str> [None] * len(args)) if bound_sig: call = self.tf.coerce(call, bound_sig.ret_type, target_ann.ret_type, self.tf.type_context(), is_wrapper_class) call = self.tf.coerce(call, cur_ann.ret_type, bound_sig.ret_type, self.tf.type_context(), is_wrapper_class) else: call = self.tf.coerce(call, cur_ann.ret_type, target_ann.ret_type, self.tf.type_context(), is_wrapper_class) if not isinstance(target_ann.ret_type, Void):