44import ast
55
66from kirin import ir
7+ from kirin .dialects import cf , py
78from kirin .lowering import Frame , Result , FromPythonAST , LoweringState
89from kirin .exceptions import DialectLoweringError
9- from kirin .dialects .cf import stmts as cf
1010
1111dialect = ir .Dialect ("lowering.cf" )
1212
@@ -21,6 +21,83 @@ def lower_Pass(self, state: LoweringState, node: ast.Pass) -> Result:
2121 state .append_stmt (cf .Branch (arguments = (), successor = next ))
2222 return Result ()
2323
24+ def lower_For (self , state : LoweringState , node : ast .For ) -> Result :
25+ iterable = state .visit (node .iter ).expect_one ()
26+ iter_stmt = state .append_stmt (py .iterable .Iter (iterable ))
27+ none_stmt = state .append_stmt (py .Constant (None ))
28+ yields : list [str ] = []
29+
30+ def new_block_arg_if_inside_loop (frame : Frame , capture : ir .SSAValue ):
31+ if not capture .name :
32+ raise DialectLoweringError ("unexpected loop variable captured" )
33+ yields .append (capture .name )
34+ return frame .entry_block .args .append_from (capture .type , capture .name )
35+
36+ frame = state .current_frame
37+ next_block = ir .Block ()
38+
39+ body_frame = state .push_frame (
40+ Frame .from_stmts (
41+ node .body ,
42+ state ,
43+ region = frame .current_region ,
44+ globals = state .current_frame .globals ,
45+ capture_callback = new_block_arg_if_inside_loop ,
46+ )
47+ )
48+ body_frame .next_block = next_block
49+ next_value = body_frame .entry_block .args .append_from (ir .types .Any , "next_value" )
50+ py .unpack .unpackable (state , node .target , next_value )
51+ state .exhaust (body_frame )
52+ next_stmt = body_frame .append_stmt (py .iterable .Next (iter_stmt .iter ))
53+ cond_stmt = body_frame .append_stmt (py .cmp .Is (next_stmt .value , none_stmt .result ))
54+ yield_args = tuple (body_frame .get_scope (name ) for name in yields )
55+ state .pop_frame ()
56+
57+ next_frame = state .push_frame (
58+ Frame .from_stmts (
59+ frame .stream .split (),
60+ state ,
61+ region = frame .current_region ,
62+ block = next_block ,
63+ globals = frame .globals ,
64+ )
65+ )
66+ next_frame .next_block = frame .next_block
67+ for name , arg in zip (yields , yield_args ):
68+ input = next_frame .current_block .args .append_from (arg .type , name )
69+ next_frame .defs [name ] = input
70+ state .exhaust ()
71+ state .pop_frame ()
72+
73+ yield_args = tuple (body_frame .get_scope (name ) for name in yields )
74+ body_frame .append_stmt (
75+ cf .ConditionalBranch (
76+ cond_stmt .result ,
77+ yield_args ,
78+ (next_stmt .value ,) + yield_args ,
79+ then_successor = next_frame .entry_block ,
80+ else_successor = body_frame .entry_block ,
81+ )
82+ )
83+
84+ next_stmt = frame .append_stmt (py .iterable .Next (iter_stmt .iter ))
85+ cond_stmt = frame .append_stmt (py .cmp .Is (next_stmt .value , none_stmt .result ))
86+ yield_args = tuple (frame .get_scope (name ) for name in yields )
87+ frame .append_stmt (
88+ cf .ConditionalBranch (
89+ cond_stmt .result ,
90+ yield_args ,
91+ (next_stmt .value ,) + yield_args ,
92+ then_successor = next_frame .entry_block ,
93+ else_successor = body_frame .entry_block ,
94+ )
95+ )
96+ frame .current_block = next_frame .current_block
97+ frame .next_block = next_frame .next_block
98+ frame .defs .update (next_frame .defs )
99+ return Result ()
100+
24101 def lower_If (self , state : LoweringState , node : ast .If ) -> Result :
25102 cond = state .visit (node .test ).expect_one ()
26103
0 commit comments