(&mut self, vm: &VirtualMachine, oparg: LoadSuperAttr)
| 9249 | } |
| 9250 | |
| 9251 | fn load_super_attr(&mut self, vm: &VirtualMachine, oparg: LoadSuperAttr) -> FrameResult { |
| 9252 | let attr_name = self.code.names[oparg.name_idx() as usize]; |
| 9253 | |
| 9254 | // Stack layout (bottom to top): [super, class, self] |
| 9255 | // Pop in LIFO order: self, class, super |
| 9256 | let self_obj = self.pop_value(); |
| 9257 | let class = self.pop_value(); |
| 9258 | let global_super = self.pop_value(); |
| 9259 | |
| 9260 | // Create super object - pass args based on has_class flag |
| 9261 | // When super is shadowed, has_class=false means call with 0 args |
| 9262 | let super_obj = if oparg.has_class() { |
| 9263 | global_super.call((class.clone(), self_obj.clone()), vm)? |
| 9264 | } else { |
| 9265 | global_super.call((), vm)? |
| 9266 | }; |
| 9267 | |
| 9268 | if oparg.is_load_method() { |
| 9269 | // Method load: push [method, self_or_null] |
| 9270 | let method = PyMethod::get(super_obj, attr_name, vm)?; |
| 9271 | match method { |
| 9272 | PyMethod::Function { target: _, func } => { |
| 9273 | self.push_value(func); |
| 9274 | self.push_value(self_obj); |
| 9275 | } |
| 9276 | PyMethod::Attribute(val) => { |
| 9277 | self.push_value(val); |
| 9278 | self.push_null(); |
| 9279 | } |
| 9280 | } |
| 9281 | } else { |
| 9282 | // Regular attribute access |
| 9283 | let obj = super_obj.get_attr(attr_name, vm)?; |
| 9284 | self.push_value(obj); |
| 9285 | } |
| 9286 | Ok(None) |
| 9287 | } |
| 9288 | |
| 9289 | fn store_attr(&mut self, vm: &VirtualMachine, attr: bytecode::NameIdx) -> FrameResult { |
| 9290 | let attr_name = self.code.names[attr as usize]; |
no test coverage detected