"""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 mypy.backports import OrderedDict from typing import List, Dict, Callable, Any, TypeVar, cast from mypy.nodes import MypyFile, Expression, ClassDef from mypy.types import Type from mypy.state import state from mypy.build import Graph from mypyc.common import TOP_LEVEL_NAME from mypyc.errors import Errors from mypyc.options import CompilerOptions from mypyc.ir.rtypes import none_rprimitive from mypyc.ir.module_ir import ModuleIR, ModuleIRs from mypyc.ir.func_ir import FuncIR, FuncDecl, FuncSignature from mypyc.irbuild.prebuildvisitor import PreBuildVisitor from mypyc.irbuild.vtable import compute_vtable from mypyc.irbuild.prepare import build_type_map, find_singledispatch_register_impls from mypyc.irbuild.builder import IRBuilder from mypyc.irbuild.visitor import IRBuilderVisitor from mypyc.irbuild.mapper import Mapper from mypyc.analysis.attrdefined import analyze_always_defined_attrs # 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 IR for a set of modules that have been type-checked by mypy.""" build_type_map(mapper, modules, graph, types, options, errors) singledispatch_info = find_singledispatch_register_impls(modules, errors) result: ModuleIRs = OrderedDict() # 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('') # 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="") builder.functions.append(func_ir)