from typing import TypeVar
from dataclasses import field, dataclass

from kirin import ir, types, interp
from kirin.worklist import WorkList

ValueType = TypeVar("ValueType")

@dataclass
class EmitFrame(interp.Frame[ValueType]):
    worklist: WorkList[interp.Successor] = field(default_factory=WorkList)
    block_ref: dict[ir.Block, ValueType] = field(default_factory=dict)

FrameType = TypeVar("FrameType", bound=EmitFrame)

class EmitABC(interp.BaseInterpreter[FrameType, ValueType]):
    def run_callable_region(
        self,
        frame: FrameType,
        code: ir.Statement,
        region: ir.Region,
        args: tuple[ValueType, ...],
    ) -> ValueType: ...
    def run_ssacfg_region(
        self, frame: FrameType, region: ir.Region, args: tuple[ValueType, ...]
    ) -> tuple[ValueType, ...]: ...
    def emit_attribute(self, attr: ir.Attribute) -> ValueType: ...
    def emit_type_Any(self, attr: types.AnyType) -> ValueType: ...
    def emit_type_Bottom(self, attr: types.BottomType) -> ValueType: ...
    def emit_type_Literal(self, attr: types.Literal) -> ValueType: ...
    def emit_type_Union(self, attr: types.Union) -> ValueType: ...
    def emit_type_TypeVar(self, attr: types.TypeVar) -> ValueType: ...
    def emit_type_Vararg(self, attr: types.Vararg) -> ValueType: ...
    def emit_type_Generic(self, attr: types.Generic) -> ValueType: ...
    def emit_type_PyClass(self, attr: types.PyClass) -> ValueType: ...
    def emit_type_PyAttr(self, attr: ir.PyAttr) -> ValueType: ...
    def emit_attribute_fallback(self, attr: ir.Attribute) -> ValueType: ...
    def emit_stmt_begin(self, frame: FrameType, stmt: ir.Statement) -> None: ...
    def emit_stmt_end(self, frame: FrameType, stmt: ir.Statement) -> None: ...
    def emit_block_begin(self, frame: FrameType, block: ir.Block) -> None: ...
    def emit_block_end(self, frame: FrameType, block: ir.Block) -> None: ...
    def emit_block(self, frame: FrameType, block: ir.Block) -> ValueType: ...
