Example #1
0
def setup_env_class(builder: IRBuilder) -> ClassIR:
    """Generate a class representing a function environment.

    Note that the variables in the function environment are not
    actually populated here. This is because when the environment
    class is generated, the function environment has not yet been
    visited. This behavior is allowed so that when the compiler visits
    nested functions, it can use the returned ClassIR instance to
    figure out free variables it needs to access.  The remaining
    attributes of the environment class are populated when the
    environment registers are loaded.

    Return a ClassIR representing an environment for a function
    containing a nested function.
    """
    env_class = ClassIR('{}_env'.format(builder.fn_info.namespaced_name()),
                        builder.module_name,
                        is_generated=True)
    env_class.attributes[SELF_NAME] = RInstance(env_class)
    if builder.fn_info.is_nested:
        # If the function is nested, its environment class must contain an environment
        # attribute pointing to its encapsulating functions' environment class.
        env_class.attributes[ENV_ATTR_NAME] = RInstance(
            builder.fn_infos[-2].env_class)
    env_class.mro = [env_class]
    builder.fn_info.env_class = env_class
    builder.classes.append(env_class)
    return env_class
Example #2
0
def deserialize_modules(data: Dict[str, JsonDict],
                        ctx: DeserMaps) -> Dict[str, ModuleIR]:
    """Deserialize a collection of modules.

    The modules can contain dependencies on each other.

    Arguments:
        data: A dict containing the modules to deserialize.
        ctx: The deserialization maps to use and to populate.
             They are populated with information from the deserialized
             modules and as a precondition must have been populated by
             deserializing any dependencies of the modules being deserialized
             (outside of dependencies between the modules themselves).

    Returns a map containing the deserialized modules.
    """
    for mod in data.values():
        # First create ClassIRs for every class so that we can construct types and whatnot
        for cls in mod['classes']:
            ir = ClassIR(cls['name'], cls['module_name'])
            assert ir.fullname not in ctx.classes, "Class %s already in map" % ir.fullname
            ctx.classes[ir.fullname] = ir

    for mod in data.values():
        # Then deserialize all of the functions so that methods are available
        # to the class deserialization.
        for method in mod['functions']:
            func = FuncIR.deserialize(method, ctx)
            assert func.decl.fullname not in ctx.functions, (
                "Method %s already in map" % func.decl.fullname)
            ctx.functions[func.decl.fullname] = func

    return {k: ModuleIR.deserialize(v, ctx) for k, v in data.items()}
Example #3
0
    def setUp(self) -> None:
        self.env = Environment()
        self.n = self.env.add_local(Var('n'), int_rprimitive)
        self.m = self.env.add_local(Var('m'), int_rprimitive)
        self.k = self.env.add_local(Var('k'), int_rprimitive)
        self.l = self.env.add_local(Var('l'), list_rprimitive)  # noqa
        self.ll = self.env.add_local(Var('ll'), list_rprimitive)
        self.o = self.env.add_local(Var('o'), object_rprimitive)
        self.o2 = self.env.add_local(Var('o2'), object_rprimitive)
        self.d = self.env.add_local(Var('d'), dict_rprimitive)
        self.b = self.env.add_local(Var('b'), bool_rprimitive)
        self.s1 = self.env.add_local(Var('s1'), short_int_rprimitive)
        self.s2 = self.env.add_local(Var('s2'), short_int_rprimitive)
        self.i32 = self.env.add_local(Var('i32'), int32_rprimitive)
        self.i32_1 = self.env.add_local(Var('i32_1'), int32_rprimitive)
        self.i64 = self.env.add_local(Var('i64'), int64_rprimitive)
        self.i64_1 = self.env.add_local(Var('i64_1'), int64_rprimitive)
        self.ptr = self.env.add_local(Var('ptr'), pointer_rprimitive)
        self.t = self.env.add_local(Var('t'),
                                    RTuple([int_rprimitive, bool_rprimitive]))
        self.tt = self.env.add_local(
            Var('tt'),
            RTuple(
                [RTuple([int_rprimitive, bool_rprimitive]), bool_rprimitive]))
        ir = ClassIR('A', 'mod')
        ir.attributes = OrderedDict([('x', bool_rprimitive),
                                     ('y', int_rprimitive)])
        compute_vtable(ir)
        ir.mro = [ir]
        self.r = self.env.add_local(Var('r'), RInstance(ir))

        self.context = EmitterContext(NameGenerator([['mod']]))
Example #4
0
    def setUp(self) -> None:
        self.env = Environment()
        self.n = self.env.add_local(Var('n'), int_rprimitive)
        self.m = self.env.add_local(Var('m'), int_rprimitive)
        self.k = self.env.add_local(Var('k'), int_rprimitive)
        self.l = self.env.add_local(Var('l'), list_rprimitive)  # noqa
        self.ll = self.env.add_local(Var('ll'), list_rprimitive)
        self.o = self.env.add_local(Var('o'), object_rprimitive)
        self.o2 = self.env.add_local(Var('o2'), object_rprimitive)
        self.d = self.env.add_local(Var('d'), dict_rprimitive)
        self.b = self.env.add_local(Var('b'), bool_rprimitive)
        self.t = self.env.add_local(Var('t'),
                                    RTuple([int_rprimitive, bool_rprimitive]))
        self.tt = self.env.add_local(
            Var('tt'),
            RTuple(
                [RTuple([int_rprimitive, bool_rprimitive]), bool_rprimitive]))
        ir = ClassIR('A', 'mod')
        ir.attributes = OrderedDict([('x', bool_rprimitive),
                                     ('y', int_rprimitive)])
        compute_vtable(ir)
        ir.mro = [ir]
        self.r = self.env.add_local(Var('r'), RInstance(ir))

        self.context = EmitterContext(NameGenerator([['mod']]))
        self.emitter = Emitter(self.context, self.env)
        self.declarations = Emitter(self.context, self.env)
        self.visitor = FunctionEmitterVisitor(self.emitter, self.declarations,
                                              'prog.py', 'prog')
Example #5
0
def setup_generator_class(builder: IRBuilder) -> ClassIR:
    name = '{}_gen'.format(builder.fn_info.namespaced_name())

    generator_class_ir = ClassIR(name, builder.module_name, is_generated=True)
    generator_class_ir.attributes[ENV_ATTR_NAME] = RInstance(builder.fn_info.env_class)
    generator_class_ir.mro = [generator_class_ir]

    builder.classes.append(generator_class_ir)
    builder.fn_info.generator_class = GeneratorClass(generator_class_ir)
    return generator_class_ir
Example #6
0
def setup_callable_class(builder: IRBuilder) -> None:
    """Generates a callable class representing a nested function or a function within a
    non-extension class and sets up the 'self' variable for that class.

    This takes the most recently visited function and returns a ClassIR to represent that
    function. Each callable class contains an environment attribute with points to another
    ClassIR representing the environment class where some of its variables can be accessed.
    Note that its '__call__' method is not yet implemented, and is implemented in the
    add_call_to_callable_class function.

    Returns a newly constructed ClassIR representing the callable class for the nested
    function.
    """

    # Check to see that the name has not already been taken. If so, rename the class. We allow
    # multiple uses of the same function name because this is valid in if-else blocks. Example:
    #     if True:
    #         def foo():          ---->    foo_obj()
    #             return True
    #     else:
    #         def foo():          ---->    foo_obj_0()
    #             return False
    name = base_name = '{}_obj'.format(builder.fn_info.namespaced_name())
    count = 0
    while name in builder.callable_class_names:
        name = base_name + '_' + str(count)
        count += 1
    builder.callable_class_names.add(name)

    # Define the actual callable class ClassIR, and set its environment to point at the
    # previously defined environment class.
    callable_class_ir = ClassIR(name, builder.module_name, is_generated=True)

    # The functools @wraps decorator attempts to call setattr on nested functions, so
    # we create a dict for these nested functions.
    # https://github.com/python/cpython/blob/3.7/Lib/functools.py#L58
    if builder.fn_info.is_nested:
        callable_class_ir.has_dict = True

    # If the enclosing class doesn't contain nested (which will happen if
    # this is a toplevel lambda), don't set up an environment.
    if builder.fn_infos[-2].contains_nested:
        callable_class_ir.attributes[ENV_ATTR_NAME] = RInstance(
            builder.fn_infos[-2].env_class
        )
    callable_class_ir.mro = [callable_class_ir]
    builder.fn_info.callable_class = ImplicitClass(callable_class_ir)
    builder.classes.append(callable_class_ir)

    # Add a 'self' variable to the callable class' environment, and store that variable in a
    # register to be accessed later.
    self_target = add_self_to_env(builder.environment, callable_class_ir)
    builder.fn_info.callable_class.self_reg = builder.read(self_target, builder.fn_info.fitem.line)
Example #7
0
def build_type_map(mapper: Mapper, modules: List[MypyFile], graph: Graph,
                   types: Dict[Expression, Type], options: CompilerOptions,
                   errors: Errors) -> None:
    # Collect all classes defined in everything we are compiling
    classes = []
    for module in modules:
        module_classes = [
            node for node in module.defs if isinstance(node, ClassDef)
        ]
        classes.extend([(module, cdef) for cdef in module_classes])

    # Collect all class mappings so that we can bind arbitrary class name
    # references even if there are import cycles.
    for module, cdef in classes:
        class_ir = ClassIR(cdef.name,
                           module.fullname,
                           is_trait(cdef),
                           is_abstract=cdef.info.is_abstract)
        class_ir.is_ext_class = is_extension_class(cdef)
        if class_ir.is_ext_class:
            class_ir.deletable = cdef.info.deletable_attributes[:]
        # If global optimizations are disabled, turn of tracking of class children
        if not options.global_opts:
            class_ir.children = None
        mapper.type_to_ir[cdef.info] = class_ir

    # Populate structural information in class IR for extension classes.
    for module, cdef in classes:
        with catch_errors(module.path, cdef.line):
            if mapper.type_to_ir[cdef.info].is_ext_class:
                prepare_class_def(module.path, module.fullname, cdef, errors,
                                  mapper)
            else:
                prepare_non_ext_class_def(module.path, module.fullname, cdef,
                                          errors, mapper)

    # Collect all the functions also. We collect from the symbol table
    # so that we can easily pick out the right copy of a function that
    # is conditionally defined.
    for module in modules:
        for func in get_module_func_defs(module):
            prepare_func_def(module.fullname, None, func, mapper)
Example #8
0
    def test_can_coerce_to(self) -> None:
        cls = ClassIR(name="Cls", module_name="cls")
        valid_cases = [
            (int64_rprimitive, int64_rprimitive),
            (str_rprimitive, str_rprimitive),
            (str_rprimitive, object_rprimitive),
            (object_rprimitive, str_rprimitive),
            (RUnion([bytes_rprimitive, str_rprimitive]), str_rprimitive),
            (str_rprimitive, RUnion([bytes_rprimitive, str_rprimitive])),
            (RInstance(cls), object_rprimitive),
        ]

        invalid_cases = [
            (int64_rprimitive, int32_rprimitive),
            (RInstance(cls), str_rprimitive),
            (str_rprimitive, bytes_rprimitive),
        ]

        for src, dest in valid_cases:
            assert can_coerce_to(src, dest)
        for src, dest in invalid_cases:
            assert not can_coerce_to(src, dest)
Example #9
0
    def setUp(self) -> None:
        self.registers = []  # type: List[Register]

        def add_local(name: str, rtype: RType) -> Register:
            reg = Register(rtype, name)
            self.registers.append(reg)
            return reg

        self.n = add_local('n', int_rprimitive)
        self.m = add_local('m', int_rprimitive)
        self.k = add_local('k', int_rprimitive)
        self.l = add_local('l', list_rprimitive)  # noqa
        self.ll = add_local('ll', list_rprimitive)
        self.o = add_local('o', object_rprimitive)
        self.o2 = add_local('o2', object_rprimitive)
        self.d = add_local('d', dict_rprimitive)
        self.b = add_local('b', bool_rprimitive)
        self.s1 = add_local('s1', short_int_rprimitive)
        self.s2 = add_local('s2', short_int_rprimitive)
        self.i32 = add_local('i32', int32_rprimitive)
        self.i32_1 = add_local('i32_1', int32_rprimitive)
        self.i64 = add_local('i64', int64_rprimitive)
        self.i64_1 = add_local('i64_1', int64_rprimitive)
        self.ptr = add_local('ptr', pointer_rprimitive)
        self.t = add_local('t', RTuple([int_rprimitive, bool_rprimitive]))
        self.tt = add_local(
            'tt',
            RTuple(
                [RTuple([int_rprimitive, bool_rprimitive]), bool_rprimitive]))
        ir = ClassIR('A', 'mod')
        ir.attributes = OrderedDict([('x', bool_rprimitive),
                                     ('y', int_rprimitive)])
        compute_vtable(ir)
        ir.mro = [ir]
        self.r = add_local('r', RInstance(ir))

        self.context = EmitterContext(NameGenerator([['mod']]))
Example #10
0
 def setUp(self) -> None:
     self.inst_a = RInstance(ClassIR('A', '__main__'))
     self.inst_b = RInstance(ClassIR('B', '__main__'))