Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ repos:
- id: isort
name: isort (python)
- repo: https://github.com/psf/black
rev: 25.1.0
rev: 26.1.0
hooks:
- id: black
- repo: https://github.com/charliermarsh/ruff-pre-commit
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ include = ["src/kirin/*"]

[tool.uv]
dev-dependencies = [
"black>=24.10.0",
"black>=26.1.0",
"coverage>=7.6.4",
"ipykernel>=6.29.5",
"ipython>=8.29.0",
Expand Down
36 changes: 10 additions & 26 deletions src/kirin/dialects/math/_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,7 @@ def builtin_math_functions():
ret_type = "types.Bool"
else:
ret_type = "types.Float"
f.write(
textwrap.dedent(
f"""
f.write(textwrap.dedent(f"""
@statement(dialect=dialect)
class {name}(ir.Statement):
\"\"\"{name} statement, wrapping the math.{name} function
Expand All @@ -71,9 +69,7 @@ class {name}(ir.Statement):
traits = frozenset({{ir.Pure(), lowering2.FromPythonCall()}})
{fields}
result: ir.ResultValue = info.result({ret_type})
"""
)
)
"""))


with open(os.path.join(os.path.dirname(__file__), "interp.py"), "w") as f:
Expand All @@ -89,23 +85,19 @@ class {name}(ir.Statement):
fields = ", ".join(
[f"values[{idx}]" for idx, _ in enumerate(sig.parameters.keys())]
)
implements.append(
f"""
implements.append(f"""
@impl(stmts.{name})
def {name}(self, interp, frame: Frame, stmt: stmts.{name}):
values = frame.get_values(stmt.args)
return (math.{name}({fields}),)"""
)
return (math.{name}({fields}),)""")

# Write the interpreter class
methods = "\n\n".join(implements)
f.write(
f"""
f.write(f"""
@dialect.register
class MathMethodTable(MethodTable):
{methods}
"""
)
""")

# __init__.py
with open(os.path.join(os.path.dirname(__file__), "__init__.py"), "w") as f:
Expand All @@ -124,14 +116,10 @@ class MathMethodTable(MethodTable):
ret_type = "bool"
else:
ret_type = "float"
f.write(
textwrap.dedent(
f"""
f.write(textwrap.dedent(f"""
@lowering2.wraps(stmts.{name})
def {name}({", ".join(f"{arg}: {ret_type}" for arg in sig.parameters.keys())}) -> {ret_type}: ...
"""
)
)
"""))
f.write("\n")

for file in ["__init__.py", "interp.py", "stmts.py"]:
Expand Down Expand Up @@ -178,16 +166,12 @@ def {name}({", ".join(f"{arg}: {ret_type}" for arg in sig.parameters.keys())}) -
args = ", ".join(arg for arg in sig.parameters.keys())
inputs = ", ".join("0.42" for _ in sig.parameters.keys())

f.write(
textwrap.dedent(
f"""
f.write(textwrap.dedent(f"""
@basic
def {name}_func({args}):
return math.{name}({args})

def test_{name}():
truth = pymath.{name}({inputs})
assert ({name}_func({inputs}) - truth) < 1e-6
"""
)
)
"""))
7 changes: 6 additions & 1 deletion src/kirin/interp/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,12 @@ def new_frame(
self.state.push_frame(frame)
try:
yield frame
finally:
except BaseException:
# NOTE: Don't pop frames on exception so that eval_context
# can capture the full frame chain for the stack trace.
# The state is re-initialized on the next eval_context call.
raise
Comment on lines +267 to +271
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new_frame now catches BaseException and deliberately leaves frames on the interpreter state. This means KeyboardInterrupt/SystemExit will also leave the interpreter stack dirty, and it also doesn't line up with eval_context, which only annotates Exception instances with KIRIN_INTERP_STATE. Consider catching Exception here (or alternatively updating eval_context to handle BaseException and resetting self.state after attaching it to the raised exception) so non-error control-flow exceptions don't leak frames.

Copilot uses AI. Check for mistakes.
else:
self.state.pop_frame()
Comment on lines +268 to 273
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because frames are no longer popped on exception, there’s currently no test coverage ensuring the source traceback includes the expected statement when KIRIN_PYTHON_STACKTRACE=0. Adding a regression test that triggers an interpreter error and asserts the printed stack trace contains the originating stmt/source would prevent this from silently regressing.

Copilot uses AI. Check for mistakes.

def frame_eval(
Expand Down
6 changes: 2 additions & 4 deletions src/kirin/lowering/python/binding.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,8 @@ class Binding(Generic[Params, RetType]):
parent: type["Statement"]

def __call__(self, *args: Params.args, **kwargs: Params.kwargs) -> RetType:
raise NotImplementedError(
f"Binding of {self.parent.name} can \
only be called from a kernel"
)
raise NotImplementedError(f"Binding of {self.parent.name} can \
only be called from a kernel")


def wraps(parent: type["Statement"]):
Expand Down
4 changes: 2 additions & 2 deletions test/lowering/test_assign.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class MultiResult(ir.Statement):
def test_multi_result():
@dummy_dialect
def multi_assign():
(x, y) = MultiResult() # type: ignore
x, y = MultiResult() # type: ignore
return x, y

stmt = multi_assign.callable_region.blocks[0].stmts.at(0)
Expand All @@ -33,7 +33,7 @@ def multi_assign():

@dummy_dialect
def multi_assign_error():
(x, y, z) = MultiResult() # type: ignore
x, y, z = MultiResult() # type: ignore
return x, y, z


Expand Down
Loading