Skip to content

analyzer

Compose the specialized semantic visitor mixins around a shared analyzer core so traversal, registration, bindings, and rule logic live in smaller modules.

Classes:

SemanticAnalyzer

SemanticAnalyzer(
    *,
    context: SemanticContext | None = None,
    session: CompilationSession | None = None,
)

Bases: ImportVisitorMixin, TemplateVisitorMixin, DeclarationVisitorMixin, ExpressionVisitorMixin, ControlFlowVisitorMixin, SemanticAnalyzerCore

Walk AST nodes, attach semantic sidecars, and delegate reusable policy to the extracted factories, registries, and binding tables.

Methods:

Source code in packages/irx/src/irx/analysis/handlers/base.py
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
def __init__(
    self,
    *,
    context: SemanticContext | None = None,
    session: CompilationSession | None = None,
) -> None:
    """
    title: Initialize SemanticAnalyzerCore.
    parameters:
      context:
        type: SemanticContext | None
      session:
        type: CompilationSession | None
    """
    self.session = session
    self.context = context or SemanticContext()
    if session is not None:
        self.context.diagnostics = session.diagnostics
    self.factory = SemanticEntityFactory(self.context)
    self.registry = SemanticRegistry(self.context, self.factory)
    self.bindings = VisibleBindings(
        context=self.context,
        factory=self.factory,
        bindings=(
            session.visible_bindings if session is not None else None
        ),
    )

analyze

analyze(node: AST) -> AST
Source code in packages/irx/src/irx/analysis/handlers/base.py
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
def analyze(self, node: astx.AST) -> astx.AST:
    """
    title: Analyze one AST root.
    parameters:
      node:
        type: astx.AST
    returns:
      type: astx.AST
    """
    if isinstance(node, astx.Module):
        parsed_module = ParsedModule(node.name, node)
        self.analyze_parsed_module(parsed_module, predeclared=False)
    else:
        with self.context.scope("module"):
            self.visit(node)
    self.context.diagnostics.raise_if_errors()
    return node

analyze_parsed_module

analyze_parsed_module(
    parsed_module: ParsedModule, *, predeclared: bool
) -> Module
Source code in packages/irx/src/irx/analysis/handlers/base.py
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
def analyze_parsed_module(
    self,
    parsed_module: ParsedModule,
    *,
    predeclared: bool,
) -> astx.Module:
    """
    title: Analyze one parsed module.
    parameters:
      parsed_module:
        type: ParsedModule
      predeclared:
        type: bool
    returns:
      type: astx.Module
    """
    if not predeclared:
        reset_templates = getattr(
            self,
            "_reset_template_analysis_state",
            None,
        )
        if callable(reset_templates):
            reset_templates(parsed_module.ast)
    with self.context.in_module(parsed_module.key):
        self._visit_module(parsed_module.ast, predeclared=predeclared)
    return parsed_module.ast

visit

visit(node: ImportFromExpr) -> None
Source code in packages/irx/src/irx/analysis/handlers/imports.py
180
181
182
183
184
185
186
187
188
189
190
191
192
@SemanticAnalyzerCore.visit.dispatch
def visit(self, node: astx.ImportFromExpr) -> None:
    """
    title: Visit ImportFromExpr nodes.
    parameters:
      node:
        type: astx.ImportFromExpr
    """
    self.context.diagnostics.add(
        "Import expressions are not supported in this MVP.",
        node=node,
    )
    self._set_type(node, None)