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.
Files changed (225) hide show
  1. kirin/__init__.py +7 -0
  2. kirin/analysis/__init__.py +24 -0
  3. kirin/analysis/callgraph.py +61 -0
  4. kirin/analysis/cfg.py +112 -0
  5. kirin/analysis/const/__init__.py +20 -0
  6. kirin/analysis/const/_visitor.py +2 -0
  7. kirin/analysis/const/_visitor.pyi +8 -0
  8. kirin/analysis/const/lattice.py +219 -0
  9. kirin/analysis/const/prop.py +116 -0
  10. kirin/analysis/forward.py +100 -0
  11. kirin/analysis/typeinfer/__init__.py +5 -0
  12. kirin/analysis/typeinfer/analysis.py +90 -0
  13. kirin/analysis/typeinfer/solve.py +141 -0
  14. kirin/decl/__init__.py +108 -0
  15. kirin/decl/base.py +65 -0
  16. kirin/decl/camel2snake.py +2 -0
  17. kirin/decl/emit/__init__.py +0 -0
  18. kirin/decl/emit/_create_fn.py +29 -0
  19. kirin/decl/emit/_set_new_attribute.py +22 -0
  20. kirin/decl/emit/dialect.py +8 -0
  21. kirin/decl/emit/init.py +277 -0
  22. kirin/decl/emit/name.py +10 -0
  23. kirin/decl/emit/property.py +182 -0
  24. kirin/decl/emit/repr.py +31 -0
  25. kirin/decl/emit/traits.py +13 -0
  26. kirin/decl/emit/typecheck.py +77 -0
  27. kirin/decl/emit/verify.py +51 -0
  28. kirin/decl/info.py +346 -0
  29. kirin/decl/scan_fields.py +157 -0
  30. kirin/decl/verify.py +69 -0
  31. kirin/dialects/__init__.py +14 -0
  32. kirin/dialects/_pprint_helper.py +53 -0
  33. kirin/dialects/cf/__init__.py +20 -0
  34. kirin/dialects/cf/constprop.py +51 -0
  35. kirin/dialects/cf/dialect.py +3 -0
  36. kirin/dialects/cf/emit.py +58 -0
  37. kirin/dialects/cf/interp.py +24 -0
  38. kirin/dialects/cf/stmts.py +68 -0
  39. kirin/dialects/cf/typeinfer.py +27 -0
  40. kirin/dialects/eltype.py +23 -0
  41. kirin/dialects/func/__init__.py +20 -0
  42. kirin/dialects/func/attrs.py +39 -0
  43. kirin/dialects/func/constprop.py +138 -0
  44. kirin/dialects/func/dialect.py +3 -0
  45. kirin/dialects/func/emit.py +80 -0
  46. kirin/dialects/func/interp.py +68 -0
  47. kirin/dialects/func/stmts.py +233 -0
  48. kirin/dialects/func/typeinfer.py +124 -0
  49. kirin/dialects/ilist/__init__.py +33 -0
  50. kirin/dialects/ilist/_dialect.py +3 -0
  51. kirin/dialects/ilist/_wrapper.py +51 -0
  52. kirin/dialects/ilist/interp.py +85 -0
  53. kirin/dialects/ilist/lowering.py +25 -0
  54. kirin/dialects/ilist/passes.py +32 -0
  55. kirin/dialects/ilist/rewrite/__init__.py +3 -0
  56. kirin/dialects/ilist/rewrite/const.py +45 -0
  57. kirin/dialects/ilist/rewrite/list.py +38 -0
  58. kirin/dialects/ilist/rewrite/unroll.py +131 -0
  59. kirin/dialects/ilist/runtime.py +63 -0
  60. kirin/dialects/ilist/stmts.py +102 -0
  61. kirin/dialects/ilist/typeinfer.py +120 -0
  62. kirin/dialects/lowering/__init__.py +7 -0
  63. kirin/dialects/lowering/call.py +48 -0
  64. kirin/dialects/lowering/cf.py +206 -0
  65. kirin/dialects/lowering/func.py +134 -0
  66. kirin/dialects/math/__init__.py +41 -0
  67. kirin/dialects/math/_gen.py +176 -0
  68. kirin/dialects/math/dialect.py +3 -0
  69. kirin/dialects/math/interp.py +190 -0
  70. kirin/dialects/math/stmts.py +369 -0
  71. kirin/dialects/module.py +139 -0
  72. kirin/dialects/py/__init__.py +40 -0
  73. kirin/dialects/py/assertion.py +91 -0
  74. kirin/dialects/py/assign.py +103 -0
  75. kirin/dialects/py/attr.py +59 -0
  76. kirin/dialects/py/base.py +34 -0
  77. kirin/dialects/py/binop/__init__.py +23 -0
  78. kirin/dialects/py/binop/_dialect.py +3 -0
  79. kirin/dialects/py/binop/interp.py +60 -0
  80. kirin/dialects/py/binop/julia.py +33 -0
  81. kirin/dialects/py/binop/lowering.py +22 -0
  82. kirin/dialects/py/binop/stmts.py +79 -0
  83. kirin/dialects/py/binop/typeinfer.py +108 -0
  84. kirin/dialects/py/boolop.py +84 -0
  85. kirin/dialects/py/builtin.py +78 -0
  86. kirin/dialects/py/cmp/__init__.py +16 -0
  87. kirin/dialects/py/cmp/_dialect.py +3 -0
  88. kirin/dialects/py/cmp/interp.py +48 -0
  89. kirin/dialects/py/cmp/julia.py +33 -0
  90. kirin/dialects/py/cmp/lowering.py +45 -0
  91. kirin/dialects/py/cmp/stmts.py +62 -0
  92. kirin/dialects/py/constant.py +79 -0
  93. kirin/dialects/py/indexing.py +251 -0
  94. kirin/dialects/py/iterable.py +90 -0
  95. kirin/dialects/py/len.py +57 -0
  96. kirin/dialects/py/list/__init__.py +15 -0
  97. kirin/dialects/py/list/_dialect.py +3 -0
  98. kirin/dialects/py/list/interp.py +21 -0
  99. kirin/dialects/py/list/lowering.py +25 -0
  100. kirin/dialects/py/list/stmts.py +22 -0
  101. kirin/dialects/py/list/typeinfer.py +54 -0
  102. kirin/dialects/py/range.py +76 -0
  103. kirin/dialects/py/slice.py +120 -0
  104. kirin/dialects/py/tuple.py +109 -0
  105. kirin/dialects/py/unary/__init__.py +24 -0
  106. kirin/dialects/py/unary/_dialect.py +3 -0
  107. kirin/dialects/py/unary/constprop.py +20 -0
  108. kirin/dialects/py/unary/interp.py +24 -0
  109. kirin/dialects/py/unary/julia.py +21 -0
  110. kirin/dialects/py/unary/lowering.py +22 -0
  111. kirin/dialects/py/unary/stmts.py +33 -0
  112. kirin/dialects/py/unary/typeinfer.py +23 -0
  113. kirin/dialects/py/unpack.py +90 -0
  114. kirin/dialects/scf/__init__.py +23 -0
  115. kirin/dialects/scf/_dialect.py +3 -0
  116. kirin/dialects/scf/absint.py +64 -0
  117. kirin/dialects/scf/constprop.py +140 -0
  118. kirin/dialects/scf/interp.py +35 -0
  119. kirin/dialects/scf/lowering.py +123 -0
  120. kirin/dialects/scf/stmts.py +250 -0
  121. kirin/dialects/scf/trim.py +36 -0
  122. kirin/dialects/scf/typeinfer.py +58 -0
  123. kirin/dialects/scf/unroll.py +92 -0
  124. kirin/emit/__init__.py +3 -0
  125. kirin/emit/abc.py +89 -0
  126. kirin/emit/abc.pyi +38 -0
  127. kirin/emit/exceptions.py +5 -0
  128. kirin/emit/julia.py +63 -0
  129. kirin/emit/str.py +51 -0
  130. kirin/exceptions.py +59 -0
  131. kirin/graph.py +34 -0
  132. kirin/idtable.py +57 -0
  133. kirin/interp/__init__.py +39 -0
  134. kirin/interp/abstract.py +253 -0
  135. kirin/interp/base.py +438 -0
  136. kirin/interp/concrete.py +62 -0
  137. kirin/interp/exceptions.py +26 -0
  138. kirin/interp/frame.py +151 -0
  139. kirin/interp/impl.py +197 -0
  140. kirin/interp/result.py +93 -0
  141. kirin/interp/state.py +71 -0
  142. kirin/interp/table.py +40 -0
  143. kirin/interp/value.py +73 -0
  144. kirin/ir/__init__.py +46 -0
  145. kirin/ir/attrs/__init__.py +20 -0
  146. kirin/ir/attrs/_types.py +8 -0
  147. kirin/ir/attrs/_types.pyi +13 -0
  148. kirin/ir/attrs/abc.py +46 -0
  149. kirin/ir/attrs/py.py +45 -0
  150. kirin/ir/attrs/types.py +522 -0
  151. kirin/ir/dialect.py +125 -0
  152. kirin/ir/group.py +249 -0
  153. kirin/ir/method.py +118 -0
  154. kirin/ir/nodes/__init__.py +7 -0
  155. kirin/ir/nodes/base.py +149 -0
  156. kirin/ir/nodes/block.py +458 -0
  157. kirin/ir/nodes/region.py +337 -0
  158. kirin/ir/nodes/stmt.py +713 -0
  159. kirin/ir/nodes/view.py +142 -0
  160. kirin/ir/ssa.py +204 -0
  161. kirin/ir/traits/__init__.py +36 -0
  162. kirin/ir/traits/abc.py +42 -0
  163. kirin/ir/traits/basic.py +78 -0
  164. kirin/ir/traits/callable.py +51 -0
  165. kirin/ir/traits/lowering/__init__.py +2 -0
  166. kirin/ir/traits/lowering/call.py +37 -0
  167. kirin/ir/traits/lowering/context.py +120 -0
  168. kirin/ir/traits/region/__init__.py +2 -0
  169. kirin/ir/traits/region/ssacfg.py +22 -0
  170. kirin/ir/traits/symbol.py +57 -0
  171. kirin/ir/use.py +17 -0
  172. kirin/lattice/__init__.py +13 -0
  173. kirin/lattice/abc.py +128 -0
  174. kirin/lattice/empty.py +25 -0
  175. kirin/lattice/mixin.py +51 -0
  176. kirin/lowering/__init__.py +7 -0
  177. kirin/lowering/binding.py +65 -0
  178. kirin/lowering/core.py +72 -0
  179. kirin/lowering/dialect.py +35 -0
  180. kirin/lowering/dialect.pyi +183 -0
  181. kirin/lowering/frame.py +171 -0
  182. kirin/lowering/result.py +68 -0
  183. kirin/lowering/state.py +441 -0
  184. kirin/lowering/stream.py +53 -0
  185. kirin/passes/__init__.py +3 -0
  186. kirin/passes/abc.py +44 -0
  187. kirin/passes/aggressive/__init__.py +1 -0
  188. kirin/passes/aggressive/fold.py +43 -0
  189. kirin/passes/fold.py +45 -0
  190. kirin/passes/inline.py +25 -0
  191. kirin/passes/typeinfer.py +25 -0
  192. kirin/prelude.py +197 -0
  193. kirin/print/__init__.py +15 -0
  194. kirin/print/printable.py +141 -0
  195. kirin/print/printer.py +415 -0
  196. kirin/py.typed +0 -0
  197. kirin/registry.py +105 -0
  198. kirin/registry.pyi +52 -0
  199. kirin/rewrite/__init__.py +14 -0
  200. kirin/rewrite/abc.py +43 -0
  201. kirin/rewrite/aggressive/__init__.py +1 -0
  202. kirin/rewrite/aggressive/fold.py +43 -0
  203. kirin/rewrite/alias.py +16 -0
  204. kirin/rewrite/apply_type.py +47 -0
  205. kirin/rewrite/call2invoke.py +34 -0
  206. kirin/rewrite/chain.py +39 -0
  207. kirin/rewrite/compactify.py +288 -0
  208. kirin/rewrite/cse.py +48 -0
  209. kirin/rewrite/dce.py +19 -0
  210. kirin/rewrite/fixpoint.py +34 -0
  211. kirin/rewrite/fold.py +57 -0
  212. kirin/rewrite/getfield.py +21 -0
  213. kirin/rewrite/getitem.py +37 -0
  214. kirin/rewrite/inline.py +143 -0
  215. kirin/rewrite/result.py +15 -0
  216. kirin/rewrite/walk.py +83 -0
  217. kirin/rewrite/wrap_const.py +55 -0
  218. kirin/source.py +21 -0
  219. kirin/symbol_table.py +27 -0
  220. kirin/types.py +34 -0
  221. kirin/worklist.py +30 -0
  222. kirin_toolchain-0.13.0.dist-info/METADATA +42 -0
  223. kirin_toolchain-0.13.0.dist-info/RECORD +225 -0
  224. kirin_toolchain-0.13.0.dist-info/WHEEL +4 -0
  225. 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
+ """
@@ -0,0 +1,8 @@
1
+ from dataclasses import dataclass
2
+
3
+ from .abc import Attribute
4
+
5
+
6
+ @dataclass
7
+ class _TypeAttribute(Attribute):
8
+ pass
@@ -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)