| from __future__ import annotations |
| |
| from mypyc.ir.class_ir import ClassIR |
| from mypyc.ir.deps import Dependency |
| from mypyc.ir.func_ir import FuncIR |
| from mypyc.ir.ops import Assign, CallC, PrimitiveOp |
| from mypyc.ir.rtypes import RStruct, RTuple, RType, RUnion, RVec |
| |
| |
| def find_implicit_op_dependencies(fn: FuncIR) -> set[Dependency] | None: |
| """Find implicit dependencies that need to be imported. |
| |
| Using primitives or types defined in librt submodules such as "librt.base64" |
| requires dependency imports (e.g., capsule imports). |
| |
| Note that a module can depend on a librt module even if it doesn't explicitly |
| import it, for example via re-exported names or via return types of functions |
| defined in other modules. |
| """ |
| deps: set[Dependency] | None = None |
| # Check function signature types for dependencies |
| deps = find_type_dependencies(fn, deps) |
| # Check ops for dependencies |
| for block in fn.blocks: |
| for op in block.ops: |
| assert not isinstance(op, PrimitiveOp), "Lowered IR is expected" |
| if isinstance(op, CallC) and op.dependencies is not None: |
| for dep in op.dependencies: |
| if deps is None: |
| deps = set() |
| deps.add(dep) |
| deps = collect_type_deps(op.type, deps) |
| if isinstance(op, Assign): |
| deps = collect_type_deps(op.dest.type, deps) |
| return deps |
| |
| |
| def find_type_dependencies(fn: FuncIR, deps: set[Dependency] | None) -> set[Dependency] | None: |
| """Find dependencies from RTypes in function signatures. |
| |
| Some RTypes (e.g., those for librt types) have associated dependencies |
| that need to be imported when the type is used. |
| """ |
| # Check parameter types |
| for arg in fn.decl.sig.args: |
| deps = collect_type_deps(arg.type, deps) |
| # Check return type |
| deps = collect_type_deps(fn.decl.sig.ret_type, deps) |
| return deps |
| |
| |
| def find_class_dependencies(cl: ClassIR) -> set[Dependency] | None: |
| """Find dependencies from class attribute types.""" |
| deps: set[Dependency] | None = None |
| for base in cl.mro: |
| for attr_type in base.attributes.values(): |
| deps = collect_type_deps(attr_type, deps) |
| return deps |
| |
| |
| def collect_type_deps(typ: RType, deps: set[Dependency] | None) -> set[Dependency] | None: |
| """Collect dependencies from an RType, recursively checking compound types.""" |
| if typ.dependencies is not None: |
| for dep in typ.dependencies: |
| if deps is None: |
| deps = set() |
| deps.add(dep) |
| if isinstance(typ, RUnion): |
| for item in typ.items: |
| deps = collect_type_deps(item, deps) |
| elif isinstance(typ, RTuple): |
| for item in typ.types: |
| deps = collect_type_deps(item, deps) |
| elif isinstance(typ, RStruct): |
| for item in typ.types: |
| deps = collect_type_deps(item, deps) |
| elif isinstance(typ, RVec): |
| deps = collect_type_deps(typ.item_type, deps) |
| return deps |