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
@@ -0,0 +1,277 @@
1
+ from typing import Any
2
+ from dataclasses import MISSING
3
+
4
+ from typing_extensions import Unpack
5
+
6
+ from kirin import ir, types
7
+ from kirin.decl import info
8
+ from kirin.decl.base import BaseModifier, StatementOptions
9
+
10
+ from ._create_fn import create_fn
11
+ from ._set_new_attribute import set_new_attribute
12
+
13
+
14
+ class _HAS_DEFAULT_FACTORY_CLASS:
15
+ def __repr__(self):
16
+ return "<factory>"
17
+
18
+
19
+ _HAS_DEFAULT_FACTORY = _HAS_DEFAULT_FACTORY_CLASS()
20
+
21
+
22
+ class EmitInit(BaseModifier):
23
+ _POST_INIT_NAME = "__post_init__"
24
+ _RESULT_VALUE_NAME = "_kirin_ResultValue"
25
+ _KIRIN_PYATTR = "_kirin_PyAttr"
26
+ _ATTR_FACTORY_PREFIX = "_kirin_attr_factory_"
27
+ _SELF_CLASS = "_kirin_self_class"
28
+ _KIRIN_STMT = "_kirin_Statement"
29
+
30
+ def __init__(self, cls: type, **kwargs: Unpack[StatementOptions]) -> None:
31
+ super().__init__(cls, **kwargs)
32
+ from kirin.ir.attrs.py import PyAttr
33
+
34
+ self._init_params: list[str] = []
35
+ self._init_body: list[str] = []
36
+ self._init_locals: dict[str, Any] = {}
37
+ self.has_post_init = hasattr(self.cls, self._POST_INIT_NAME)
38
+ self.globals.update(
39
+ {
40
+ "_PY_ANY": types.Any,
41
+ self._KIRIN_STMT: ir.Statement,
42
+ self._SELF_CLASS: self.cls,
43
+ self._RESULT_VALUE_NAME: ir.ResultValue,
44
+ self._KIRIN_PYATTR: PyAttr,
45
+ }
46
+ )
47
+
48
+ @classmethod
49
+ def _hint_name(cls, f: info.Field):
50
+ return f"_hint_{f.name}"
51
+
52
+ def emit_init(self):
53
+ _args_groups = []
54
+ for f in self.fields.args.values():
55
+ if f.group:
56
+ _args_groups.append(f.name)
57
+ setattr(self.cls, "_arg_groups", frozenset(_args_groups))
58
+
59
+ if "__init__" in self.cls.__dict__:
60
+ return True
61
+
62
+ self._init_locals.update(
63
+ {self._hint_name(f): f.annotation for f in self.fields}
64
+ )
65
+ self._init_locals.update(
66
+ {
67
+ "MISSING": MISSING,
68
+ "_HAS_DEFAULT_FACTORY": _HAS_DEFAULT_FACTORY,
69
+ }
70
+ )
71
+
72
+ self._emit_params()
73
+ self._emit_field_init(len(_args_groups) > 0)
74
+
75
+ fn = create_fn(
76
+ "__init__",
77
+ self._init_params,
78
+ self._init_body,
79
+ globals=self.globals,
80
+ locals=self._init_locals,
81
+ return_type=None,
82
+ )
83
+ set_new_attribute(self.cls, "__init__", fn)
84
+
85
+ def _emit_params(self):
86
+ self._init_params.append(self._self_name)
87
+ for f in self.fields.std_args.values():
88
+ self._init_params.append(self._init_param_value(f))
89
+
90
+ kw_params: list[str] = []
91
+ for f in self.fields.kw_args.values():
92
+ kw_params.append(self._init_param_value(f))
93
+
94
+ for f in self.fields.attributes.values():
95
+ if f.init:
96
+ kw_params.append(self._init_param_value(f))
97
+
98
+ for f in self.fields.regions.values():
99
+ if f.init:
100
+ kw_params.append(self._init_param_value(f))
101
+
102
+ for f in self.fields.blocks.values():
103
+ if f.init:
104
+ kw_params.append(self._init_param_value(f))
105
+
106
+ if kw_params:
107
+ self._init_params.append("*")
108
+ self._init_params.extend(kw_params)
109
+
110
+ def _emit_field_init(self, has_args_groups: bool):
111
+ self._init_body.append(
112
+ (
113
+ f"{self._KIRIN_STMT}.__init__({self._self_name},"
114
+ f"args={self._arg_seq()},"
115
+ f"regions={self._regions_seq()},"
116
+ f"successors={self._blocks_seq()},"
117
+ f"result_types={self._result_types_seq()},"
118
+ f"attributes={self._attribute_seq()},"
119
+ f"args_slice={self._args_slice(has_args_groups)}"
120
+ ")"
121
+ )
122
+ )
123
+
124
+ # TODO: support InitVar?
125
+ if self.has_post_init:
126
+ self._init_body.append(f"{self._self_name}.{self._POST_INIT_NAME}()")
127
+
128
+ def _init_param_value(self, f: info.Field):
129
+ if isinstance(f, info.AttributeField): # only attribute can have defaults
130
+ if f.default is MISSING and f.default_factory is None:
131
+ default = ""
132
+ elif f.default is not MISSING:
133
+ default = f"={self._ATTR_FACTORY_PREFIX}{f.name}"
134
+ elif f.default_factory is not None:
135
+ default = "=_HAS_DEFAULT_FACTORY"
136
+ else:
137
+ raise ValueError("unexpected default")
138
+ return f"{f.name}:{self._hint_name(f)}{default}"
139
+ elif isinstance(f, info.ArgumentField): # arguments are always required
140
+ return f"{f.name}:{self._hint_name(f)}"
141
+ elif isinstance(f, info.ResultField):
142
+ raise ValueError("result fields are not allowed in __init__")
143
+ elif isinstance(f, info.RegionField):
144
+ return f"{f.name}:{self._hint_name(f)}=_HAS_DEFAULT_FACTORY"
145
+ elif isinstance(f, info.BlockField):
146
+ return f"{f.name}:{self._hint_name(f)}=_HAS_DEFAULT_FACTORY"
147
+ else: # the rest fields are all required
148
+ raise ValueError(f"unexpected field type {type(f)}")
149
+
150
+ def _arg_seq(self):
151
+ args: list[str] = [self._field_param(f) for f in self.fields.args.values()]
152
+ return self._tuple_str(args)
153
+
154
+ def _field_param(self, f: info.ArgumentField):
155
+ if f.group:
156
+ return f"*{f.name}"
157
+ else:
158
+ return f"{f.name}"
159
+
160
+ def _result_types_seq(self):
161
+ result_types = [
162
+ self._result_type_value(f) for f in self.fields.results.values()
163
+ ]
164
+ return self._tuple_str(result_types)
165
+
166
+ def _result_type_value(self, f: info.ResultField):
167
+ name = f"_result_type_{f.name}"
168
+ self._init_locals[name] = f.type
169
+ return name
170
+
171
+ def _attribute_seq(self):
172
+ attrs = ",".join(
173
+ [
174
+ f'"{name}": {self._attribute_value(f)}'
175
+ for name, f in self.fields.attributes.items()
176
+ ]
177
+ )
178
+ return "{" + attrs + "}"
179
+
180
+ def _attribute_value(self, f: info.AttributeField):
181
+ default_name = f"{self._ATTR_FACTORY_PREFIX}{f.name}"
182
+ if f.default_factory is not None:
183
+ value = self._field_with_default_factory(
184
+ default_name, f.name, f.init, f.default_factory
185
+ )
186
+ else:
187
+ # no default factory
188
+ if f.init:
189
+ if f.default is not MISSING:
190
+ self._init_locals[default_name] = f.default
191
+ value: str = f.name # type: ignore
192
+ else: # no default factory, no init, no default
193
+ raise ValueError(
194
+ "attribute must have a default or default factory or be initialized (init=True)"
195
+ )
196
+
197
+ # declared via python type, optionally check if we can
198
+ # convert the value to data.PyAttr
199
+ if f.pytype:
200
+ attr_type = f"_kirin_attr_type_{f.name}"
201
+ self._init_locals[attr_type] = f.type
202
+ value = (
203
+ f"{self._KIRIN_PYATTR}({value}, {attr_type}) "
204
+ f"if not isinstance({value}, {self._KIRIN_PYATTR}) "
205
+ f"else {value}"
206
+ )
207
+
208
+ return value
209
+
210
+ def _regions_seq(self):
211
+ regions = [self._regions_value(f) for f in self.fields.regions.values()]
212
+ return self._tuple_str(regions)
213
+
214
+ def _regions_value(self, f: info.RegionField):
215
+ return self._field_with_default_factory(
216
+ f"_kirin_region_{f.name}", f.name, f.init, f.default_factory
217
+ )
218
+
219
+ def _blocks_seq(self):
220
+ blocks = [self._blocks_value(f) for f in self.fields.blocks.values()]
221
+ return self._tuple_str(blocks)
222
+
223
+ def _blocks_value(self, f: info.BlockField):
224
+ return self._field_with_default_factory(
225
+ f"_kirin_block_{f.name}", f.name, f.init, f.default_factory
226
+ )
227
+
228
+ def _args_slice(self, has_args_groups: bool):
229
+ if not has_args_groups:
230
+ return (
231
+ "{"
232
+ + ", ".join(
233
+ [
234
+ f"'{f.name}': {index}"
235
+ for index, f in enumerate(self.fields.args.values())
236
+ ]
237
+ )
238
+ + "}"
239
+ )
240
+
241
+ # NOTE: SSAValue fields do not have default/default_factory
242
+ # so we can just count the input arguments
243
+ ret: list[str] = []
244
+ self._init_body.append("__args_slice_count = 0")
245
+ for f in self.fields.args.values():
246
+ if f.group:
247
+ self._init_body.append(
248
+ f"__{f.name}_slice = slice(__args_slice_count, __args_slice_count + len({f.name}))"
249
+ )
250
+ self._init_body.append(f"__args_slice_count += len({f.name})")
251
+ else:
252
+ self._init_body.append(f"__{f.name}_slice = __args_slice_count")
253
+ self._init_body.append("__args_slice_count += 1")
254
+ ret.append(f'"{f.name}": __{f.name}_slice')
255
+ return "{" + ",".join(ret) + "}"
256
+
257
+ def _field_with_default_factory(
258
+ self, factory_name: str, name: str | None, init: bool, default_factory
259
+ ):
260
+ # block always has default_factory
261
+ if init:
262
+ self._init_locals[factory_name] = default_factory
263
+ value = (
264
+ f"{factory_name}() "
265
+ f"if {name} is _HAS_DEFAULT_FACTORY "
266
+ f"else {name}"
267
+ )
268
+ else:
269
+ self._init_locals[factory_name] = default_factory
270
+ value = f"{factory_name}()"
271
+ return value
272
+
273
+ @staticmethod
274
+ def _tuple_str(seq: list[str]):
275
+ if not seq:
276
+ return "()"
277
+ return f"({', '.join(seq)}, )"
@@ -0,0 +1,10 @@
1
+ from kirin.decl.base import BaseModifier
2
+ from kirin.decl.camel2snake import camel2snake
3
+
4
+ from ._set_new_attribute import set_new_attribute
5
+
6
+
7
+ class EmitName(BaseModifier):
8
+
9
+ def emit_name(self):
10
+ set_new_attribute(self.cls, "name", camel2snake(self.cls.__name__))
@@ -0,0 +1,182 @@
1
+ from kirin import ir
2
+ from kirin.decl import info
3
+ from kirin.decl.emit.init import BaseModifier
4
+
5
+ from ._create_fn import create_fn
6
+ from ._set_new_attribute import set_new_attribute
7
+
8
+
9
+ class EmitProperty(BaseModifier):
10
+ _KIRIN_PYATTR = "_kirin_PyAttr"
11
+
12
+ def emit_property(self):
13
+ for name, f in self.fields.args.items():
14
+ getter, setter = self._emit_arg_property(f)
15
+ set_new_attribute(self.cls, name, property(getter, setter))
16
+
17
+ for name, f in self.fields.kw_args.items():
18
+ getter, setter = self._emit_arg_property(f)
19
+ set_new_attribute(self.cls, name, property(getter, setter))
20
+
21
+ for i, (name, f) in enumerate(self.fields.results.items()):
22
+ getter, setter = self._emit_result_property(i, f)
23
+ set_new_attribute(self.cls, name, property(getter, setter))
24
+
25
+ for name, f in self.fields.attributes.items():
26
+ getter, setter = self._emit_attribute_property(f)
27
+ set_new_attribute(self.cls, name, property(getter, setter))
28
+
29
+ for i, (name, f) in enumerate(self.fields.blocks.items()):
30
+ getter, setter = self._emit_successor_property(i, f)
31
+ set_new_attribute(self.cls, name, property(getter, setter))
32
+
33
+ for i, (name, f) in enumerate(self.fields.regions.items()):
34
+ getter, setter = self._emit_region_property(i, f)
35
+ set_new_attribute(self.cls, name, property(getter, setter))
36
+
37
+ def _emit_arg_property(self, f: info.ArgumentField):
38
+ getter = create_fn(
39
+ f"_get_{f.name}",
40
+ args=[self._self_name],
41
+ body=[
42
+ f'return {self._self_name}._args[{self._self_name}._name_args_slice["{f.name}"]]'
43
+ ],
44
+ globals=self.globals,
45
+ return_type=tuple[ir.SSAValue, ...] if f.group else ir.SSAValue,
46
+ )
47
+
48
+ if f.group:
49
+ return getter, self._emit_arg_property_group_setter(f)
50
+ return getter, self._emit_arg_property_std_setter(f)
51
+
52
+ def _emit_arg_property_std_setter(self, f: info.ArgumentField):
53
+ return create_fn(
54
+ f"_set_{f.name}",
55
+ args=[self._self_name, "value: _value_hint"],
56
+ body=[
57
+ f"s = {self._self_name}._name_args_slice['{f.name}']",
58
+ f"old = {self._self_name}.args[s]",
59
+ f"old.remove_use(Use({self._self_name}, s))",
60
+ f"value.add_use(Use({self._self_name}, s))",
61
+ "self.args = (*self.args[:s], value, *self.args[s + 1:])",
62
+ ],
63
+ globals=self.globals,
64
+ locals={"_value_hint": ir.SSAValue},
65
+ return_type=None,
66
+ )
67
+
68
+ def _emit_arg_property_group_setter(self, f: info.ArgumentField):
69
+ return create_fn(
70
+ f"_set_{f.name}",
71
+ args=[self._self_name, "value: _value_hint"],
72
+ body=[
73
+ f"s = {self._self_name}._name_args_slice['{f.name}']",
74
+ "start, stop = s.start, s.stop",
75
+ f"old = {self._self_name}.args[s]",
76
+ "a_range = range(start, stop, s.step or 1)",
77
+ "for i, arg in zip(a_range, old):",
78
+ f" arg.remove_use(Use({self._self_name}, i))",
79
+ "for i, arg in zip(a_range, value):",
80
+ f" arg.add_use(Use({self._self_name}, i))",
81
+ f"{self._self_name}.args = (*{self._self_name}.args[:start], *value, *{self._self_name}.args[stop + 1:])",
82
+ ],
83
+ globals=self.globals,
84
+ locals={"_value_hint": tuple[ir.SSAValue, ...]},
85
+ return_type=None,
86
+ )
87
+
88
+ def _emit_result_property(self, index: int, f: info.ResultField):
89
+ getter = create_fn(
90
+ f"_get_{f.name}",
91
+ args=[self._self_name],
92
+ body=[f"return {self._self_name}._results[{index}]"],
93
+ globals=self.globals,
94
+ return_type=ir.ResultValue,
95
+ )
96
+
97
+ # well you cannot delete what already happened, can you?
98
+ setter = create_fn(
99
+ f"_set_{f.name}",
100
+ args=[self._self_name, "value: _value_hint"],
101
+ body=[f"raise AttributeError('result property {f.name} is read-only')"],
102
+ globals=self.globals,
103
+ locals={"_value_hint": ir.ResultValue},
104
+ return_type=None,
105
+ )
106
+
107
+ return getter, setter
108
+
109
+ def _emit_attribute_property(self, f: info.AttributeField):
110
+ from kirin.ir.attrs.py import PyAttr
111
+
112
+ storage = "attributes"
113
+ attr = f"{self._self_name}.{storage}['{f.name}']"
114
+ getter = create_fn(
115
+ f"_get_{f.name}",
116
+ args=[self._self_name],
117
+ body=[f"return {attr}.data" if f.pytype else f"return {attr}"],
118
+ globals=self.globals,
119
+ return_type=f.annotation,
120
+ )
121
+
122
+ setter = create_fn(
123
+ f"_set_{f.name}",
124
+ args=[self._self_name, "value: _value_hint"],
125
+ body=[
126
+ (
127
+ f"{attr} = value if isinstance(value, {self._KIRIN_PYATTR}) else {self._KIRIN_PYATTR}(value)"
128
+ if f.pytype
129
+ else f"{attr} = value"
130
+ )
131
+ ],
132
+ globals=self.globals,
133
+ locals={"_value_hint": PyAttr if f.pytype else f.annotation},
134
+ return_type=None,
135
+ )
136
+
137
+ return getter, setter
138
+
139
+ def _emit_successor_property(self, index: int, f: info.BlockField):
140
+ getter = create_fn(
141
+ f"_get_{f.name}",
142
+ args=[self._self_name],
143
+ body=[f"return {self._self_name}.successors[{index}]"],
144
+ globals=self.globals,
145
+ return_type=ir.Block,
146
+ )
147
+
148
+ setter = create_fn(
149
+ f"_set_{f.name}",
150
+ args=[self._self_name, "value: _value_hint"],
151
+ body=[f"{self._self_name}.successors[{index}] = value"],
152
+ globals=self.globals,
153
+ locals={"_value_hint": ir.Block},
154
+ return_type=None,
155
+ )
156
+
157
+ return getter, setter
158
+
159
+ def _emit_region_property(self, index: int, f: info.RegionField):
160
+ getter = create_fn(
161
+ f"_get_{f.name}",
162
+ args=[self._self_name],
163
+ body=[f"return {self._self_name}.regions[{index}]"],
164
+ globals=self.globals,
165
+ return_type=ir.Region,
166
+ )
167
+
168
+ setter = create_fn(
169
+ f"_set_{f.name}",
170
+ args=[self._self_name, "value: _value_hint"],
171
+ body=[
172
+ f"old = {self._self_name}.regions[{index}]",
173
+ "old.parent = None",
174
+ f"value.parent = {self._self_name}",
175
+ f"{self._self_name}.regions[{index}] = value",
176
+ ],
177
+ globals=self.globals,
178
+ locals={"_value_hint": ir.Region},
179
+ return_type=None,
180
+ )
181
+
182
+ return getter, setter
@@ -0,0 +1,31 @@
1
+ from kirin.decl.base import BaseModifier
2
+
3
+ from ._create_fn import create_fn
4
+ from ._set_new_attribute import set_new_attribute
5
+
6
+
7
+ class EmitRepr(BaseModifier):
8
+
9
+ def emit_repr(self):
10
+ if "repr" not in self.params or not self.params["repr"]:
11
+ return
12
+
13
+ body = [f'ret = "{self.cls.__name__}("']
14
+ for idx, field in enumerate(self.fields):
15
+ if idx > 0:
16
+ body.append('ret += ", "')
17
+ body.append(f'ret += f"{field.name}={{{self._self_name}.{field.name}}}"')
18
+ body.append('ret += ")"')
19
+ body.append("return ret")
20
+
21
+ set_new_attribute(
22
+ self.cls,
23
+ "__repr__",
24
+ create_fn(
25
+ "__repr__",
26
+ args=[self._self_name],
27
+ body=body,
28
+ globals=self.globals,
29
+ return_type=str,
30
+ ),
31
+ )
@@ -0,0 +1,13 @@
1
+ from kirin.decl.base import BaseModifier
2
+
3
+ from ._set_new_attribute import set_new_attribute
4
+
5
+
6
+ class EmitTraits(BaseModifier):
7
+
8
+ def emit_traits(self):
9
+ # if no parent defines traits, set it to empty set
10
+ for base in self.cls.__mro__[-1:0:-1]:
11
+ if hasattr(base, "traits"):
12
+ return
13
+ set_new_attribute(self.cls, "traits", frozenset({}))
@@ -0,0 +1,77 @@
1
+ from typing import Any
2
+
3
+ from kirin.exceptions import VerificationError
4
+ from kirin.decl.emit.init import BaseModifier
5
+
6
+ from ._create_fn import create_fn
7
+ from ._set_new_attribute import set_new_attribute
8
+
9
+
10
+ class EmitTypeCheck(BaseModifier):
11
+ _VERIFICATION_ERROR = "_kirin_VerificationError"
12
+
13
+ def emit_typecheck(self):
14
+ typecheck_locals: dict[str, Any] = {
15
+ self._VERIFICATION_ERROR: VerificationError,
16
+ }
17
+ body: list[str] = []
18
+ for name, f in self.fields.args.items():
19
+ if f.type is f.type.top():
20
+ continue
21
+
22
+ value_type = f"_args_{f.name}_type"
23
+ typecheck_locals.update({value_type: f.type})
24
+ if f.group:
25
+ body.extend(
26
+ (
27
+ f"for v in {self._self_name}.{f.name}:",
28
+ *self._guard_ssa_type("v", f.name, value_type, indent=1),
29
+ )
30
+ )
31
+ else:
32
+ body.extend(
33
+ self._guard_ssa_type(
34
+ f"{self._self_name}.{name}", f.name, value_type
35
+ )
36
+ )
37
+
38
+ for name, f in self.fields.results.items():
39
+ if f.type is f.type.top():
40
+ continue
41
+
42
+ value_type = f"_results_{f.name}_type"
43
+ typecheck_locals.update({value_type: f.type})
44
+ body.extend(
45
+ self._guard_ssa_type(f"{self._self_name}.{name}", name, value_type)
46
+ )
47
+
48
+ for name in self.fields.blocks.keys():
49
+ body.append(f"{self._self_name}.{name}.typecheck()")
50
+
51
+ for name, f in self.fields.regions.items():
52
+ body.append(f"{self._self_name}.{name}.typecheck()")
53
+
54
+ # NOTE: we still need to generate this because it is abstract
55
+ if not body:
56
+ body.append("pass")
57
+
58
+ set_new_attribute(
59
+ self.cls,
60
+ "typecheck",
61
+ create_fn(
62
+ name="_kirin_decl_typecheck",
63
+ args=[self._self_name],
64
+ body=body,
65
+ globals=self.globals,
66
+ locals=typecheck_locals,
67
+ return_type=None,
68
+ ),
69
+ )
70
+
71
+ def _guard_ssa_type(self, ssa, name, type, indent: int = 0):
72
+ space = " " * indent
73
+ msg = f"'Invalid type for {name}, expected ' + repr({type}) + ', got ' + repr({ssa}.type)"
74
+ return (
75
+ space + f"if not {ssa}.type.is_subseteq({type}):",
76
+ space + f" raise {self._VERIFICATION_ERROR}({self._self_name}, {msg})",
77
+ )
@@ -0,0 +1,51 @@
1
+ from typing import Any
2
+
3
+ from kirin.exceptions import VerificationError
4
+ from kirin.decl.emit.init import BaseModifier
5
+
6
+ from ._create_fn import create_fn
7
+ from ._set_new_attribute import set_new_attribute
8
+
9
+
10
+ class EmitVerify(BaseModifier):
11
+ _VERIFICATION_ERROR = "_kirin_VerificationError"
12
+
13
+ def emit_verify(self):
14
+ verify_locals: dict[str, Any] = {
15
+ self._VERIFICATION_ERROR: VerificationError,
16
+ }
17
+ body: list[str] = []
18
+ for name in self.fields.blocks.keys():
19
+ body.append(f"{self._self_name}.{name}.verify()")
20
+
21
+ for name, f in self.fields.regions.items():
22
+ body.append(f"{self._self_name}.{name}.verify()")
23
+ if not f.multi:
24
+ body.append(f"if len({self._self_name}.{name}.blocks) != 1:")
25
+ body.append(
26
+ f" raise {self._VERIFICATION_ERROR}({self._self_name},"
27
+ f" 'Invalid number of blocks for {name}')"
28
+ )
29
+
30
+ if (traits := getattr(self.cls, "traits", None)) is not None:
31
+ for trait in traits:
32
+ trait_obj = f"_kirin_verify_trait_{trait.__class__.__name__}"
33
+ verify_locals.update({trait_obj: trait})
34
+ body.append(f"{trait_obj}.verify({self._self_name})")
35
+
36
+ # NOTE: we still need to generate this because it is abstract
37
+ if not body:
38
+ body.append("pass")
39
+
40
+ set_new_attribute(
41
+ self.cls,
42
+ "verify",
43
+ create_fn(
44
+ name="_kirin_decl_verify",
45
+ args=[self._self_name],
46
+ body=body,
47
+ globals=self.globals,
48
+ locals=verify_locals,
49
+ return_type=None,
50
+ ),
51
+ )