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,143 @@
1
+ from typing import Callable
2
+ from dataclasses import dataclass
3
+
4
+ from kirin import ir
5
+ from kirin.dialects import cf, func
6
+ from kirin.rewrite.abc import RewriteRule, RewriteResult
7
+
8
+ # TODO: use func.Constant instead of kirin.dialects.py.stmts.Constant
9
+ from kirin.dialects.py.constant import Constant
10
+
11
+ # NOTE: this only inlines func dialect
12
+
13
+
14
+ @dataclass
15
+ class Inline(RewriteRule):
16
+ heuristic: Callable[[ir.IRNode], bool]
17
+ """inline heuristic that determines whether a function should be inlined
18
+ """
19
+
20
+ def rewrite_Statement(self, node: ir.Statement) -> RewriteResult:
21
+ if isinstance(node, func.Invoke):
22
+ return self.rewrite_func_Invoke(node)
23
+ elif isinstance(node, func.Call):
24
+ return self.rewrite_func_Call(node)
25
+ else:
26
+ return RewriteResult()
27
+
28
+ def rewrite_func_Call(self, node: func.Call) -> RewriteResult:
29
+ if not isinstance(lambda_stmt := node.callee.owner, func.Lambda):
30
+ return RewriteResult()
31
+
32
+ # NOTE: a lambda statement is defined and used in the same scope
33
+ self.inline_call_like(node, tuple(node.args), lambda_stmt.body)
34
+ return RewriteResult(has_done_something=True)
35
+
36
+ def rewrite_func_Invoke(self, node: func.Invoke) -> RewriteResult:
37
+ has_done_something = False
38
+ callee = node.callee
39
+
40
+ if (
41
+ isinstance(callee, ir.Method)
42
+ and self.heuristic(callee.code)
43
+ and (call_trait := callee.code.get_trait(ir.CallableStmtInterface))
44
+ is not None
45
+ ):
46
+ region = call_trait.get_callable_region(callee.code)
47
+ func_self = Constant(node.callee)
48
+ func_self.result.name = node.callee.sym_name
49
+ func_self.insert_before(node)
50
+ self.inline_call_like(
51
+ node, (func_self.result,) + tuple(arg for arg in node.args), region
52
+ )
53
+ has_done_something = True
54
+
55
+ return RewriteResult(has_done_something=has_done_something)
56
+
57
+ def inline_call_like(
58
+ self,
59
+ call_like: ir.Statement,
60
+ args: tuple[ir.SSAValue, ...],
61
+ region: ir.Region,
62
+ ):
63
+ """
64
+ Inline a function call-like statement
65
+
66
+ Args:
67
+ call_like (ir.Statement): the call-like statement
68
+ args (tuple[ir.SSAValue, ...]): the arguments of the call (first one is the callee)
69
+ region (ir.Region): the region of the callee
70
+ """
71
+ # <stmt>
72
+ # <stmt>
73
+ # <br (a, b, c)>
74
+
75
+ # <block (a, b,c)>:
76
+ # <block>:
77
+ # <block>:
78
+ # <br>
79
+
80
+ # ^<block>:
81
+ # <stmt>
82
+ # <stmt>
83
+
84
+ # 1. we insert the entry block of the callee function
85
+ # 2. we insert the rest of the blocks into the parent region
86
+ # 3.1 if the return is in the entry block, means no control flow,
87
+ # replace the call results with the return values
88
+ # 3.2 if the return is some of the blocks, means control flow,
89
+ # split the current block into two, and replace the return with
90
+ # the branch instruction
91
+ # 4. remove the call
92
+ if not call_like.parent_block:
93
+ return
94
+
95
+ if not call_like.parent_region:
96
+ return
97
+
98
+ # NOTE: we cannot change region because it may be used elsewhere
99
+ inline_region: ir.Region = region.clone()
100
+ parent_block: ir.Block = call_like.parent_block
101
+ parent_region: ir.Region = call_like.parent_region
102
+
103
+ # wrap what's after invoke into a block
104
+ after_block = ir.Block()
105
+ stmt = call_like.next_stmt
106
+ while stmt is not None:
107
+ stmt.detach()
108
+ after_block.stmts.append(stmt)
109
+ stmt = call_like.next_stmt
110
+
111
+ for result in call_like.results:
112
+ block_arg = after_block.args.append_from(result.type, result.name)
113
+ result.replace_by(block_arg)
114
+
115
+ parent_block_idx = parent_region._block_idx[parent_block]
116
+ entry_block = inline_region.blocks.popfirst()
117
+ idx, block = 0, entry_block
118
+ while block is not None:
119
+ idx += 1
120
+
121
+ if block.last_stmt and isinstance(block.last_stmt, func.Return):
122
+ block.last_stmt.replace_by(
123
+ cf.Branch(
124
+ arguments=(block.last_stmt.value,),
125
+ successor=after_block,
126
+ )
127
+ )
128
+
129
+ parent_region.blocks.insert(parent_block_idx + idx, block)
130
+ block = inline_region.blocks.popfirst()
131
+
132
+ parent_region.blocks.append(after_block)
133
+
134
+ # NOTE: we expect always to have an entry block
135
+ # but we still check for it cuz we are not gonna
136
+ # error for empty regions here.
137
+ if entry_block:
138
+ cf.Branch(
139
+ arguments=args,
140
+ successor=entry_block,
141
+ ).insert_before(call_like)
142
+ call_like.delete()
143
+ return
@@ -0,0 +1,15 @@
1
+ from dataclasses import field, dataclass
2
+
3
+
4
+ @dataclass
5
+ class RewriteResult:
6
+ terminated: bool = field(default=False, kw_only=True)
7
+ has_done_something: bool = field(default=False, kw_only=True)
8
+ exceeded_max_iter: bool = field(default=False, kw_only=True)
9
+
10
+ def join(self, other: "RewriteResult") -> "RewriteResult":
11
+ return RewriteResult(
12
+ terminated=self.terminated or other.terminated,
13
+ has_done_something=self.has_done_something or other.has_done_something,
14
+ exceeded_max_iter=self.exceeded_max_iter or other.exceeded_max_iter,
15
+ )
kirin/rewrite/walk.py ADDED
@@ -0,0 +1,83 @@
1
+ from typing import Callable
2
+ from dataclasses import field, dataclass
3
+
4
+ from kirin.ir import Block, Region, Statement
5
+ from kirin.worklist import WorkList
6
+ from kirin.rewrite.abc import RewriteRule
7
+ from kirin.ir.nodes.base import IRNode
8
+ from kirin.rewrite.result import RewriteResult
9
+
10
+
11
+ @dataclass
12
+ class Walk(RewriteRule):
13
+ """Walk through the IR nodes and apply a rewrite rule.
14
+
15
+ The walk will apply the rewrite rule to each node in the IR tree in a depth-first order.
16
+
17
+ ### Parameters
18
+ - `map`: The rewrite rule to apply.
19
+ - `reverse`: Whether to traverse the IR tree in reverse order. Default is `False`.
20
+ - `region_first`: Whether to traverse the regions before the blocks. Default is `False`.
21
+ """
22
+
23
+ rule: RewriteRule
24
+ worklist: WorkList[IRNode] = field(default_factory=WorkList)
25
+ skip: Callable[[IRNode], bool] = field(default=lambda _: False)
26
+
27
+ # options
28
+ reverse: bool = field(default=False)
29
+ region_first: bool = field(default=False)
30
+
31
+ def rewrite(self, node: IRNode) -> RewriteResult:
32
+ # NOTE: because the rewrite pass may mutate the node
33
+ # thus we need to save the list of nodes to be processed
34
+ # first before we start processing them
35
+ self.populate_worklist(node)
36
+ has_done_something = False
37
+ subnode = self.worklist.pop()
38
+ while subnode is not None:
39
+ result = self.rule.rewrite(subnode)
40
+ if result.terminated:
41
+ return result
42
+
43
+ if result.has_done_something:
44
+ has_done_something = True
45
+ subnode = self.worklist.pop()
46
+ return RewriteResult(has_done_something=has_done_something)
47
+
48
+ def populate_worklist(self, node: IRNode) -> None:
49
+ if self.skip(node):
50
+ return
51
+
52
+ if isinstance(node, Statement):
53
+ self.populate_worklist_Statement(node)
54
+ elif isinstance(node, Region):
55
+ self.populate_worklist_Region(node)
56
+ elif isinstance(node, Block):
57
+ self.populate_worklist_Block(node)
58
+ else:
59
+ raise NotImplementedError(f"populate_worklist_{node.__class__.__name__}")
60
+
61
+ def populate_worklist_Statement(self, node: Statement) -> None:
62
+ if self.region_first:
63
+ self.worklist.append(node)
64
+
65
+ if node.regions:
66
+ for region in reversed(node.regions) if not self.reverse else node.regions:
67
+ self.populate_worklist(region)
68
+
69
+ if not self.region_first:
70
+ self.worklist.append(node)
71
+
72
+ def populate_worklist_Region(self, node: Region) -> None:
73
+ self.worklist.append(node)
74
+ if node.blocks:
75
+ for block in reversed(node.blocks) if not self.reverse else node.blocks:
76
+ self.populate_worklist(block)
77
+
78
+ def populate_worklist_Block(self, node: Block) -> None:
79
+ self.worklist.append(node)
80
+ stmt = node.last_stmt
81
+ while stmt is not None:
82
+ self.populate_worklist(stmt)
83
+ stmt = stmt.prev_stmt
@@ -0,0 +1,55 @@
1
+ from dataclasses import dataclass
2
+
3
+ from kirin import ir
4
+ from kirin.analysis import const
5
+ from kirin.rewrite.abc import RewriteRule, RewriteResult
6
+
7
+
8
+ @dataclass
9
+ class WrapConst(RewriteRule):
10
+ """Insert constant hints into the SSA values.
11
+
12
+ !!! note
13
+ This pass is not exactly the same as ConstantFold. ConstantFold
14
+ only rewrites the SSAValue with `const.Value` into a constant
15
+ statement. This rule, however, inserts the entire constant lattice
16
+ into the SSAValue's hints. Thus enabling other rules/analysis to
17
+ utilize the constant information beyond just `const.Value`.
18
+ """
19
+
20
+ frame: const.Frame
21
+
22
+ def wrap(self, value: ir.SSAValue) -> bool:
23
+ result = self.frame.entries.get(value)
24
+ if not result:
25
+ return False
26
+
27
+ const_hint = value.hints.get("const")
28
+ if const_hint and isinstance(const_hint, const.Result):
29
+ const_result = result.join(const_hint)
30
+ if const_result.is_equal(const_hint):
31
+ return False
32
+ else:
33
+ const_result = result
34
+ value.hints["const"] = const_result
35
+ return True
36
+
37
+ def rewrite_Block(self, node: ir.Block) -> RewriteResult:
38
+ has_done_something = False
39
+ for arg in node.args:
40
+ if self.wrap(arg):
41
+ has_done_something = True
42
+ return RewriteResult(has_done_something=has_done_something)
43
+
44
+ def rewrite_Statement(self, node: ir.Statement) -> RewriteResult:
45
+ has_done_something = False
46
+ for result in node.results:
47
+ if self.wrap(result):
48
+ has_done_something = True
49
+
50
+ if (
51
+ trait := node.get_trait(ir.MaybePure)
52
+ ) and node in self.frame.should_be_pure:
53
+ trait.set_pure(node)
54
+ has_done_something = True
55
+ return RewriteResult(has_done_something=has_done_something)
kirin/source.py ADDED
@@ -0,0 +1,21 @@
1
+ import ast
2
+ from dataclasses import dataclass
3
+
4
+
5
+ @dataclass
6
+ class SourceInfo:
7
+ lineno: int
8
+ col_offset: int
9
+ end_lineno: int | None
10
+ end_col_offset: int | None
11
+
12
+ @classmethod
13
+ def from_ast(cls, node: ast.AST, lineno_offset: int = 0, col_offset: int = 0):
14
+ end_lineno = getattr(node, "end_lineno", None)
15
+ end_col_offset = getattr(node, "end_col_offset", None)
16
+ return cls(
17
+ getattr(node, "lineno", 0) + lineno_offset,
18
+ getattr(node, "col_offset", 0) + col_offset,
19
+ end_lineno + lineno_offset if end_lineno is not None else None,
20
+ end_col_offset + col_offset if end_col_offset is not None else None,
21
+ )
kirin/symbol_table.py ADDED
@@ -0,0 +1,27 @@
1
+ from typing import Generic, TypeVar
2
+ from dataclasses import field, dataclass
3
+
4
+ T = TypeVar("T")
5
+
6
+
7
+ @dataclass
8
+ class SymbolTable(Generic[T]):
9
+ names: dict[str, T] = field(default_factory=dict)
10
+ """The table that maps names to values."""
11
+ prefix: str = field(default="", kw_only=True)
12
+ name_count: dict[str, int] = field(default_factory=dict, kw_only=True)
13
+ """The count of names that have been requested."""
14
+
15
+ def __getitem__(self, name: str) -> T:
16
+ return self.names[name]
17
+
18
+ def __contains__(self, name: str) -> bool:
19
+ return name in self.names
20
+
21
+ def __setitem__(self, name: str, value: T) -> None:
22
+ count = self.name_count.setdefault(name, 0)
23
+ self.name_count[name] = count + 1
24
+ self.names[f"{self.prefix}_{name}_{count}"] = value
25
+
26
+ def __delitem__(self, name: str) -> None:
27
+ del self.names[name]
kirin/types.py ADDED
@@ -0,0 +1,34 @@
1
+ """Bindings for built-in types.
2
+ """
3
+
4
+ from kirin.ir.method import Method
5
+ from kirin.ir.attrs.types import (
6
+ Union as Union,
7
+ Vararg as Vararg,
8
+ AnyType as AnyType,
9
+ Generic as Generic,
10
+ Literal as Literal,
11
+ PyClass as PyClass,
12
+ TypeVar as TypeVar,
13
+ BottomType as BottomType,
14
+ TypeAttribute as TypeAttribute,
15
+ hint2type as hint2type,
16
+ is_tuple_of as is_tuple_of,
17
+ )
18
+
19
+ Any = AnyType()
20
+ Bottom = BottomType()
21
+ Int = PyClass(int)
22
+ Float = PyClass(float)
23
+ String = PyClass(str)
24
+ Bool = PyClass(bool)
25
+ NoneType = PyClass(type(None))
26
+ List = Generic(list, TypeVar("T"))
27
+ Slice = Generic(slice, TypeVar("T"))
28
+ Tuple = Generic(tuple, Vararg(TypeVar("T")))
29
+ Dict = Generic(dict, TypeVar("K"), TypeVar("V"))
30
+ Set = Generic(set, TypeVar("T"))
31
+ FrozenSet = Generic(frozenset, TypeVar("T"))
32
+ TypeofFunctionType = Generic[type(lambda: None)]
33
+ FunctionType = Generic(type(lambda: None), Tuple, Vararg(Any))
34
+ MethodType = Generic(Method, TypeVar("Params", Tuple), TypeVar("Ret"))
kirin/worklist.py ADDED
@@ -0,0 +1,30 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Generic, TypeVar, Iterable
4
+ from dataclasses import field, dataclass
5
+
6
+ ElemType = TypeVar("ElemType")
7
+
8
+
9
+ @dataclass
10
+ class WorkList(Generic[ElemType]):
11
+ """The worklist data structure.
12
+
13
+ The worklist is a stack that allows for O(1) removal of elements from the stack.
14
+ """
15
+
16
+ _stack: list[ElemType] = field(default_factory=list, init=False)
17
+
18
+ def is_empty(self) -> bool:
19
+ return len(self._stack) == 0
20
+
21
+ def append(self, item: ElemType) -> None:
22
+ self._stack.append(item)
23
+
24
+ def extend(self, items: Iterable[ElemType]) -> None:
25
+ self._stack.extend(items)
26
+
27
+ def pop(self) -> ElemType | None:
28
+ if self._stack:
29
+ return self._stack.pop()
30
+ return None
@@ -0,0 +1,42 @@
1
+ Metadata-Version: 2.4
2
+ Name: kirin-toolchain
3
+ Version: 0.13.0
4
+ Summary: The Kirin Toolchain for building compilers and interpreters.
5
+ Author-email: Roger-luo <rluo@quera.com>
6
+ License-File: LICENSE
7
+ Requires-Python: >=3.10
8
+ Requires-Dist: beartype>=0.17.2
9
+ Requires-Dist: rich>=13.7.1
10
+ Requires-Dist: typing-extensions>=4.11.0
11
+ Description-Content-Type: text/markdown
12
+
13
+ # KIRIN
14
+
15
+ [![CI](https://github.com/QuEraComputing/kirin/actions/workflows/ci.yml/badge.svg)](https://github.com/QuEraComputing/kirin/actions/workflows/ci.yml)
16
+ [![codecov](https://codecov.io/gh/QuEraComputing/kirin/graph/badge.svg?token=lkUZ9DTqy4)](https://codecov.io/gh/QuEraComputing/kirin)
17
+ [![Supported Python versions](https://img.shields.io/pypi/pyversions/kirin-toolchain.svg?color=%2334D058)](https://pypi.org/project/fastapi)
18
+
19
+ *K*ernel *I*ntermediate *R*epresentation *IN*frastructure
20
+
21
+ > [!IMPORTANT]
22
+ >
23
+ > This project is in the early stage of development. API and features are subject to change.
24
+ > If you are concerned about the stability of the APIs, consider pin the version of Kirin in your project.
25
+
26
+ ## Installation
27
+
28
+ ### Install via `uv` (Recommended)
29
+
30
+ ```py
31
+ uv add kirin-toolchain
32
+ ```
33
+
34
+ ### Install via pip
35
+
36
+ ```bash
37
+ pip install kirin-toolchain
38
+ ```
39
+
40
+ ## License
41
+
42
+ Apache License 2.0 with LLVM Exceptions