"""Transform classes for runtime type checking."""

from typing import Undefined, List, Set, Any, cast, Tuple, Dict

from mypy.nodes import (
    TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt,
    TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt,
    AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode
)
from mypy import nodes
from mypy.semanal import self_type
from mypy.types import (
    Callable, Instance, Type, AnyType, BOUND_VAR, Void, RuntimeTypeVar,
    UnboundType
)
from mypy.checkmember import analyse_member_access
from mypy.checkexpr import type_object_type
from mypy.subtypes import map_instance_to_supertype
import mypy.transform
from mypy.transformfunc import FuncTransformer
from mypy.transutil import (
    self_expr, tvar_slot_name, tvar_arg_name, prepend_arg_type
)
from mypy.rttypevars import translate_runtime_type_vars_locally
from mypy.compileslotmap import find_slot_origin
from mypy.coerce import coerce
from mypy.maptypevar import num_slots, get_tvar_access_path
from mypy import erasetype


class TypeTransformer:
    """Class for transforming type definitions for runtime type checking.

    Transform a type definition by modifying it in-place.

    The following transformations are performed:

      * Represent generic type variables explicitly as attributes.
      * Create generic wrapper classes used by coercions to different type
        args.
      * Create wrapper methods needed when overriding methods with different
        signatures.
      * Create wrapper methods for calling methods in dynamically typed code.
        These perform the necessary coercions for arguments and return values
        to/from 'Any'.
    
    This is used by DyncheckTransformVisitor and is logically aggregated within
    that class.
    """
    
    # Used for common transformation operations.
    tf = Undefined('mypy.transform.DyncheckTransformVisitor')
    # Used for transforming methods.
    func_tf = Undefined(FuncTransformer)
    
    def __init__(self, tf: 'mypy.transform.DyncheckTransformVisitor') -> None:
        self.tf = tf
        self.func_tf = FuncTransformer(tf)
    
    def transform_type_def(self, tdef: TypeDef) -> List[Node]:        
        """Transform a type definition.

        The result may be one or two definitions.  The first is the
        transformation of the original TypeDef. The second is a
        wrapper type, which is generated for generic types only.
        """
        defs = [] # type: List[Node]
        
        if tdef.info.type_vars:
            # This is a generic type. Insert type variable slots in
            # the class definition for new type variables, i.e. type
            # variables not mapped to superclass type variables.
            defs.extend(self.make_tvar_representation(tdef.info))
        
        # Iterate over definitions and transform each of them.
        vars = set() # type: Set[Var]
        for d in tdef.defs.body:
            if isinstance(d, FuncDef):
                # Implicit cast from FuncDef[] to Node[] is safe below.
                defs.extend(Any(self.func_tf.transform_method(d)))
            elif isinstance(d, VarDef):
                defs.extend(self.transform_var_def(d))
                for n in d.items:
                    vars.add(n)
            elif isinstance(d, AssignmentStmt):
                self.transform_assignment(d)
                defs.append(d)

        # Add accessors for implicitly defined attributes.
        for node in tdef.info.names.values():
            if isinstance(node.node, Var):
                v = cast(Var, node.node)
                if v.info == tdef.info and v not in vars:
                    defs.extend(self.make_accessors(v))
        
        # For generic classes, add an implicit __init__ wrapper.
        defs.extend(self.make_init_wrapper(tdef))
        
        if tdef.is_generic() or (tdef.info.bases and
                                 tdef.info.mro[1].is_generic()):
            self.make_instance_tvar_initializer(
                cast(FuncDef, tdef.info.get_method('__init__')))

        if not defs:
            defs.append(PassStmt())

        if tdef.is_generic():
            gen_wrapper = self.generic_class_wrapper(tdef)

        tdef.defs = Block(defs)

        dyn_wrapper = self.make_type_object_wrapper(tdef)
        
        if not tdef.is_generic():
            return [tdef, dyn_wrapper]
        else:
            return [tdef, dyn_wrapper, gen_wrapper]
    
    def make_init_wrapper(self, tdef: TypeDef) -> List[Node]:
        """Make and return an implicit __init__ if class needs it.
        
        Otherwise, return an empty list. We include an implicit
        __init__ if the class is generic or if it extends a generic class
        and if it does not define __init__.
        
        The __init__ of a generic class requires one or more extra type
        variable arguments. The inherited __init__ may not accept these.

        For example, assume these definitions:
        
        . class A(Generic[T]): pass
        . class B(A[int]): pass
        
        The constructor for B will be (equivalent to)
        
        . def __init__(self: B) -> None:
        .     self.__tv = <int>
        .     super().__init__(<int>)
        """
        
        # FIX overloading, default args / varargs, keyword args

        info = tdef.info
        
        if '__init__' not in info.names and (
                tdef.is_generic() or (info.bases and
                                      info.mro[1].is_generic())):
            # Generic class with no explicit __init__ method
            # (i.e. __init__ inherited from superclass). Generate a
            # wrapper that initializes type variable slots and calls
            # the superclass __init__ method.

            base = info.mro[1]
            selftype = self_type(info)    
            callee_type = cast(Callable, analyse_member_access(
                '__init__', selftype, None, False, True, None, None,
                base))
            
            # Now the callee type may contain the type variables of a
            # grandparent as bound type variables, but we want the
            # type variables of the parent class. Explicitly set the
            # bound type variables.
            callee_type = self.fix_bound_init_tvars(callee_type,
                map_instance_to_supertype(selftype, base))
            
            super_init = cast(FuncDef, base.get_method('__init__'))
            
            # Build argument list.
            args = [Var('self')]
            for i in range(1, len(super_init.args)):
                args.append(Var(super_init.args[i].name()))
                args[-1].type = callee_type.arg_types[i - 1]

            selft = self_type(self.tf.type_context())
            callee_type = prepend_arg_type(callee_type, selft)
            
            creat = FuncDef('__init__', args,
                            super_init.arg_kinds, [None] * len(args),
                            Block([]))
            creat.info = tdef.info
            creat.type = callee_type
            creat.is_implicit = False
            tdef.info.names['__init__'] = SymbolTableNode(MDEF, creat,
                                                          typ=creat.type)
            
            # Insert a call to superclass constructor. If the
            # superclass is object, the constructor does nothing =>
            # omit the call.
            if base.fullname() != 'builtins.object':
                creat.body.body.append(
                    self.make_superclass_constructor_call(tdef.info,
                                                          callee_type))
            
            # Implicit cast from FuncDef[] to Node[] is safe below.
            return Any(self.func_tf.transform_method(creat))
        else:
            return []
    
    def fix_bound_init_tvars(self, callable: Callable,
                             typ: Instance) -> Callable:
        """Replace bound type vars of callable with args from instance type."""
        a = [] # type: List[Tuple[int, Type]]
        for i in range(len(typ.args)):
            a.append((i + 1, typ.args[i]))
        return Callable(callable.arg_types, callable.arg_kinds,
                        callable.arg_names, callable.ret_type,
                        callable.is_type_obj(), callable.name,
                        callable.variables, a)
    
    def make_superclass_constructor_call(
            self, info: TypeInfo, callee_type: Callable) -> ExpressionStmt:
        """Construct a statement that calls the superclass constructor.

        In particular, it passes any type variables arguments as needed.
        """
        callee = SuperExpr('__init__')
        callee.info = info
        
        # We do not handle generic constructors. Either pass runtime
        # type variables from the current scope or perhaps require
        # explicit constructor in this case.
        
        selftype = self_type(info)    
        
        # FIX overloading
        # FIX default args / varargs
        
        # Map self type to the superclass context.
        base = info.mro[1]
        selftype = map_instance_to_supertype(selftype, base)
        
        super_init = cast(FuncDef, base.get_method('__init__'))
        
        # Add constructor arguments.
        args = [] # type: List[Node]
        for n in range(1, callee_type.min_args):            
            args.append(NameExpr(super_init.args[n].name()))
            self.tf.set_type(args[-1], callee_type.arg_types[n])

        # Store callee type after stripping away the 'self' type.
        self.tf.set_type(callee, nodes.method_callable(callee_type))
        
        call = CallExpr(callee, args, [nodes.ARG_POS] * len(args))
        return ExpressionStmt(call)
    
    def transform_var_def(self, o: VarDef) -> List[Node]:
        """Transform a member variable definition.

        The result may be one or more definitions.
        """
        res = [o] # type: List[Node]
        
        self.tf.visit_var_def(o)
        
        # Add $x and set$x accessor wrappers for data attributes. These let
        # derived classes redefine a data attribute as a property.
        for n in o.items:
            res.extend(self.make_accessors(n))
        
        return res
    
    def transform_assignment(self, o: AssignmentStmt) -> None:
        """Transform an assignment statement in class body."""
        self.tf.visit_assignment_stmt(o)

    def make_accessors(self, n: Var) -> List[Node]:
        if n.type:
            t = n.type
        else:
            t = AnyType()
        return [self.make_getter_wrapper(n.name(), t),
                self.make_setter_wrapper(n.name(), t),
                self.make_dynamic_getter_wrapper(n.name(), t),
                self.make_dynamic_setter_wrapper(n.name(), t)]
    
    def make_getter_wrapper(self, name: str, typ: Type) -> FuncDef:
        """Create a getter wrapper for a data attribute.

        The getter will be of this form:
        
        . def $name*(self: C) -> type:
        .     return self.name!
        """
        scope = self.make_scope()
        selft = self.self_type()
        selfv = scope.add('self', selft)
        
        member_expr = MemberExpr(scope.name_expr('self'), name, direct=True)
        ret = ReturnStmt(member_expr)

        wrapper_name = '$' + name
        sig = Callable([selft], [nodes.ARG_POS], [None], typ, False)
        fdef = FuncDef(wrapper_name,
                       [selfv],
                       [nodes.ARG_POS],
                       [None],
                       Block([ret]), sig)
        fdef.info = self.tf.type_context()
        return fdef
    
    def make_dynamic_getter_wrapper(self, name: str, typ: Type) -> FuncDef:
        """Create a dynamically-typed getter wrapper for a data attribute.

        The getter will be of this form:
        
        . def $name*(self: C) -> Any:
        .     return {Any <= typ self.name!}
        """
        scope = self.make_scope()
        selft = self.self_type()
        selfv = scope.add('self', selft)
        
        member_expr = MemberExpr(scope.name_expr('self'), name, direct=True)
        coerce_expr = coerce(member_expr, AnyType(), typ,
                             self.tf.type_context())
        ret = ReturnStmt(coerce_expr)

        wrapper_name = '$' + name + self.tf.dynamic_suffix()
        sig = Callable([selft], [nodes.ARG_POS], [None], AnyType(), False)
        return FuncDef(wrapper_name,
                       [selfv],
                       [nodes.ARG_POS],
                       [None],
                       Block([ret]), sig)
    
    def make_setter_wrapper(self, name: str, typ: Type) -> FuncDef:
        """Create a setter wrapper for a data attribute.

        The setter will be of this form:
        
        . def set$name(self: C, name: typ) -> None:
        .     self.name! = name
        """
        scope = self.make_scope()
        selft = self.self_type()
        selfv = scope.add('self', selft)
        namev = scope.add(name, typ)
        
        lvalue = MemberExpr(scope.name_expr('self'), name, direct=True)
        rvalue = scope.name_expr(name)
        ret = AssignmentStmt([lvalue], rvalue)

        wrapper_name = 'set$' + name
        sig = Callable([selft, typ],
                       [nodes.ARG_POS, nodes.ARG_POS],
                       [None, None],
                       Void(), False)
        fdef = FuncDef(wrapper_name,
                       [selfv, namev],
                       [nodes.ARG_POS, nodes.ARG_POS],
                       [None, None],
                       Block([ret]), sig)
        fdef.info = self.tf.type_context()
        return fdef
    
    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)
    
    def generic_accessor_wrappers(self, s: AssignmentStmt) -> List[Node]:
        """Construct wrapper class methods for attribute accessors."""
        res = [] # type: List[Node]
        assert len(s.lvalues) == 1
        assert isinstance(s.lvalues[0], NameExpr)
        assert s.type is not None
        name = cast(NameExpr, s.lvalues[0])
        for fd in [self.make_getter_wrapper(name.name, s.type),
                   self.make_setter_wrapper(name.name, s.type)]:
            res.extend(self.func_tf.generic_method_wrappers(fd))
        return res
    
    def generic_class_wrapper(self, tdef: TypeDef) -> TypeDef:
        """Construct a wrapper class for a generic type."""
        # FIX semanal meta-info for nodes + TypeInfo
        
        defs = [] # type: List[Node]
        
        # Does the type have a superclass, other than builtins.object?
        base = tdef.info.mro[1]
        has_proper_superclass = base.fullname() != 'builtins.object'
        
        if not has_proper_superclass or self.tf.is_java:
            # Generate member variables for wrapper object.
            defs.extend(self.make_generic_wrapper_member_vars(tdef))
        
        for alt in [False, BOUND_VAR]:
            defs.extend(self.make_tvar_representation(tdef.info, alt))
        
        # Generate constructor.
        defs.append(self.make_generic_wrapper_init(tdef.info))
        
        # Generate method wrappers.
        for d in tdef.defs.body:
            if isinstance(d, FuncDef):
                if not d.is_constructor():
                    defs.extend(self.func_tf.generic_method_wrappers(d))
            elif isinstance(d, AssignmentStmt):
                defs.extend(self.generic_accessor_wrappers(d))
            elif not isinstance(d, PassStmt):
                raise RuntimeError(
                    'Definition {} at line {} not supported'.format(
                        type(d), d.line))
        
        base_type = self.tf.named_type('builtins.object') # type: Type
        # Inherit superclass wrapper if there is one.
        if has_proper_superclass:
            base = self.find_generic_base_class(tdef.info)
            if base:
                # TODO bind the type somewhere
                base_type = UnboundType(base.defn.name +
                                        self.tf.wrapper_class_suffix())
        
        # Build the type definition.
        wrapper = TypeDef(tdef.name + self.tf.wrapper_class_suffix(),
                          Block(defs),
                          None,
                          [base_type])
        # FIX fullname
        
        self.tf.add_line_mapping(tdef, wrapper)
        
        return wrapper
    
    def find_generic_base_class(self, info: TypeInfo) -> TypeInfo:
        base = info.mro[1]
        while True:
            if base.type_vars != []:
                return base
            if len(base.mro) <= 1:
                return None
            base = base.mro[1]
    
    def make_generic_wrapper_member_vars(self, tdef: TypeDef) -> List[Node]:
        """Generate member variable definition for wrapped object (__o).
        
        This is added to a generic wrapper class.
        """
        # The type is 'Any' since it should behave covariantly in subclasses.
        return [VarDef([Var(self.object_member_name(tdef.info),
                            AnyType())], False, None)]
    
    def object_member_name(self, info: TypeInfo) -> str:
        if self.tf.is_java:
            return '__o_{}'.format(info.name)
        else:
            return '__o'
    
    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_tvar_representation(self, info: TypeInfo,
                                 is_alt: Any = False) -> List[Node]:
        """Return type variable slot member definitions.

        There are of form '__tv*: Any'. Only include new slots defined in the
        type.
        """
        defs = [] # type: List[Node]
        base_slots = num_slots(info.mro[1])
        for n in range(len(info.type_vars)):
            # Only include a type variable if it introduces a new slot.
            slot = get_tvar_access_path(info, n + 1)[0] - 1
            if slot >= base_slots:
                defs.append(VarDef([Var(tvar_slot_name(slot, is_alt),
                                        AnyType())], False, None))
        return defs
    
    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_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 make_tvar_init_expression(self, info: TypeInfo, slot: int) -> TypeExpr:
        """Return the initializer for the given slot in the given type.
        
        This is the type expression that initializes the given slot
        using the type arguments given to the constructor.
        
        Examples:
          - In 'class C(Generic[T]) ...', the initializer for the slot 0 is
            TypeExpr(RuntimeTypeVar(NameExpr('__tv'))).
          - In 'class D(C[int]) ...', the initializer for the slot 0 is
            TypeExpr(<int instance>).
        """
        # Figure out the superclass which defines the slot; also figure out
        # the tvar index that maps to the slot.
        origin, tv = find_slot_origin(info, slot)
        
        # Map self type to the superclass -> extract tvar with target index
        # (only contains subclass tvars?? PROBABLY NOT).
        selftype = self_type(info)
        selftype = map_instance_to_supertype(selftype, origin)
        tvar = selftype.args[tv - 1]
        
        # Map tvar to an expression; refer to local vars instead of member
        # vars always.
        tvar = translate_runtime_type_vars_locally(tvar)
        
        # Build the rvalue (initializer) expression
        return TypeExpr(tvar)

    def make_type_object_wrapper(self, tdef: TypeDef) -> FuncDef:
        """Construct dynamically typed wrapper function for a class.

        It simple calls the type object and returns the result.
        """
        
        # TODO keyword args, default args and varargs
        # TODO overloads

        type_sig = cast(Callable, type_object_type(tdef.info, None))
        type_sig = cast(Callable, erasetype.erase_typevars(type_sig))
        
        init = cast(FuncDef, tdef.info.get_method('__init__'))
        arg_kinds = type_sig.arg_kinds

        # The wrapper function has a dynamically typed signature.
        wrapper_sig = Callable( [AnyType()] * len(arg_kinds),
                               arg_kinds, [None] * len(arg_kinds),
                               AnyType(), False)
        
        n = NameExpr(tdef.name) # TODO full name
        args = self.func_tf.call_args(
            init.args[1:],
            type_sig,
            wrapper_sig,
            True, False)
        call = CallExpr(n, args, arg_kinds)
        ret = ReturnStmt(call)
        

        fdef = FuncDef(tdef.name + self.tf.dynamic_suffix(),
                       init.args[1:],
                       arg_kinds, [None] * len(arg_kinds),
                       Block([ret]))
        
        fdef.type = wrapper_sig
        return fdef

    def self_type(self) -> Instance:
        return self_type(self.tf.type_context())

    def make_scope(self) -> 'Scope':
        return Scope(self.tf.type_map)
        

class Scope:
    """Maintain a temporary local scope during transformation."""
    def __init__(self, type_map: Dict[Node, Type]) -> None:
        self.names = {} # type: Dict[str, Var]
        self.type_map = type_map

    def add(self, name: str, type: Type) -> Var:
        v = Var(name)
        v.type = type
        self.names[name] = v
        return v

    def name_expr(self, name: str) -> NameExpr:
        nexpr = NameExpr(name)
        nexpr.kind = nodes.LDEF
        node = self.names[name]
        nexpr.node = node
        self.type_map[nexpr] = node.type
        return nexpr

[(52, 'typing.Undefined', 'Undefined', False, 'from typing import Undefined, List, Set, Any, cast, Tuple, Dict\n'), (54, 'typing.Undefined', 'Undefined', False, 'from typing import Undefined, List, Set, Any, cast, Tuple, Dict\n'), (58, 'mypy.transformfunc.FuncTransformer', 'FuncTransformer', False, 'from mypy.transformfunc import FuncTransformer\n'), (110, 'mypy.nodes.Block', 'Block', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (216, 'mypy.nodes.SuperExpr', 'SuperExpr', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (223, 'mypy.semanal.self_type', 'self_type', False, 'from mypy.semanal import self_type\n'), (230, 'mypy.subtypes.map_instance_to_supertype', 'map_instance_to_supertype', False, 'from mypy.subtypes import map_instance_to_supertype\n'), (244, 'mypy.nodes.ExpressionStmt', 'ExpressionStmt', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (289, 'mypy.nodes.ReturnStmt', 'ReturnStmt', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (292, 'mypy.types.Callable', 'Callable', False, 'from mypy.types import Callable, Instance, Type, AnyType, BOUND_VAR, Void, RuntimeTypeVar, UnboundType\n'), (316, 'mypy.nodes.ReturnStmt', 'ReturnStmt', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (341, 'mypy.nodes.AssignmentStmt', 'AssignmentStmt', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (365, 'mypy.nodes.NameExpr', 'NameExpr', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (367, 'mypy.nodes.AssignmentStmt', 'AssignmentStmt', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (387, 'typing.cast', 'cast', False, 'from typing import Undefined, List, Set, Any, cast, Tuple, Dict\n'), (471, 'mypy.maptypevar.num_slots', 'num_slots', False, 'from mypy.maptypevar import num_slots, get_tvar_access_path\n'), (527, 'mypy.maptypevar.num_slots', 'num_slots', False, 'from mypy.maptypevar import num_slots, get_tvar_access_path\n'), (583, 'mypy.compileslotmap.find_slot_origin', 'find_slot_origin', False, 'from mypy.compileslotmap import find_slot_origin\n'), (587, 'mypy.semanal.self_type', 'self_type', False, 'from mypy.semanal import self_type\n'), (588, 'mypy.subtypes.map_instance_to_supertype', 'map_instance_to_supertype', False, 'from mypy.subtypes import map_instance_to_supertype\n'), (593, 'mypy.rttypevars.translate_runtime_type_vars_locally', 'translate_runtime_type_vars_locally', False, 'from mypy.rttypevars import translate_runtime_type_vars_locally\n'), (596, 'mypy.nodes.TypeExpr', 'TypeExpr', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (618, 'mypy.nodes.NameExpr', 'NameExpr', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (624, 'mypy.nodes.CallExpr', 'CallExpr', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (625, 'mypy.nodes.ReturnStmt', 'ReturnStmt', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (650, 'mypy.nodes.Var', 'Var', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (656, 'mypy.nodes.NameExpr', 'NameExpr', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (154, 'mypy.semanal.self_type', 'self_type', False, 'from mypy.semanal import self_type\n'), (175, 'mypy.transutil.prepend_arg_type', 'prepend_arg_type', False, 'from mypy.transutil import self_expr, tvar_slot_name, tvar_arg_name, prepend_arg_type\n'), (183, 'mypy.nodes.SymbolTableNode', 'SymbolTableNode', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (241, 'mypy.nodes.method_callable', 'nodes.method_callable', False, 'from mypy import nodes\n'), (270, 'mypy.types.AnyType', 'AnyType', False, 'from mypy.types import Callable, Instance, Type, AnyType, BOUND_VAR, Void, RuntimeTypeVar, UnboundType\n'), (297, 'mypy.nodes.Block', 'Block', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (314, 'mypy.types.AnyType', 'AnyType', False, 'from mypy.types import Callable, Instance, Type, AnyType, BOUND_VAR, Void, RuntimeTypeVar, UnboundType\n'), (319, 'mypy.types.AnyType', 'AnyType', False, 'from mypy.types import Callable, Instance, Type, AnyType, BOUND_VAR, Void, RuntimeTypeVar, UnboundType\n'), (324, 'mypy.nodes.Block', 'Block', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (347, 'mypy.types.Void', 'Void', False, 'from mypy.types import Callable, Instance, Type, AnyType, BOUND_VAR, Void, RuntimeTypeVar, UnboundType\n'), (352, 'mypy.nodes.Block', 'Block', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (364, 'mypy.transutil.self_expr', 'self_expr', False, 'from mypy.transutil import self_expr, tvar_slot_name, tvar_arg_name, prepend_arg_type\n'), (366, 'mypy.types.AnyType', 'AnyType', False, 'from mypy.types import Callable, Instance, Type, AnyType, BOUND_VAR, Void, RuntimeTypeVar, UnboundType\n'), (374, 'mypy.types.Void', 'Void', False, 'from mypy.types import Callable, Instance, Type, AnyType, BOUND_VAR, Void, RuntimeTypeVar, UnboundType\n'), (379, 'mypy.nodes.Block', 'Block', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (436, 'mypy.nodes.Block', 'Block', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (478, 'mypy.nodes.SuperExpr', 'SuperExpr', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (495, 'mypy.nodes.Var', 'Var', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (495, 'mypy.nodes.Var', 'Var', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (508, 'mypy.nodes.Block', 'Block', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (541, 'mypy.maptypevar.num_slots', 'num_slots', False, 'from mypy.maptypevar import num_slots, get_tvar_access_path\n'), (607, 'mypy.checkexpr.type_object_type', 'type_object_type', False, 'from mypy.checkexpr import type_object_type\n'), (608, 'mypy.erasetype.erase_typevars', 'erasetype.erase_typevars', False, 'from mypy import erasetype\n'), (616, 'mypy.types.AnyType', 'AnyType', False, 'from mypy.types import Callable, Instance, Type, AnyType, BOUND_VAR, Void, RuntimeTypeVar, UnboundType\n'), (631, 'mypy.nodes.Block', 'Block', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (92, 'typing.cast', 'cast', False, 'from typing import Undefined, List, Set, Any, cast, Tuple, Dict\n'), (105, 'mypy.nodes.PassStmt', 'PassStmt', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (155, 'mypy.checkmember.analyse_member_access', 'analyse_member_access', False, 'from mypy.checkmember import analyse_member_access\n'), (164, 'mypy.subtypes.map_instance_to_supertype', 'map_instance_to_supertype', False, 'from mypy.subtypes import map_instance_to_supertype\n'), (169, 'mypy.nodes.Var', 'Var', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (179, 'mypy.nodes.Block', 'Block', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (371, 'mypy.types.AnyType', 'AnyType', False, 'from mypy.types import Callable, Instance, Type, AnyType, BOUND_VAR, Void, RuntimeTypeVar, UnboundType\n'), (376, 'mypy.nodes.Var', 'Var', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (376, 'mypy.nodes.Var', 'Var', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (479, 'mypy.nodes.NameExpr', 'NameExpr', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (480, 'mypy.maptypevar.num_slots', 'num_slots', False, 'from mypy.maptypevar import num_slots, get_tvar_access_path\n'), (482, 'mypy.maptypevar.num_slots', 'num_slots', False, 'from mypy.maptypevar import num_slots, get_tvar_access_path\n'), (485, 'mypy.nodes.ExpressionStmt', 'ExpressionStmt', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (492, 'mypy.nodes.NameExpr', 'NameExpr', False, 'from mypy.nodes import TypeDef, Node, FuncDef, VarDef, Block, Var, ExpressionStmt, TypeInfo, SuperExpr, NameExpr, CallExpr, MDEF, MemberExpr, ReturnStmt, AssignmentStmt, TypeExpr, PassStmt, SymbolTableNode\n'), (511, 'mypy.types.Void', 'Void', False, 'from mypy.types import Callable, Instance, Type, AnyType, BOUND_VAR, Void, RuntimeTypeVar, UnboundType\n'), (547, 'mypy.types.AnyType', 'AnyType', False, 'from mypy.types import Callable, Instance, Type, AnyType, BOUND_VAR, Void, RuntimeTypeVar, UnboundType\n'), (548, 'mypy.types.AnyType', 'AnyType', False, 'from mypy.types import Callable, Instance, Type, AnyType, BOUND_VAR, Void, RuntimeTypeVar, UnboundType\n'), (558, 'mypy.maptypevar.num_slots', 'num_slots', False, 'from mypy.maptypevar import num_slots, get_tvar_access_path\n'), (530, 'mypy.maptypevar.get_tvar_access_path', 'get_tvar_access_path', False, 'from mypy.maptypevar import num_slots, get_tvar_access_path\n'), (565, 'mypy.types.AnyType', 'AnyType', False, 'from mypy.types import Callable, Instance, Type, AnyType, BOUND_VAR, Void, RuntimeTypeVar, UnboundType\n'), (566, 'mypy.types.AnyType', 'AnyType', False, 'from mypy.types import Callable, Instance, Type, AnyType, BOUND_VAR, Void, RuntimeTypeVar, UnboundType\n'), (614, 'mypy.types.AnyType', 'AnyType', False, 'from mypy.types import Callable, Instance, Type, AnyType, BOUND_VAR, Void, RuntimeTypeVar, UnboundType\n'), (461, 'mypy.types.AnyType', 'AnyType', False, 'from mypy.types import Callable, Instance, Type, AnyType, BOUND_VAR, Void, RuntimeTypeVar, UnboundType\n'), (481, 'mypy.transutil.tvar_arg_name', 'tvar_arg_name', False, 'from mypy.transutil import self_expr, tvar_slot_name, tvar_arg_name, prepend_arg_type\n'), (483, 'mypy.transutil.tvar_arg_name', 'tvar_arg_name', False, 'from mypy.transutil import self_expr, tvar_slot_name, tvar_arg_name, prepend_arg_type\n'), (489, 'mypy.transutil.self_expr', 'self_expr', False, 'from mypy.transutil import self_expr, tvar_slot_name, tvar_arg_name, prepend_arg_type\n'), (500, 'mypy.transutil.tvar_arg_name', 'tvar_arg_name', False, 'from mypy.transutil import self_expr, tvar_slot_name, tvar_arg_name, prepend_arg_type\n'), (509, 'mypy.types.AnyType', 'AnyType', False, 'from mypy.types import Callable, Instance, Type, AnyType, BOUND_VAR, Void, RuntimeTypeVar, UnboundType\n'), (543, 'mypy.transutil.self_expr', 'self_expr', False, 'from mypy.transutil import self_expr, tvar_slot_name, tvar_arg_name, prepend_arg_type\n'), (544, 'mypy.transutil.tvar_slot_name', 'tvar_slot_name', False, 'from mypy.transutil import self_expr, tvar_slot_name, tvar_arg_name, prepend_arg_type\n'), (560, 'mypy.transutil.tvar_slot_name', 'tvar_slot_name', False, 'from mypy.transutil import self_expr, tvar_slot_name, tvar_arg_name, prepend_arg_type\n'), (562, 'mypy.transutil.self_expr', 'self_expr', False, 'from mypy.transutil import self_expr, tvar_slot_name, tvar_arg_name, prepend_arg_type\n'), (563, 'mypy.transutil.tvar_slot_name', 'tvar_slot_name', False, 'from mypy.transutil import self_expr, tvar_slot_name, tvar_arg_name, prepend_arg_type\n'), (532, 'mypy.transutil.tvar_slot_name', 'tvar_slot_name', False, 'from mypy.transutil import self_expr, tvar_slot_name, tvar_arg_name, prepend_arg_type\n'), (533, 'mypy.types.AnyType', 'AnyType', False, 'from mypy.types import Callable, Instance, Type, AnyType, BOUND_VAR, Void, RuntimeTypeVar, UnboundType\n')]