예제 #1
0
    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)
예제 #2
0
    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)
예제 #3
0
    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
예제 #4
0
    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)
예제 #5
0
    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)
예제 #6
0
    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)
예제 #7
0
    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)
예제 #8
0
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)
예제 #9
0
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)
예제 #10
0
    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)
예제 #11
0
    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)
예제 #12
0
                       [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)
예제 #13
0
        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)
예제 #14
0
 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):