@@ -71,6 +71,7 @@ pub struct SSAChunk {
7171 pub names : Vec < String > ,
7272 pub functions : Vec < ( Vec < String > , SSAChunk ) > ,
7373 pub annotations : HashMap < String , String > ,
74+ pub phi_sources : Vec < ( u16 , u16 ) >
7475}
7576
7677impl SSAChunk {
@@ -83,7 +84,8 @@ impl SSAChunk {
8384}
8485
8586struct JoinNode {
86- backup : HashMap < String , u32 >
87+ backup : HashMap < String , u32 > ,
88+ then : Option < HashMap < String , u32 > >
8789}
8890
8991pub struct Parser < ' src , I : Iterator < Item = Token > > {
@@ -138,9 +140,10 @@ impl<'src, I: Iterator<Item = Token>> Parser<'src, I> {
138140 fn current_version ( & self , name : & str ) -> u32 { self . ssa_versions . get ( name) . copied ( ) . unwrap_or ( 0 ) }
139141
140142 fn increment_version ( & mut self , name : & str ) -> u32 {
141- let v = self . current_version ( name) + 1 ;
142- self . ssa_versions . insert ( name. to_string ( ) , v) ;
143- v
143+ let current = self . ssa_versions . get ( name) . copied ( ) . unwrap_or ( 0 ) ;
144+ let new_ver = current + 1 ;
145+ self . ssa_versions . insert ( name. to_string ( ) , new_ver) ;
146+ new_ver
144147 }
145148
146149 fn emit_load_ssa ( & mut self , name : String ) {
@@ -151,41 +154,60 @@ impl<'src, I: Iterator<Item = Token>> Parser<'src, I> {
151154 }
152155
153156 fn enter_block ( & mut self ) {
154- self . join_stack . push ( JoinNode { backup : self . ssa_versions . clone ( ) } ) ;
157+ self . join_stack . push ( JoinNode { backup : self . ssa_versions . clone ( ) , then : None } ) ;
155158 }
156159
157- fn commit_block ( & mut self ) {
158- if let Some ( j) = self . join_stack . pop ( ) {
159- let post = self . ssa_versions . clone ( ) ;
160- self . ssa_versions = j. backup ;
161-
162- let mut diffs: Vec < ( String , u32 ) > = post
163- . into_iter ( )
164- . filter ( |( name, post_ver) | {
165- self . ssa_versions . get ( name) . copied ( ) . unwrap_or ( 0 ) != * post_ver
166- } )
167- . collect ( ) ;
168-
169- diffs. sort_by ( |( a, _) , ( b, _) | a. cmp ( b) ) ;
170-
171- for ( name, post_ver) in diffs {
172- self . ssa_versions . insert ( name. clone ( ) , post_ver) ;
173- let new_ver = self . increment_version ( & name) ;
174- let ssa = format ! ( "{}_{}" , name, new_ver) ;
175- let i = self . chunk . push_name ( & ssa) ;
176- self . chunk . emit ( OpCode :: Phi , i) ;
177- }
160+ fn mid_block ( & mut self ) {
161+ let Some ( j) = self . join_stack . last_mut ( ) else { return } ;
162+
163+ let current = self . ssa_versions . clone ( ) ;
164+ j. then = Some ( current. clone ( ) ) ;
165+
166+ // Merge de versiones más altas (max) - inline y súper limpio
167+ let mut restored = j. backup . clone ( ) ;
168+ for ( name, & v) in & current {
169+ let e = restored. entry ( name. clone ( ) ) . or_insert ( 0 ) ;
170+ * e = ( * e) . max ( v) ;
178171 }
172+ self . ssa_versions = restored;
179173 }
180174
181- fn peek ( & mut self ) -> Option < TokenType > {
182- loop {
183- match self . tokens . peek ( ) . map ( |t| t. kind . clone ( ) ) {
184- Some ( TokenType :: Newline | TokenType :: Nl | TokenType :: Comment ) => { self . tokens . next ( ) ; }
185- Some ( k) => return Some ( k) ,
186- None => return None ,
187- }
175+ fn commit_block ( & mut self ) {
176+ let Some ( j) = self . join_stack . pop ( ) else { return } ;
177+ let post = self . ssa_versions . clone ( ) ;
178+ let ( a, b) = match j. then {
179+ Some ( t) => ( t, post) ,
180+ None => ( post, j. backup . clone ( ) )
181+ } ;
182+
183+ let mut names: Vec < _ > = a. keys ( ) . chain ( b. keys ( ) ) . cloned ( ) . collect ( ) ;
184+ names. sort ( ) ; names. dedup ( ) ;
185+
186+ for name in names {
187+ let va = * a. get ( & name) . unwrap_or ( & 0 ) ;
188+ let vb = * b. get ( & name) . unwrap_or ( & 0 ) ;
189+ if va == vb { continue ; }
190+
191+ let ia = if va == 0 {
192+ self . chunk . push_name ( & format ! ( "{}_{}" , name, vb) )
193+ } else {
194+ self . chunk . push_name ( & format ! ( "{}_{}" , name, va) )
195+ } ;
196+ let ib = if vb == 0 {
197+ self . chunk . push_name ( & format ! ( "{}_{}" , name, va) )
198+ } else {
199+ self . chunk . push_name ( & format ! ( "{}_{}" , name, vb) )
200+ } ;
201+
202+ let v = self . increment_version ( & name) ;
203+ let ix = self . chunk . push_name ( & format ! ( "{}_{}" , name, v) ) ;
204+
205+ self . chunk . phi_sources . push ( ( ia, ib) ) ;
206+ self . chunk . emit ( OpCode :: Phi , ix) ;
207+
208+ self . ssa_versions . insert ( name. clone ( ) , v) ;
188209 }
210+
189211 }
190212
191213 fn advance ( & mut self ) -> Token { self . tokens . next ( ) . unwrap ( ) }
@@ -265,6 +287,7 @@ impl<'src, I: Iterator<Item = Token>> Parser<'src, I> {
265287 self . advance ( ) ; // consume 'elif'
266288 self . chunk . emit ( OpCode :: Jump , 0 ) ;
267289 let jmp = self . chunk . instructions . len ( ) - 1 ;
290+ self . mid_block ( ) ;
268291 self . patch ( jf) ;
269292 self . if_body ( ) ; // recursivo SIN enter/commit
270293 self . patch ( jmp) ;
@@ -273,6 +296,7 @@ impl<'src, I: Iterator<Item = Token>> Parser<'src, I> {
273296 self . advance ( ) ;
274297 self . chunk . emit ( OpCode :: Jump , 0 ) ;
275298 let jmp = self . chunk . instructions . len ( ) - 1 ;
299+ self . mid_block ( ) ;
276300 self . patch ( jf) ;
277301 self . eat ( TokenType :: Colon ) ;
278302 self . compile_block ( ) ; // ← usa block aquí
@@ -282,6 +306,16 @@ impl<'src, I: Iterator<Item = Token>> Parser<'src, I> {
282306 }
283307 }
284308
309+ fn peek ( & mut self ) -> Option < TokenType > {
310+ loop {
311+ match self . tokens . peek ( ) . map ( |t| t. kind . clone ( ) ) {
312+ Some ( TokenType :: Newline | TokenType :: Nl | TokenType :: Comment ) => { self . tokens . next ( ) ; }
313+ Some ( k) => return Some ( k) ,
314+ None => return None ,
315+ }
316+ }
317+ }
318+
285319 fn for_stmt ( & mut self ) {
286320 self . advance ( ) ;
287321 let var = { let t = self . advance ( ) ; self . lexeme ( & t) . to_string ( ) } ;
@@ -620,7 +654,7 @@ impl<'src, I: Iterator<Item = Token>> Parser<'src, I> {
620654 }
621655
622656 fn compile_body ( & mut self , params : & [ String ] ) -> SSAChunk {
623- let ( mut saved_chunk, saved_ver) = (
657+ let ( saved_chunk, saved_ver) = (
624658 std:: mem:: take ( & mut self . chunk ) ,
625659 std:: mem:: take ( & mut self . ssa_versions ) ,
626660 ) ;
@@ -632,7 +666,9 @@ impl<'src, I: Iterator<Item = Token>> Parser<'src, I> {
632666 self . compile_block ( ) ; // ← SOLO esto
633667
634668 let body = std:: mem:: take ( & mut self . chunk ) ;
669+
635670 ( self . chunk , self . ssa_versions ) = ( saved_chunk, saved_ver) ;
671+
636672 body
637673 }
638674
0 commit comments