@@ -6,9 +6,9 @@ impl<'a> VM<'a> {
66
77 /* StoreName con back-propagación SSA a versiones previas. */
88
9- pub ( crate ) fn handle_store ( & mut self , operand : u16 , slots : & mut [ Option < Val > ] ) -> Result < ( ) , VmErr > {
9+ pub ( crate ) fn handle_store ( & mut self , operand : u16 , slots : & mut [ Val ] ) -> Result < ( ) , VmErr > {
1010 let v = self . pop ( ) ?;
11- slots[ operand as usize ] = Some ( v ) ;
11+ slots[ operand as usize ] = v ;
1212 Ok ( ( ) )
1313 }
1414
@@ -119,15 +119,15 @@ impl<'a> VM<'a> {
119119
120120 /* Side-effects and impurities: assert, del, global/nonlocal, import, type aliases, exception handling stubs and await/yield-from. */
121121
122- pub ( crate ) fn handle_side ( & mut self , op : OpCode , operand : u16 , slots : & mut [ Option < Val > ] ) -> Result < ( ) , VmErr > {
122+ pub ( crate ) fn handle_side ( & mut self , op : OpCode , operand : u16 , slots : & mut [ Val ] ) -> Result < ( ) , VmErr > {
123123 match op {
124124 OpCode :: Assert => {
125125 let v = self . pop ( ) ?;
126126 if !self . truthy ( v) { return Err ( VmErr :: Runtime ( "AssertionError" ) ) ; }
127127 }
128128 OpCode :: Del => {
129129 let slot = operand as usize ;
130- if slot < slots. len ( ) { slots[ slot] = None ; }
130+ if slot < slots. len ( ) { slots[ slot] = Val :: undef ( ) ; }
131131 }
132132 OpCode :: Global | OpCode :: Nonlocal => self . mark_impure ( ) ,
133133 OpCode :: TypeAlias => { self . pop ( ) ?; }
@@ -140,59 +140,59 @@ impl<'a> VM<'a> {
140140 let msg = self . display ( exc) ;
141141 return Err ( VmErr :: Raised ( msg) ) ;
142142 }
143- OpCode :: Await => {
144- // If awaiting a coroutine, run it to completion or yield
145- let val = self . pop ( ) ?;
146- if val. is_heap ( ) && matches ! ( self . heap. get( val) , HeapObj :: Coroutine ( ..) ) {
147- // Resume the inner coroutine
148- self . push ( val) ;
149- // Use Call dispatch with 0 args - callee is on stack
150- let callee = val;
151- if let HeapObj :: Coroutine ( ip, saved_slots, saved_stack, fi, saved_iters) = self . heap . get ( callee) {
152- let ( ip, fi) = ( * ip, * fi) ;
153- let mut fn_slots = saved_slots. clone ( ) ;
154- let saved_stack_len = self . stack . len ( ) ;
155- let saved_iter_len = self . iter_stack . len ( ) ;
156- self . stack . extend_from_slice ( & saved_stack. clone ( ) ) ;
157- self . iter_stack . extend ( saved_iters. clone ( ) ) ;
158- let saved_yielded = self . yielded ;
159- self . yielded = false ;
160- self . depth += 1 ;
161- let ( _, body, _, _) = self . functions [ fi] ;
162- let result = self . exec_from ( body, & mut fn_slots, ip) ;
163- self . depth -= 1 ;
164- let result = result?;
165- if self . yielded {
166- // Inner coroutine yielded - propagate yield upward
167- self . yielded = false ;
168- let resume_ip = self . resume_ip ;
169- let remaining = self . stack . split_off ( saved_stack_len) ;
170- let coro_iters: Vec < super :: super :: types:: IterFrame > = self . iter_stack . drain ( saved_iter_len..) . collect ( ) ;
171- if let HeapObj :: Coroutine ( sip, ss, sst, _, si) = self . heap . get_mut ( callee) {
172- * sip = resume_ip;
173- * ss = fn_slots;
174- * sst = remaining;
175- * si = coro_iters;
176- }
177- // Propagate: yield the value from this coroutine too
178- self . push ( result) ;
179- self . yielded = true ;
180- } else {
181- // Inner coroutine finished - push its return value
182- self . stack . truncate ( saved_stack_len) ;
183- self . iter_stack . truncate ( saved_iter_len) ;
184- self . yielded = saved_yielded;
185- self . push ( result) ;
186- }
187- } else {
188- // Not a coroutine anymore (shouldn't happen)
189- self . push ( val) ;
190- }
191- } else {
192- // Not a coroutine - just push the value (sync call already resolved)
193- self . push ( val) ;
194- }
195- }
143+ OpCode :: Await => {
144+ // If awaiting a coroutine, run it to completion or yield
145+ let val = self . pop ( ) ?;
146+ if val. is_heap ( ) && matches ! ( self . heap. get( val) , HeapObj :: Coroutine ( ..) ) {
147+ // Resume the inner coroutine
148+ self . push ( val) ;
149+ // Use Call dispatch with 0 args - callee is on stack
150+ let callee = val;
151+ if let HeapObj :: Coroutine ( ip, saved_slots, saved_stack, fi, saved_iters) = self . heap . get ( callee) {
152+ let ( ip, fi) = ( * ip, * fi) ;
153+ let mut fn_slots = saved_slots. clone ( ) ;
154+ let saved_stack_len = self . stack . len ( ) ;
155+ let saved_iter_len = self . iter_stack . len ( ) ;
156+ self . stack . extend_from_slice ( & saved_stack. clone ( ) ) ;
157+ self . iter_stack . extend ( saved_iters. clone ( ) ) ;
158+ let saved_yielded = self . yielded ;
159+ self . yielded = false ;
160+ self . depth += 1 ;
161+ let ( _, body, _, _) = self . functions [ fi] ;
162+ let result = self . exec_from ( body, & mut fn_slots, ip) ;
163+ self . depth -= 1 ;
164+ let result = result?;
165+ if self . yielded {
166+ // Inner coroutine yielded - propagate yield upward
167+ self . yielded = false ;
168+ let resume_ip = self . resume_ip ;
169+ let remaining = self . stack . split_off ( saved_stack_len) ;
170+ let coro_iters: Vec < super :: super :: types:: IterFrame > = self . iter_stack . drain ( saved_iter_len..) . collect ( ) ;
171+ if let HeapObj :: Coroutine ( sip, ss, sst, _, si) = self . heap . get_mut ( callee) {
172+ * sip = resume_ip;
173+ * ss = fn_slots;
174+ * sst = remaining;
175+ * si = coro_iters;
176+ }
177+ // Propagate: yield the value from this coroutine too
178+ self . push ( result) ;
179+ self . yielded = true ;
180+ } else {
181+ // Inner coroutine finished - push its return value
182+ self . stack . truncate ( saved_stack_len) ;
183+ self . iter_stack . truncate ( saved_iter_len) ;
184+ self . yielded = saved_yielded;
185+ self . push ( result) ;
186+ }
187+ } else {
188+ // Not a coroutine anymore (shouldn't happen)
189+ self . push ( val) ;
190+ }
191+ } else {
192+ // Not a coroutine - just push the value (sync call already resolved)
193+ self . push ( val) ;
194+ }
195+ }
196196 OpCode :: YieldFrom => { }
197197 _ => unreachable ! ( "non-side opcode in handle_side" ) ,
198198 }
0 commit comments