MCPcopy Create free account
hub / github.com/dylan-sutton-chavez/edge-python / exec_call_method

Method exec_call_method

compiler/src/modules/vm/dispatch.rs:265–360  ·  view source on GitHub ↗

Resolve the receiver's method and call directly; args come from CallMethodArgs. */

(&mut self, attr_idx: u16, call_op: u16, chunk: &SSAChunk, slots: &mut [Val])

Source from the content-addressed store, hash-verified

263
264 /* Resolve the receiver's method and call directly; args come from CallMethodArgs. */
265 fn exec_call_method(&mut self, attr_idx: u16, call_op: u16, chunk: &SSAChunk, slots: &mut [Val]) -> Result<(), VmErr> {
266 let raw = call_op as usize;
267 let num_kw = (raw >> 8) & 0xFF;
268 let num_pos = raw & 0xFF;
269 let total = num_pos + 2 * num_kw;
270
271 let mut stack_items: Vec<Val> = (0..total).map(|_| self.pop()).collect::<Result<_, _>>()?;
272 stack_items.reverse();
273
274 let kw_flat: Vec<Val> = stack_items.split_off(num_pos);
275 let positional = stack_items;
276
277 let obj = self.pop()?;
278 let name = chunk.names.get(attr_idx as usize).ok_or(VmErr::Runtime("CallMethod: bad name index"))?.clone();
279
280 let lookup = match self.resolve_attr(obj, &name) {
281 Ok(l) => l,
282 Err(VmErr::Attribute(msg)) => {
283 // if `__getattr__` resolves the name to a callable, invoke it with the positional args.
284 if let Some(v) = self.try_getattr_fallback(obj, &name, chunk, slots)? {
285 self.push(v);
286 for a in &positional { self.push(*a); }
287 for a in &kw_flat { self.push(*a); }
288 let argc = positional.len() as u16;
289 let encoded = ((kw_flat.len() as u16 / 2) << 8) | argc;
290 return self.exec_call(encoded, chunk, slots);
291 }
292 return Err(VmErr::Attribute(msg));
293 }
294 Err(other) => return Err(other),
295 };
296 match lookup {
297 handlers::methods::AttrLookup::ModuleAttr(callee)
298 | handlers::methods::AttrLookup::ClassMember(callee) => {
299 // Direct call on the resolved value, no `self` prepended.
300 self.push(callee);
301 for a in &positional { self.push(*a); }
302 for a in &kw_flat { self.push(*a); }
303 let argc = positional.len() as u16;
304 let encoded = ((kw_flat.len() as u16 / 2) << 8) | argc;
305 self.exec_call(encoded, chunk, slots)
306 }
307 handlers::methods::AttrLookup::InstanceMethod { recv, func, class } => {
308 // Prepend `self`; kwargs aren't forwarded (preserved behaviour). `super()` reads the binding off `pending`.
309 self.pending.method_binding = Some((class, recv));
310 self.push(func);
311 self.push(recv);
312 for a in &positional { self.push(*a); }
313 let argc = (positional.len() + 1) as u16;
314 let encoded = ((kw_flat.len() as u16 / 2) << 8) | argc;
315 self.exec_call(encoded, chunk, slots)
316 }
317 handlers::methods::AttrLookup::BuiltinMethod(id) => {
318 // sort runs user __lt__, so it needs chunk/slots the builtin-method table can't carry.
319 if id.name() == "sort" { return self.exec_sort(obj, &positional, &kw_flat, chunk, slots); }
320 self.exec_bound_method(obj, id, &positional, &kw_flat)
321 }
322 handlers::methods::AttrLookup::InstanceField(field) => {

Callers 1

dispatchMethod · 0.80

Calls 13

cold_depthFunction · 0.85
resolve_attrMethod · 0.80
try_getattr_fallbackMethod · 0.80
pushMethod · 0.80
exec_callMethod · 0.80
exec_sortMethod · 0.80
exec_bound_methodMethod · 0.80
type_nameMethod · 0.80
popMethod · 0.45
getMethod · 0.45
lenMethod · 0.45
nameMethod · 0.45

Tested by

no test coverage detected