kirin-toolchain 0.13.0__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- kirin/__init__.py +7 -0
- kirin/analysis/__init__.py +24 -0
- kirin/analysis/callgraph.py +61 -0
- kirin/analysis/cfg.py +112 -0
- kirin/analysis/const/__init__.py +20 -0
- kirin/analysis/const/_visitor.py +2 -0
- kirin/analysis/const/_visitor.pyi +8 -0
- kirin/analysis/const/lattice.py +219 -0
- kirin/analysis/const/prop.py +116 -0
- kirin/analysis/forward.py +100 -0
- kirin/analysis/typeinfer/__init__.py +5 -0
- kirin/analysis/typeinfer/analysis.py +90 -0
- kirin/analysis/typeinfer/solve.py +141 -0
- kirin/decl/__init__.py +108 -0
- kirin/decl/base.py +65 -0
- kirin/decl/camel2snake.py +2 -0
- kirin/decl/emit/__init__.py +0 -0
- kirin/decl/emit/_create_fn.py +29 -0
- kirin/decl/emit/_set_new_attribute.py +22 -0
- kirin/decl/emit/dialect.py +8 -0
- kirin/decl/emit/init.py +277 -0
- kirin/decl/emit/name.py +10 -0
- kirin/decl/emit/property.py +182 -0
- kirin/decl/emit/repr.py +31 -0
- kirin/decl/emit/traits.py +13 -0
- kirin/decl/emit/typecheck.py +77 -0
- kirin/decl/emit/verify.py +51 -0
- kirin/decl/info.py +346 -0
- kirin/decl/scan_fields.py +157 -0
- kirin/decl/verify.py +69 -0
- kirin/dialects/__init__.py +14 -0
- kirin/dialects/_pprint_helper.py +53 -0
- kirin/dialects/cf/__init__.py +20 -0
- kirin/dialects/cf/constprop.py +51 -0
- kirin/dialects/cf/dialect.py +3 -0
- kirin/dialects/cf/emit.py +58 -0
- kirin/dialects/cf/interp.py +24 -0
- kirin/dialects/cf/stmts.py +68 -0
- kirin/dialects/cf/typeinfer.py +27 -0
- kirin/dialects/eltype.py +23 -0
- kirin/dialects/func/__init__.py +20 -0
- kirin/dialects/func/attrs.py +39 -0
- kirin/dialects/func/constprop.py +138 -0
- kirin/dialects/func/dialect.py +3 -0
- kirin/dialects/func/emit.py +80 -0
- kirin/dialects/func/interp.py +68 -0
- kirin/dialects/func/stmts.py +233 -0
- kirin/dialects/func/typeinfer.py +124 -0
- kirin/dialects/ilist/__init__.py +33 -0
- kirin/dialects/ilist/_dialect.py +3 -0
- kirin/dialects/ilist/_wrapper.py +51 -0
- kirin/dialects/ilist/interp.py +85 -0
- kirin/dialects/ilist/lowering.py +25 -0
- kirin/dialects/ilist/passes.py +32 -0
- kirin/dialects/ilist/rewrite/__init__.py +3 -0
- kirin/dialects/ilist/rewrite/const.py +45 -0
- kirin/dialects/ilist/rewrite/list.py +38 -0
- kirin/dialects/ilist/rewrite/unroll.py +131 -0
- kirin/dialects/ilist/runtime.py +63 -0
- kirin/dialects/ilist/stmts.py +102 -0
- kirin/dialects/ilist/typeinfer.py +120 -0
- kirin/dialects/lowering/__init__.py +7 -0
- kirin/dialects/lowering/call.py +48 -0
- kirin/dialects/lowering/cf.py +206 -0
- kirin/dialects/lowering/func.py +134 -0
- kirin/dialects/math/__init__.py +41 -0
- kirin/dialects/math/_gen.py +176 -0
- kirin/dialects/math/dialect.py +3 -0
- kirin/dialects/math/interp.py +190 -0
- kirin/dialects/math/stmts.py +369 -0
- kirin/dialects/module.py +139 -0
- kirin/dialects/py/__init__.py +40 -0
- kirin/dialects/py/assertion.py +91 -0
- kirin/dialects/py/assign.py +103 -0
- kirin/dialects/py/attr.py +59 -0
- kirin/dialects/py/base.py +34 -0
- kirin/dialects/py/binop/__init__.py +23 -0
- kirin/dialects/py/binop/_dialect.py +3 -0
- kirin/dialects/py/binop/interp.py +60 -0
- kirin/dialects/py/binop/julia.py +33 -0
- kirin/dialects/py/binop/lowering.py +22 -0
- kirin/dialects/py/binop/stmts.py +79 -0
- kirin/dialects/py/binop/typeinfer.py +108 -0
- kirin/dialects/py/boolop.py +84 -0
- kirin/dialects/py/builtin.py +78 -0
- kirin/dialects/py/cmp/__init__.py +16 -0
- kirin/dialects/py/cmp/_dialect.py +3 -0
- kirin/dialects/py/cmp/interp.py +48 -0
- kirin/dialects/py/cmp/julia.py +33 -0
- kirin/dialects/py/cmp/lowering.py +45 -0
- kirin/dialects/py/cmp/stmts.py +62 -0
- kirin/dialects/py/constant.py +79 -0
- kirin/dialects/py/indexing.py +251 -0
- kirin/dialects/py/iterable.py +90 -0
- kirin/dialects/py/len.py +57 -0
- kirin/dialects/py/list/__init__.py +15 -0
- kirin/dialects/py/list/_dialect.py +3 -0
- kirin/dialects/py/list/interp.py +21 -0
- kirin/dialects/py/list/lowering.py +25 -0
- kirin/dialects/py/list/stmts.py +22 -0
- kirin/dialects/py/list/typeinfer.py +54 -0
- kirin/dialects/py/range.py +76 -0
- kirin/dialects/py/slice.py +120 -0
- kirin/dialects/py/tuple.py +109 -0
- kirin/dialects/py/unary/__init__.py +24 -0
- kirin/dialects/py/unary/_dialect.py +3 -0
- kirin/dialects/py/unary/constprop.py +20 -0
- kirin/dialects/py/unary/interp.py +24 -0
- kirin/dialects/py/unary/julia.py +21 -0
- kirin/dialects/py/unary/lowering.py +22 -0
- kirin/dialects/py/unary/stmts.py +33 -0
- kirin/dialects/py/unary/typeinfer.py +23 -0
- kirin/dialects/py/unpack.py +90 -0
- kirin/dialects/scf/__init__.py +23 -0
- kirin/dialects/scf/_dialect.py +3 -0
- kirin/dialects/scf/absint.py +64 -0
- kirin/dialects/scf/constprop.py +140 -0
- kirin/dialects/scf/interp.py +35 -0
- kirin/dialects/scf/lowering.py +123 -0
- kirin/dialects/scf/stmts.py +250 -0
- kirin/dialects/scf/trim.py +36 -0
- kirin/dialects/scf/typeinfer.py +58 -0
- kirin/dialects/scf/unroll.py +92 -0
- kirin/emit/__init__.py +3 -0
- kirin/emit/abc.py +89 -0
- kirin/emit/abc.pyi +38 -0
- kirin/emit/exceptions.py +5 -0
- kirin/emit/julia.py +63 -0
- kirin/emit/str.py +51 -0
- kirin/exceptions.py +59 -0
- kirin/graph.py +34 -0
- kirin/idtable.py +57 -0
- kirin/interp/__init__.py +39 -0
- kirin/interp/abstract.py +253 -0
- kirin/interp/base.py +438 -0
- kirin/interp/concrete.py +62 -0
- kirin/interp/exceptions.py +26 -0
- kirin/interp/frame.py +151 -0
- kirin/interp/impl.py +197 -0
- kirin/interp/result.py +93 -0
- kirin/interp/state.py +71 -0
- kirin/interp/table.py +40 -0
- kirin/interp/value.py +73 -0
- kirin/ir/__init__.py +46 -0
- kirin/ir/attrs/__init__.py +20 -0
- kirin/ir/attrs/_types.py +8 -0
- kirin/ir/attrs/_types.pyi +13 -0
- kirin/ir/attrs/abc.py +46 -0
- kirin/ir/attrs/py.py +45 -0
- kirin/ir/attrs/types.py +522 -0
- kirin/ir/dialect.py +125 -0
- kirin/ir/group.py +249 -0
- kirin/ir/method.py +118 -0
- kirin/ir/nodes/__init__.py +7 -0
- kirin/ir/nodes/base.py +149 -0
- kirin/ir/nodes/block.py +458 -0
- kirin/ir/nodes/region.py +337 -0
- kirin/ir/nodes/stmt.py +713 -0
- kirin/ir/nodes/view.py +142 -0
- kirin/ir/ssa.py +204 -0
- kirin/ir/traits/__init__.py +36 -0
- kirin/ir/traits/abc.py +42 -0
- kirin/ir/traits/basic.py +78 -0
- kirin/ir/traits/callable.py +51 -0
- kirin/ir/traits/lowering/__init__.py +2 -0
- kirin/ir/traits/lowering/call.py +37 -0
- kirin/ir/traits/lowering/context.py +120 -0
- kirin/ir/traits/region/__init__.py +2 -0
- kirin/ir/traits/region/ssacfg.py +22 -0
- kirin/ir/traits/symbol.py +57 -0
- kirin/ir/use.py +17 -0
- kirin/lattice/__init__.py +13 -0
- kirin/lattice/abc.py +128 -0
- kirin/lattice/empty.py +25 -0
- kirin/lattice/mixin.py +51 -0
- kirin/lowering/__init__.py +7 -0
- kirin/lowering/binding.py +65 -0
- kirin/lowering/core.py +72 -0
- kirin/lowering/dialect.py +35 -0
- kirin/lowering/dialect.pyi +183 -0
- kirin/lowering/frame.py +171 -0
- kirin/lowering/result.py +68 -0
- kirin/lowering/state.py +441 -0
- kirin/lowering/stream.py +53 -0
- kirin/passes/__init__.py +3 -0
- kirin/passes/abc.py +44 -0
- kirin/passes/aggressive/__init__.py +1 -0
- kirin/passes/aggressive/fold.py +43 -0
- kirin/passes/fold.py +45 -0
- kirin/passes/inline.py +25 -0
- kirin/passes/typeinfer.py +25 -0
- kirin/prelude.py +197 -0
- kirin/print/__init__.py +15 -0
- kirin/print/printable.py +141 -0
- kirin/print/printer.py +415 -0
- kirin/py.typed +0 -0
- kirin/registry.py +105 -0
- kirin/registry.pyi +52 -0
- kirin/rewrite/__init__.py +14 -0
- kirin/rewrite/abc.py +43 -0
- kirin/rewrite/aggressive/__init__.py +1 -0
- kirin/rewrite/aggressive/fold.py +43 -0
- kirin/rewrite/alias.py +16 -0
- kirin/rewrite/apply_type.py +47 -0
- kirin/rewrite/call2invoke.py +34 -0
- kirin/rewrite/chain.py +39 -0
- kirin/rewrite/compactify.py +288 -0
- kirin/rewrite/cse.py +48 -0
- kirin/rewrite/dce.py +19 -0
- kirin/rewrite/fixpoint.py +34 -0
- kirin/rewrite/fold.py +57 -0
- kirin/rewrite/getfield.py +21 -0
- kirin/rewrite/getitem.py +37 -0
- kirin/rewrite/inline.py +143 -0
- kirin/rewrite/result.py +15 -0
- kirin/rewrite/walk.py +83 -0
- kirin/rewrite/wrap_const.py +55 -0
- kirin/source.py +21 -0
- kirin/symbol_table.py +27 -0
- kirin/types.py +34 -0
- kirin/worklist.py +30 -0
- kirin_toolchain-0.13.0.dist-info/METADATA +42 -0
- kirin_toolchain-0.13.0.dist-info/RECORD +225 -0
- kirin_toolchain-0.13.0.dist-info/WHEEL +4 -0
- kirin_toolchain-0.13.0.dist-info/licenses/LICENSE +234 -0
kirin/interp/impl.py
ADDED
@@ -0,0 +1,197 @@
|
|
1
|
+
from typing import (
|
2
|
+
TYPE_CHECKING,
|
3
|
+
Any,
|
4
|
+
Type,
|
5
|
+
Union,
|
6
|
+
Generic,
|
7
|
+
TypeVar,
|
8
|
+
Callable,
|
9
|
+
TypeAlias,
|
10
|
+
overload,
|
11
|
+
)
|
12
|
+
from dataclasses import dataclass
|
13
|
+
|
14
|
+
from kirin import types
|
15
|
+
from kirin.ir import Attribute, Statement
|
16
|
+
from kirin.interp.value import StatementResult
|
17
|
+
|
18
|
+
if TYPE_CHECKING:
|
19
|
+
from kirin.interp.base import FrameABC, BaseInterpreter
|
20
|
+
from kirin.interp.table import MethodTable
|
21
|
+
|
22
|
+
MethodTableSelf = TypeVar("MethodTableSelf", bound="MethodTable")
|
23
|
+
InterpreterType = TypeVar("InterpreterType", bound="BaseInterpreter")
|
24
|
+
FrameType = TypeVar("FrameType", bound="FrameABC")
|
25
|
+
StatementType = TypeVar("StatementType", bound=Statement)
|
26
|
+
AttributeType = TypeVar("AttributeType", bound=Attribute)
|
27
|
+
MethodFunction: TypeAlias = Callable[
|
28
|
+
[MethodTableSelf, InterpreterType, FrameType, StatementType], StatementResult
|
29
|
+
]
|
30
|
+
AttributeFunction: TypeAlias = Callable[
|
31
|
+
[MethodTableSelf, InterpreterType, AttributeType], Any
|
32
|
+
]
|
33
|
+
|
34
|
+
|
35
|
+
@dataclass(frozen=True)
|
36
|
+
class Signature:
|
37
|
+
"""Signature of a statement."""
|
38
|
+
|
39
|
+
stmt: Type[Statement]
|
40
|
+
args: tuple[types.TypeAttribute, ...] | None = None
|
41
|
+
|
42
|
+
def __repr__(self):
|
43
|
+
if self.args:
|
44
|
+
return f"{self.stmt.__name__}[{', '.join(map(repr, self.args))}]"
|
45
|
+
else:
|
46
|
+
return f"{self.stmt.__name__}[...]"
|
47
|
+
|
48
|
+
|
49
|
+
SigType = TypeVar("SigType")
|
50
|
+
ImplType = TypeVar("ImplType")
|
51
|
+
|
52
|
+
|
53
|
+
@dataclass
|
54
|
+
class Def(Generic[SigType, ImplType]):
|
55
|
+
"""Base class of an interpreter implementation definition."""
|
56
|
+
|
57
|
+
signature: SigType
|
58
|
+
impl: ImplType
|
59
|
+
|
60
|
+
|
61
|
+
@dataclass
|
62
|
+
class ImplDef(Def[tuple[Signature, ...], "MethodFunction"]):
|
63
|
+
"""Definition of an interpreter implementation for a statement."""
|
64
|
+
|
65
|
+
parent: Type[Statement]
|
66
|
+
|
67
|
+
def __repr__(self):
|
68
|
+
if self.parent.dialect:
|
69
|
+
return f"interp {self.parent.dialect.name}.{self.parent.name}"
|
70
|
+
else:
|
71
|
+
return f"interp {self.parent.name}"
|
72
|
+
|
73
|
+
def __call__(self, *args, **kwargs):
|
74
|
+
return self.impl(*args, **kwargs)
|
75
|
+
|
76
|
+
|
77
|
+
@dataclass
|
78
|
+
class AttributeImplDef(Def[type[Attribute], "AttributeFunction"]):
|
79
|
+
"""Definition of an interpreter implementation for an attribute."""
|
80
|
+
|
81
|
+
def __repr__(self):
|
82
|
+
if self.signature.dialect:
|
83
|
+
return f"attribute impl {self.signature.dialect.name}.{self.signature.name}"
|
84
|
+
else:
|
85
|
+
return f"attribute impl {self.signature.name}"
|
86
|
+
|
87
|
+
|
88
|
+
StatementType = TypeVar("StatementType", bound=Statement)
|
89
|
+
HeadType = TypeVar("HeadType")
|
90
|
+
|
91
|
+
|
92
|
+
class impl(Generic[HeadType]):
|
93
|
+
"""Decorator to define an interpreter implementation for a statement or attribute.
|
94
|
+
|
95
|
+
!!! note
|
96
|
+
While the `impl` decorator accepts both statements and attributes, and optionally
|
97
|
+
statements with its type signature, unlike a programming language, the actual
|
98
|
+
dispatch behavior given an instance of a statement or attribute is defined by the
|
99
|
+
implementation of the interpreter
|
100
|
+
(via [`lookup_registry`][kirin.interp.base.BaseInterpreter.lookup_registry]).
|
101
|
+
|
102
|
+
# Example
|
103
|
+
|
104
|
+
```python
|
105
|
+
@dialect.register
|
106
|
+
class MyMethods(interp.MethodTable):
|
107
|
+
@impl(Add)
|
108
|
+
def interp_add(
|
109
|
+
self,
|
110
|
+
interp: Interpreter,
|
111
|
+
frame: Frame,
|
112
|
+
stmt: Add,
|
113
|
+
) -> StatementResult:
|
114
|
+
...
|
115
|
+
```
|
116
|
+
"""
|
117
|
+
|
118
|
+
# TODO: validate only concrete types are allowed here
|
119
|
+
|
120
|
+
def __init__(
|
121
|
+
self, stmt_or_attribute: Type[HeadType], *args: types.TypeAttribute
|
122
|
+
) -> None:
|
123
|
+
if args and issubclass(stmt_or_attribute, Attribute):
|
124
|
+
raise ValueError("Attributes do not take arguments")
|
125
|
+
self.stmt_or_attribute: type[HeadType] = stmt_or_attribute
|
126
|
+
self.args = args
|
127
|
+
|
128
|
+
@overload
|
129
|
+
def __call__(
|
130
|
+
self,
|
131
|
+
func: Union[
|
132
|
+
Callable[
|
133
|
+
[MethodTableSelf, InterpreterType, FrameType, StatementType],
|
134
|
+
StatementResult,
|
135
|
+
],
|
136
|
+
ImplDef,
|
137
|
+
],
|
138
|
+
) -> ImplDef: ...
|
139
|
+
|
140
|
+
@overload
|
141
|
+
def __call__(
|
142
|
+
self,
|
143
|
+
func: Union[
|
144
|
+
Callable[
|
145
|
+
[MethodTableSelf, InterpreterType, AttributeType],
|
146
|
+
Any,
|
147
|
+
],
|
148
|
+
AttributeImplDef,
|
149
|
+
],
|
150
|
+
) -> AttributeImplDef: ...
|
151
|
+
|
152
|
+
def __call__(
|
153
|
+
self,
|
154
|
+
func: Union[
|
155
|
+
Callable[
|
156
|
+
[MethodTableSelf, InterpreterType, FrameType, StatementType],
|
157
|
+
StatementResult,
|
158
|
+
],
|
159
|
+
Callable[
|
160
|
+
[MethodTableSelf, InterpreterType, AttributeType],
|
161
|
+
Any,
|
162
|
+
],
|
163
|
+
ImplDef,
|
164
|
+
AttributeImplDef,
|
165
|
+
],
|
166
|
+
) -> Def:
|
167
|
+
if issubclass(self.stmt_or_attribute, Statement):
|
168
|
+
return self._impl_statement(self.stmt_or_attribute, func)
|
169
|
+
elif issubclass(self.stmt_or_attribute, Attribute):
|
170
|
+
return self._impl_attribute(self.stmt_or_attribute, func)
|
171
|
+
else:
|
172
|
+
raise ValueError(f"Invalid statement type {self.stmt_or_attribute}")
|
173
|
+
|
174
|
+
def _impl_attribute(
|
175
|
+
self,
|
176
|
+
attr: Type[Attribute],
|
177
|
+
func: Union[Callable, Def],
|
178
|
+
) -> AttributeImplDef:
|
179
|
+
if isinstance(func, Def):
|
180
|
+
return AttributeImplDef(attr, func.impl)
|
181
|
+
else:
|
182
|
+
return AttributeImplDef(attr, func)
|
183
|
+
|
184
|
+
def _impl_statement(
|
185
|
+
self,
|
186
|
+
stmt: Type[Statement],
|
187
|
+
func: Union[Callable, Def],
|
188
|
+
) -> ImplDef:
|
189
|
+
if self.args:
|
190
|
+
sig = Signature(stmt, self.args)
|
191
|
+
else:
|
192
|
+
sig = Signature(stmt)
|
193
|
+
|
194
|
+
if isinstance(func, Def):
|
195
|
+
return ImplDef(func.signature + (sig,), func.impl, stmt)
|
196
|
+
else:
|
197
|
+
return ImplDef((sig,), func, stmt)
|
kirin/interp/result.py
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
from typing import Generic, TypeVar
|
2
|
+
from dataclasses import dataclass
|
3
|
+
|
4
|
+
from kirin.ir.traits import SymbolOpInterface, CallableStmtInterface
|
5
|
+
|
6
|
+
from .frame import FrameABC
|
7
|
+
from .exceptions import WrapException
|
8
|
+
|
9
|
+
ValueType = TypeVar("ValueType")
|
10
|
+
FrameType = TypeVar("FrameType", bound=FrameABC)
|
11
|
+
|
12
|
+
|
13
|
+
@dataclass
|
14
|
+
class Result(Generic[ValueType]):
|
15
|
+
"""Result type for the interpreter.
|
16
|
+
|
17
|
+
This is a generic result type that represents the result of interpretation.
|
18
|
+
The result can be either an `Ok` value or an `Err` value. The `Ok` value
|
19
|
+
represents a successful interpretation result, while the `Err` value
|
20
|
+
represents an error during interpretation with a stack trace. One can use
|
21
|
+
the `expect` method to extract the value from the result, which will raise
|
22
|
+
an exception and print the stack trace if the result is an `Err`.
|
23
|
+
"""
|
24
|
+
|
25
|
+
def expect(self) -> ValueType:
|
26
|
+
raise NotImplementedError("unreachable")
|
27
|
+
|
28
|
+
|
29
|
+
@dataclass
|
30
|
+
class Err(Result[ValueType], Generic[FrameType, ValueType]):
|
31
|
+
exception: Exception
|
32
|
+
frames: list[FrameType]
|
33
|
+
|
34
|
+
def __init__(self, exception: Exception, frames: list[FrameType]):
|
35
|
+
super().__init__()
|
36
|
+
self.exception = exception
|
37
|
+
self.frames = frames
|
38
|
+
|
39
|
+
def __repr__(self) -> str:
|
40
|
+
return f"Err({self.exception.__class__.__name__}: {self.exception})"
|
41
|
+
|
42
|
+
def print_stack(self):
|
43
|
+
"""Print the stack trace of the error."""
|
44
|
+
top_method_code = self.frames[0].code
|
45
|
+
if (call_trait := top_method_code.get_trait(CallableStmtInterface)) is None:
|
46
|
+
raise ValueError(f"Method code {top_method_code} is not callable")
|
47
|
+
|
48
|
+
region = call_trait.get_callable_region(top_method_code)
|
49
|
+
name = (
|
50
|
+
top_method_code.get_trait(SymbolOpInterface)
|
51
|
+
.get_sym_name(top_method_code) # type: ignore
|
52
|
+
.data
|
53
|
+
)
|
54
|
+
args = ",".join(
|
55
|
+
[
|
56
|
+
(
|
57
|
+
f"{arg.name}"
|
58
|
+
if arg.type is arg.type.top()
|
59
|
+
else f"{arg.name}:{arg.type}"
|
60
|
+
)
|
61
|
+
for arg in region.blocks[0].args[1:]
|
62
|
+
]
|
63
|
+
)
|
64
|
+
print("Traceback (most recent call last):")
|
65
|
+
print(f" {name}({args})")
|
66
|
+
for frame in reversed(self.frames):
|
67
|
+
if frame.code:
|
68
|
+
frame.code.print()
|
69
|
+
print(f"{self.exception.__class__.__name__}: {self.exception}")
|
70
|
+
print(
|
71
|
+
"================================ Python Stacktrace ================================"
|
72
|
+
)
|
73
|
+
|
74
|
+
def expect(self) -> ValueType:
|
75
|
+
self.print_stack()
|
76
|
+
if isinstance(self.exception, WrapException):
|
77
|
+
raise self.exception.exception from self.exception
|
78
|
+
else:
|
79
|
+
raise self.exception from None
|
80
|
+
|
81
|
+
|
82
|
+
@dataclass
|
83
|
+
class Ok(Result[ValueType]):
|
84
|
+
value: ValueType
|
85
|
+
|
86
|
+
def __len__(self) -> int:
|
87
|
+
return 1
|
88
|
+
|
89
|
+
def __repr__(self) -> str:
|
90
|
+
return f"Ok({self.value})"
|
91
|
+
|
92
|
+
def expect(self) -> ValueType:
|
93
|
+
return self.value
|
kirin/interp/state.py
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
from typing import Generic, TypeVar
|
2
|
+
from contextlib import contextmanager
|
3
|
+
from dataclasses import field, dataclass
|
4
|
+
|
5
|
+
from kirin.interp.frame import FrameABC
|
6
|
+
|
7
|
+
FrameType = TypeVar("FrameType", bound=FrameABC)
|
8
|
+
|
9
|
+
|
10
|
+
@dataclass
|
11
|
+
class InterpreterState(Generic[FrameType]):
|
12
|
+
"""Interpreter state.
|
13
|
+
|
14
|
+
This class represents the state of the interpreter. It contains the
|
15
|
+
stack of frames for the interpreter. The stack of frames is used to
|
16
|
+
store the current state of the interpreter during interpretation.
|
17
|
+
"""
|
18
|
+
|
19
|
+
frames: list[FrameType] = field(default_factory=list)
|
20
|
+
|
21
|
+
def push_frame(self, frame: FrameType):
|
22
|
+
"""Push a frame onto the stack.
|
23
|
+
|
24
|
+
Args:
|
25
|
+
frame(FrameType): The frame to push onto the stack.
|
26
|
+
|
27
|
+
Returns:
|
28
|
+
FrameType: The frame that was pushed.
|
29
|
+
"""
|
30
|
+
self.frames.append(frame)
|
31
|
+
return frame
|
32
|
+
|
33
|
+
def pop_frame(self) -> FrameType:
|
34
|
+
"""Pop a frame from the stack.
|
35
|
+
|
36
|
+
Returns:
|
37
|
+
FrameType: The frame that was popped.
|
38
|
+
"""
|
39
|
+
return self.frames.pop()
|
40
|
+
|
41
|
+
@contextmanager
|
42
|
+
def new_frame(self, frame: FrameType):
|
43
|
+
"""Context manager to push and pop a frame.
|
44
|
+
|
45
|
+
This context manager is used to push a frame onto the stack before
|
46
|
+
executing a block of code and pop the frame from the stack after
|
47
|
+
executing the block of code.
|
48
|
+
|
49
|
+
Args:
|
50
|
+
frame(FrameType): The frame to push onto the stack.
|
51
|
+
|
52
|
+
Yields:
|
53
|
+
FrameType: The frame that was pushed.
|
54
|
+
"""
|
55
|
+
self.push_frame(frame)
|
56
|
+
try:
|
57
|
+
yield frame
|
58
|
+
finally:
|
59
|
+
self.pop_frame()
|
60
|
+
|
61
|
+
def current_frame(self) -> FrameType:
|
62
|
+
"""Get the current frame.
|
63
|
+
|
64
|
+
Returns:
|
65
|
+
FrameType: The current frame.
|
66
|
+
"""
|
67
|
+
if not self.frames:
|
68
|
+
raise ValueError(
|
69
|
+
"unable to retrieve the current frame because no frames were pushed"
|
70
|
+
)
|
71
|
+
return self.frames[-1]
|
kirin/interp/table.py
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
import inspect
|
2
|
+
from abc import ABC
|
3
|
+
from typing import TYPE_CHECKING, TypeVar, ClassVar
|
4
|
+
from dataclasses import dataclass
|
5
|
+
|
6
|
+
from kirin.interp.base import BaseInterpreter
|
7
|
+
from kirin.interp.impl import ImplDef, AttributeImplDef
|
8
|
+
|
9
|
+
if TYPE_CHECKING:
|
10
|
+
from kirin.ir import Attribute
|
11
|
+
from kirin.interp.base import BaseInterpreter
|
12
|
+
from kirin.interp.impl import Signature, MethodFunction, AttributeFunction
|
13
|
+
|
14
|
+
|
15
|
+
InterpreterType = TypeVar("InterpreterType", bound="BaseInterpreter")
|
16
|
+
ValueType = TypeVar("ValueType")
|
17
|
+
|
18
|
+
|
19
|
+
@dataclass
|
20
|
+
class MethodTable(ABC):
|
21
|
+
"""Base class to define lookup tables for interpreting code for IR nodes in a dialect."""
|
22
|
+
|
23
|
+
table: ClassVar[dict["Signature", "MethodFunction"]]
|
24
|
+
"""Lookup table for interpreting code for IR nodes in a dialect."""
|
25
|
+
attribute: ClassVar[dict[type["Attribute"], "AttributeFunction"]]
|
26
|
+
"""Lookup table for interpreting code for IR attributes in a dialect."""
|
27
|
+
|
28
|
+
def __init_subclass__(cls) -> None:
|
29
|
+
# init the subclass first
|
30
|
+
super().__init_subclass__()
|
31
|
+
cls.table = {}
|
32
|
+
for _, value in inspect.getmembers(cls):
|
33
|
+
if isinstance(value, ImplDef):
|
34
|
+
for sig in value.signature:
|
35
|
+
cls.table[sig] = value.impl
|
36
|
+
|
37
|
+
cls.attribute = {}
|
38
|
+
for _, value in inspect.getmembers(cls):
|
39
|
+
if isinstance(value, AttributeImplDef):
|
40
|
+
cls.attribute[value.signature] = value.impl
|
kirin/interp/value.py
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
from typing import Tuple, Generic, TypeVar, TypeAlias, final
|
2
|
+
from dataclasses import dataclass
|
3
|
+
|
4
|
+
from kirin.ir import Block
|
5
|
+
|
6
|
+
ValueType = TypeVar("ValueType")
|
7
|
+
|
8
|
+
|
9
|
+
@final
|
10
|
+
@dataclass
|
11
|
+
class ReturnValue(Generic[ValueType]):
|
12
|
+
"""Return value from a statement evaluation.
|
13
|
+
|
14
|
+
This class represents a return value from a statement evaluation. It is used
|
15
|
+
to indicate that the statement evaluation should later pop the frame and
|
16
|
+
return the value. Kirin does not allow multiple return values to follow Python
|
17
|
+
semantics. If you want to return multiple values, you should return a tuple.
|
18
|
+
"""
|
19
|
+
|
20
|
+
value: ValueType
|
21
|
+
|
22
|
+
def __len__(self) -> int:
|
23
|
+
return 0
|
24
|
+
|
25
|
+
|
26
|
+
@final
|
27
|
+
@dataclass
|
28
|
+
class YieldValue(Generic[ValueType]):
|
29
|
+
"""Yield value from a statement evaluation.
|
30
|
+
|
31
|
+
This class represents values returned from a statement that terminates current
|
32
|
+
region execution and returns the values to the caller. Unlike `ReturnValue`, this
|
33
|
+
class won't pop the frame and return the value to the caller.
|
34
|
+
"""
|
35
|
+
|
36
|
+
values: tuple[ValueType, ...]
|
37
|
+
|
38
|
+
def __len__(self) -> int:
|
39
|
+
return len(self.values)
|
40
|
+
|
41
|
+
def __iter__(self):
|
42
|
+
return iter(self.values)
|
43
|
+
|
44
|
+
def __getitem__(self, index: int) -> ValueType:
|
45
|
+
return self.values[index]
|
46
|
+
|
47
|
+
|
48
|
+
@final
|
49
|
+
@dataclass(init=False)
|
50
|
+
class Successor(Generic[ValueType]):
|
51
|
+
"""Successor block from a statement evaluation."""
|
52
|
+
|
53
|
+
block: Block
|
54
|
+
block_args: Tuple[ValueType, ...]
|
55
|
+
|
56
|
+
def __init__(self, block: Block, *block_args: ValueType):
|
57
|
+
super().__init__()
|
58
|
+
self.block = block
|
59
|
+
self.block_args = block_args
|
60
|
+
|
61
|
+
def __hash__(self) -> int:
|
62
|
+
return hash(self.block)
|
63
|
+
|
64
|
+
def __len__(self) -> int:
|
65
|
+
return 0
|
66
|
+
|
67
|
+
|
68
|
+
SpecialValue: TypeAlias = (
|
69
|
+
None | ReturnValue[ValueType] | YieldValue[ValueType] | Successor[ValueType]
|
70
|
+
)
|
71
|
+
"""Special value for statement evaluation."""
|
72
|
+
StatementResult: TypeAlias = tuple[ValueType, ...] | SpecialValue[ValueType]
|
73
|
+
"""Type alias for the result of a statement evaluation."""
|
kirin/ir/__init__.py
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
"""IR module for kirin.
|
2
|
+
|
3
|
+
This module contains the data structure definition
|
4
|
+
of the intermediate representation (IR) for kirin.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from kirin.ir import attrs as attrs, traits as traits
|
8
|
+
from kirin.ir.ssa import (
|
9
|
+
SSAValue as SSAValue,
|
10
|
+
TestValue as TestValue,
|
11
|
+
ResultValue as ResultValue,
|
12
|
+
BlockArgument as BlockArgument,
|
13
|
+
DeletedSSAValue as DeletedSSAValue,
|
14
|
+
)
|
15
|
+
from kirin.ir.use import Use as Use
|
16
|
+
from kirin.ir.group import DialectGroup as DialectGroup, dialect_group as dialect_group
|
17
|
+
from kirin.ir.nodes import (
|
18
|
+
Block as Block,
|
19
|
+
IRNode as IRNode,
|
20
|
+
Region as Region,
|
21
|
+
Statement as Statement,
|
22
|
+
)
|
23
|
+
from kirin.ir.method import Method as Method
|
24
|
+
from kirin.ir.traits import (
|
25
|
+
Pure as Pure,
|
26
|
+
HasParent as HasParent,
|
27
|
+
MaybePure as MaybePure,
|
28
|
+
StmtTrait as StmtTrait,
|
29
|
+
RegionTrait as RegionTrait,
|
30
|
+
SymbolTable as SymbolTable,
|
31
|
+
ConstantLike as ConstantLike,
|
32
|
+
HasSignature as HasSignature,
|
33
|
+
IsTerminator as IsTerminator,
|
34
|
+
NoTerminator as NoTerminator,
|
35
|
+
SSACFGRegion as SSACFGRegion,
|
36
|
+
FromPythonCall as FromPythonCall,
|
37
|
+
FromPythonWith as FromPythonWith,
|
38
|
+
IsolatedFromAbove as IsolatedFromAbove,
|
39
|
+
SymbolOpInterface as SymbolOpInterface,
|
40
|
+
PythonLoweringTrait as PythonLoweringTrait,
|
41
|
+
CallableStmtInterface as CallableStmtInterface,
|
42
|
+
FromPythonWithSingleItem as FromPythonWithSingleItem,
|
43
|
+
)
|
44
|
+
from kirin.ir.dialect import Dialect as Dialect
|
45
|
+
from kirin.ir.attrs.py import PyAttr as PyAttr
|
46
|
+
from kirin.ir.attrs.abc import Attribute as Attribute, AttributeMeta as AttributeMeta
|
@@ -0,0 +1,20 @@
|
|
1
|
+
"""Compile-time values in Kirin IR.
|
2
|
+
|
3
|
+
This module contains the following:
|
4
|
+
|
5
|
+
## `abc` module
|
6
|
+
`abc.AttributeMeta`: The metaclass for all attributes.
|
7
|
+
`abc.Attribute`: The base class for all attributes.
|
8
|
+
|
9
|
+
## `types` module
|
10
|
+
`types.TypeAttribute`: The base class for all type attributes.
|
11
|
+
`types.PyClass`: A type attribute representing a Python class.
|
12
|
+
`types.TypeVar`: A type attribute representing a type variable.
|
13
|
+
`types.Literal`: A type attribute representing a literal type.
|
14
|
+
`types.Generic`: A type attribute representing a generic type.
|
15
|
+
`types.Union`: A type attribute representing a union type.
|
16
|
+
|
17
|
+
## `py` module
|
18
|
+
|
19
|
+
`py.PyAttr`: An attribute representing a Python value.
|
20
|
+
"""
|
kirin/ir/attrs/_types.py
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
from dataclasses import dataclass
|
2
|
+
|
3
|
+
from .abc import Attribute
|
4
|
+
from .types import Union, Generic, Literal, PyClass, TypeVar, TypeAttribute
|
5
|
+
|
6
|
+
@dataclass
|
7
|
+
class _TypeAttribute(Attribute):
|
8
|
+
def is_subseteq_Union(self, other: Union) -> bool: ...
|
9
|
+
def is_subseteq_Literal(self, other: Literal) -> bool: ...
|
10
|
+
def is_subseteq_TypeVar(self, other: TypeVar) -> bool: ...
|
11
|
+
def is_subseteq_PyClass(self, other: PyClass) -> bool: ...
|
12
|
+
def is_subseteq_Generic(self, other: Generic) -> bool: ...
|
13
|
+
def is_subseteq_fallback(self, other: TypeAttribute) -> bool: ...
|
kirin/ir/attrs/abc.py
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
from abc import ABC, ABCMeta, abstractmethod
|
2
|
+
from typing import TYPE_CHECKING, ClassVar, Optional
|
3
|
+
from dataclasses import field, dataclass
|
4
|
+
|
5
|
+
from kirin.print import Printable
|
6
|
+
from kirin.lattice.abc import LatticeMeta, SingletonMeta
|
7
|
+
|
8
|
+
if TYPE_CHECKING:
|
9
|
+
from kirin.ir.dialect import Dialect
|
10
|
+
|
11
|
+
|
12
|
+
class AttributeMeta(ABCMeta):
|
13
|
+
"""Metaclass for attributes."""
|
14
|
+
|
15
|
+
pass
|
16
|
+
|
17
|
+
|
18
|
+
class LatticeAttributeMeta(LatticeMeta, AttributeMeta):
|
19
|
+
"""Metaclass for lattice attributes."""
|
20
|
+
|
21
|
+
pass
|
22
|
+
|
23
|
+
|
24
|
+
class SingletonLatticeAttributeMeta(LatticeAttributeMeta, SingletonMeta):
|
25
|
+
"""Metaclass for singleton lattice attributes."""
|
26
|
+
|
27
|
+
pass
|
28
|
+
|
29
|
+
|
30
|
+
@dataclass(eq=False)
|
31
|
+
class Attribute(ABC, Printable, metaclass=AttributeMeta):
|
32
|
+
"""ABC for compile-time values. All attributes are hashable
|
33
|
+
and thus need to implement the `__hash__` method.
|
34
|
+
|
35
|
+
!!! note "Pretty Printing"
|
36
|
+
This object is pretty printable via
|
37
|
+
[`.print()`][kirin.print.printable.Printable.print] method.
|
38
|
+
"""
|
39
|
+
|
40
|
+
dialect: ClassVar[Optional["Dialect"]] = field(default=None, init=False, repr=False)
|
41
|
+
"""Dialect of the attribute. (default: None)"""
|
42
|
+
name: ClassVar[str] = field(init=False, repr=False)
|
43
|
+
"""Name of the attribute in printing and other text format."""
|
44
|
+
|
45
|
+
@abstractmethod
|
46
|
+
def __hash__(self) -> int: ...
|
kirin/ir/attrs/py.py
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
from typing import Generic, TypeVar
|
2
|
+
from dataclasses import dataclass
|
3
|
+
|
4
|
+
from kirin.print import Printer
|
5
|
+
|
6
|
+
from .abc import Attribute
|
7
|
+
from .types import PyClass, TypeAttribute
|
8
|
+
|
9
|
+
T = TypeVar("T")
|
10
|
+
|
11
|
+
|
12
|
+
@dataclass
|
13
|
+
class PyAttr(Generic[T], Attribute):
|
14
|
+
"""Python attribute for compile-time values.
|
15
|
+
This is a generic attribute that holds a Python value.
|
16
|
+
|
17
|
+
The constructor takes a Python value and an optional type attribute.
|
18
|
+
If the type attribute is not provided, the type of the value is inferred
|
19
|
+
as `PyClass(type(value))`.
|
20
|
+
|
21
|
+
!!! note "Pretty Printing"
|
22
|
+
This object is pretty printable via
|
23
|
+
[`.print()`][kirin.print.printable.Printable.print] method.
|
24
|
+
"""
|
25
|
+
|
26
|
+
name = "PyAttr"
|
27
|
+
data: T
|
28
|
+
type: TypeAttribute
|
29
|
+
|
30
|
+
def __init__(self, data: T, pytype: TypeAttribute | None = None):
|
31
|
+
self.data = data
|
32
|
+
|
33
|
+
if pytype is None:
|
34
|
+
self.type = PyClass(type(data))
|
35
|
+
else:
|
36
|
+
self.type = pytype
|
37
|
+
|
38
|
+
def __hash__(self):
|
39
|
+
return hash(self.data) + hash(self.type)
|
40
|
+
|
41
|
+
def print_impl(self, printer: Printer) -> None:
|
42
|
+
printer.plain_print(repr(self.data))
|
43
|
+
with printer.rich(style="comment"):
|
44
|
+
printer.plain_print(" : ")
|
45
|
+
printer.print(self.type)
|