main.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. """Transform a mypy AST to the IR form (Intermediate Representation).
  2. For example, consider a function like this:
  3. def f(x: int) -> int:
  4. return x * 2 + 1
  5. It would be translated to something that conceptually looks like this:
  6. r0 = 2
  7. r1 = 1
  8. r2 = x * r0 :: int
  9. r3 = r2 + r1 :: int
  10. return r3
  11. This module deals with the module-level IR transformation logic and
  12. putting it all together. The actual IR is implemented in mypyc.ir.
  13. For the core of the IR transform implementation, look at build_ir()
  14. below, mypyc.irbuild.builder, and mypyc.irbuild.visitor.
  15. """
  16. from __future__ import annotations
  17. from typing import Any, Callable, TypeVar, cast
  18. from mypy.build import Graph
  19. from mypy.nodes import ClassDef, Expression, MypyFile
  20. from mypy.state import state
  21. from mypy.types import Type
  22. from mypyc.analysis.attrdefined import analyze_always_defined_attrs
  23. from mypyc.common import TOP_LEVEL_NAME
  24. from mypyc.errors import Errors
  25. from mypyc.ir.func_ir import FuncDecl, FuncIR, FuncSignature
  26. from mypyc.ir.module_ir import ModuleIR, ModuleIRs
  27. from mypyc.ir.rtypes import none_rprimitive
  28. from mypyc.irbuild.builder import IRBuilder
  29. from mypyc.irbuild.mapper import Mapper
  30. from mypyc.irbuild.prebuildvisitor import PreBuildVisitor
  31. from mypyc.irbuild.prepare import build_type_map, find_singledispatch_register_impls
  32. from mypyc.irbuild.visitor import IRBuilderVisitor
  33. from mypyc.irbuild.vtable import compute_vtable
  34. from mypyc.options import CompilerOptions
  35. # The stubs for callable contextmanagers are busted so cast it to the
  36. # right type...
  37. F = TypeVar("F", bound=Callable[..., Any])
  38. strict_optional_dec = cast(Callable[[F], F], state.strict_optional_set(True))
  39. @strict_optional_dec # Turn on strict optional for any type manipulations we do
  40. def build_ir(
  41. modules: list[MypyFile],
  42. graph: Graph,
  43. types: dict[Expression, Type],
  44. mapper: Mapper,
  45. options: CompilerOptions,
  46. errors: Errors,
  47. ) -> ModuleIRs:
  48. """Build basic IR for a set of modules that have been type-checked by mypy.
  49. The returned IR is not complete and requires additional
  50. transformations, such as the insertion of refcount handling.
  51. """
  52. build_type_map(mapper, modules, graph, types, options, errors)
  53. singledispatch_info = find_singledispatch_register_impls(modules, errors)
  54. result: ModuleIRs = {}
  55. # Generate IR for all modules.
  56. class_irs = []
  57. for module in modules:
  58. # First pass to determine free symbols.
  59. pbv = PreBuildVisitor(errors, module, singledispatch_info.decorators_to_remove)
  60. module.accept(pbv)
  61. # Construct and configure builder objects (cyclic runtime dependency).
  62. visitor = IRBuilderVisitor()
  63. builder = IRBuilder(
  64. module.fullname,
  65. types,
  66. graph,
  67. errors,
  68. mapper,
  69. pbv,
  70. visitor,
  71. options,
  72. singledispatch_info.singledispatch_impls,
  73. )
  74. visitor.builder = builder
  75. # Second pass does the bulk of the work.
  76. transform_mypy_file(builder, module)
  77. module_ir = ModuleIR(
  78. module.fullname,
  79. list(builder.imports),
  80. builder.functions,
  81. builder.classes,
  82. builder.final_names,
  83. )
  84. result[module.fullname] = module_ir
  85. class_irs.extend(builder.classes)
  86. analyze_always_defined_attrs(class_irs)
  87. # Compute vtables.
  88. for cir in class_irs:
  89. if cir.is_ext_class:
  90. compute_vtable(cir)
  91. return result
  92. def transform_mypy_file(builder: IRBuilder, mypyfile: MypyFile) -> None:
  93. """Generate IR for a single module."""
  94. if mypyfile.fullname in ("typing", "abc"):
  95. # These module are special; their contents are currently all
  96. # built-in primitives.
  97. return
  98. builder.set_module(mypyfile.fullname, mypyfile.path)
  99. classes = [node for node in mypyfile.defs if isinstance(node, ClassDef)]
  100. # Collect all classes.
  101. for cls in classes:
  102. ir = builder.mapper.type_to_ir[cls.info]
  103. builder.classes.append(ir)
  104. builder.enter("<module>")
  105. # Make sure we have a builtins import
  106. builder.gen_import("builtins", -1)
  107. # Generate ops.
  108. for node in mypyfile.defs:
  109. builder.accept(node)
  110. builder.maybe_add_implicit_return()
  111. # Generate special function representing module top level.
  112. args, _, blocks, ret_type, _ = builder.leave()
  113. sig = FuncSignature([], none_rprimitive)
  114. func_ir = FuncIR(
  115. FuncDecl(TOP_LEVEL_NAME, None, builder.module_name, sig),
  116. args,
  117. blocks,
  118. traceback_name="<module>",
  119. )
  120. builder.functions.append(func_ir)