Skip to content

Abstract

AbstractFrame dataclass

AbstractFrame(
    code: Statement,
    worklist: WorkList[Successor[ResultType]] = WorkList(),
    visited: dict[
        ir.Block, set[Successor[ResultType]]
    ] = dict(),
    *,
    parent: Self | None = None,
    has_parent_access: bool = False,
    lineno_offset: int = 0,
    entries: dict[SSAValue, ValueType] = dict()
)

Bases: Frame[ResultType]

Interpreter frame for abstract interpreter.

This frame is used to store the state of the abstract interpreter. It contains the worklist of successors to be processed.

AbstractInterpreter dataclass

AbstractInterpreter(
    dialects: ir.DialectGroup,
    *,
    max_depth: int = 800,
    max_python_recursion_depth: int = 131072,
    debug: bool = False
)

Bases: InterpreterABC[AbstractFrameType, ResultType], ABC

Abstract interpreter for the IR.

This is a base class for implementing abstract interpreters for the IR. It provides a framework for implementing abstract interpreters given a bounded lattice type.

The abstract interpreter is a forward dataflow analysis that computes the abstract values for each SSA value in the IR. The abstract values are computed by evaluating the statements in the IR using the abstract lattice operations.

The abstract interpreter is implemented as a worklist algorithm. The worklist contains the successors of the current block to be processed. The abstract interpreter processes each successor by evaluating the statements in the block and updating the abstract values in the frame.

The abstract interpreter provides hooks for customizing the behavior of the interpreter. The [prehook_succ][kirin.interp.abstract.AbstractInterpreter.prehook_succ] and [posthook_succ][kirin.interp.abstract.AbstractInterpreter.posthook_succ] methods can be used to perform custom actions before and after processing a successor.

lattice class-attribute instance-attribute

lattice: type[BoundedLattice[ResultType]] = field(
    init=False
)

lattice type for the abstract interpreter.

expect_const classmethod

expect_const(value: ir.SSAValue, type_: type[T])

Expect a constant value of a given type.

If the value is not a constant or the constant is not of the given type, raise an InterpreterError.

Source code in src/kirin/interp/abstract.py
146
147
148
149
150
151
152
153
154
155
156
@classmethod
def expect_const(cls, value: ir.SSAValue, type_: type[T]):
    """Expect a constant value of a given type.

    If the value is not a constant or the constant is not of the given type, raise
    an `InterpreterError`.
    """
    hint = cls.maybe_const(value, type_)
    if hint is None:
        raise InterpreterError(f"expected {type_}, got {hint}")
    return hint

maybe_const classmethod

maybe_const(value: ir.SSAValue, type_: type[T]) -> T | None

Get a constant value of a given type.

If the value is not a constant or the constant is not of the given type, return None.

Source code in src/kirin/interp/abstract.py
133
134
135
136
137
138
139
140
141
142
143
144
@classmethod
def maybe_const(cls, value: ir.SSAValue, type_: type[T]) -> T | None:
    """Get a constant value of a given type.

    If the value is not a constant or the constant is not of the given type, return
    `None`.
    """
    from kirin.analysis.const.lattice import Value

    hint = value.hints.get("const")
    if isinstance(hint, Value) and isinstance(hint.data, type_):
        return hint.data

recursion_limit_reached

recursion_limit_reached() -> ResultType

Handle the recursion limit reached.

This method is called when the maximum depth of the interpreter stack when calling a callable node is reached. By default a StackOverflowError is raised. Overload this method to provide a custom behavior, e.g. in the case of abstract interpreter, the recursion limit returns a bottom value.

Source code in src/kirin/interp/abstract.py
79
80
def recursion_limit_reached(self) -> ResultType:
    return self.lattice.bottom()