| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- """Transform a mypy AST to the IR form (Intermediate Representation).
- For example, consider a function like this:
- def f(x: int) -> int:
- return x * 2 + 1
- It would be translated to something that conceptually looks like this:
- r0 = 2
- r1 = 1
- r2 = x * r0 :: int
- r3 = r2 + r1 :: int
- return r3
- This module deals with the module-level IR transformation logic and
- putting it all together. The actual IR is implemented in mypyc.ir.
- For the core of the IR transform implementation, look at build_ir()
- below, mypyc.irbuild.builder, and mypyc.irbuild.visitor.
- """
- from __future__ import annotations
- from typing import Any, Callable, TypeVar, cast
- from mypy.build import Graph
- from mypy.nodes import ClassDef, Expression, MypyFile
- from mypy.state import state
- from mypy.types import Type
- from mypyc.analysis.attrdefined import analyze_always_defined_attrs
- from mypyc.common import TOP_LEVEL_NAME
- from mypyc.errors import Errors
- from mypyc.ir.func_ir import FuncDecl, FuncIR, FuncSignature
- from mypyc.ir.module_ir import ModuleIR, ModuleIRs
- from mypyc.ir.rtypes import none_rprimitive
- from mypyc.irbuild.builder import IRBuilder
- from mypyc.irbuild.mapper import Mapper
- from mypyc.irbuild.prebuildvisitor import PreBuildVisitor
- from mypyc.irbuild.prepare import build_type_map, find_singledispatch_register_impls
- from mypyc.irbuild.visitor import IRBuilderVisitor
- from mypyc.irbuild.vtable import compute_vtable
- from mypyc.options import CompilerOptions
- # The stubs for callable contextmanagers are busted so cast it to the
- # right type...
- F = TypeVar("F", bound=Callable[..., Any])
- strict_optional_dec = cast(Callable[[F], F], state.strict_optional_set(True))
- @strict_optional_dec # Turn on strict optional for any type manipulations we do
- def build_ir(
- modules: list[MypyFile],
- graph: Graph,
- types: dict[Expression, Type],
- mapper: Mapper,
- options: CompilerOptions,
- errors: Errors,
- ) -> ModuleIRs:
- """Build basic IR for a set of modules that have been type-checked by mypy.
- The returned IR is not complete and requires additional
- transformations, such as the insertion of refcount handling.
- """
- build_type_map(mapper, modules, graph, types, options, errors)
- singledispatch_info = find_singledispatch_register_impls(modules, errors)
- result: ModuleIRs = {}
- # Generate IR for all modules.
- class_irs = []
- for module in modules:
- # First pass to determine free symbols.
- pbv = PreBuildVisitor(errors, module, singledispatch_info.decorators_to_remove)
- module.accept(pbv)
- # Construct and configure builder objects (cyclic runtime dependency).
- visitor = IRBuilderVisitor()
- builder = IRBuilder(
- module.fullname,
- types,
- graph,
- errors,
- mapper,
- pbv,
- visitor,
- options,
- singledispatch_info.singledispatch_impls,
- )
- visitor.builder = builder
- # Second pass does the bulk of the work.
- transform_mypy_file(builder, module)
- module_ir = ModuleIR(
- module.fullname,
- list(builder.imports),
- builder.functions,
- builder.classes,
- builder.final_names,
- )
- result[module.fullname] = module_ir
- class_irs.extend(builder.classes)
- analyze_always_defined_attrs(class_irs)
- # Compute vtables.
- for cir in class_irs:
- if cir.is_ext_class:
- compute_vtable(cir)
- return result
- def transform_mypy_file(builder: IRBuilder, mypyfile: MypyFile) -> None:
- """Generate IR for a single module."""
- if mypyfile.fullname in ("typing", "abc"):
- # These module are special; their contents are currently all
- # built-in primitives.
- return
- builder.set_module(mypyfile.fullname, mypyfile.path)
- classes = [node for node in mypyfile.defs if isinstance(node, ClassDef)]
- # Collect all classes.
- for cls in classes:
- ir = builder.mapper.type_to_ir[cls.info]
- builder.classes.append(ir)
- builder.enter("<module>")
- # Make sure we have a builtins import
- builder.gen_import("builtins", -1)
- # Generate ops.
- for node in mypyfile.defs:
- builder.accept(node)
- builder.maybe_add_implicit_return()
- # Generate special function representing module top level.
- args, _, blocks, ret_type, _ = builder.leave()
- sig = FuncSignature([], none_rprimitive)
- func_ir = FuncIR(
- FuncDecl(TOP_LEVEL_NAME, None, builder.module_name, sig),
- args,
- blocks,
- traceback_name="<module>",
- )
- builder.functions.append(func_ir)
|