|
bytecode::Instruction::MatchKeys => { |
|
// Typically we pop a sequence of keys first |
|
let _keys = self.pop_value(); |
|
// Pop keys tuple and subject |
|
let keys_tuple = self.pop_value(); |
|
let subject = self.pop_value(); |
|
|
|
// Check if subject is a dict (or mapping) and all keys match |
|
if let Ok(_dict) = subject.downcast::<PyDict>() { |
|
// Example: gather the values corresponding to keys |
|
// If keys match, push the matched values & success |
|
self.push_value(vm.ctx.new_bool(true).into()); |
|
// Push the subject back first |
|
self.push_value(subject.clone()); |
|
|
|
// Check if subject is a mapping and extract values for keys |
|
if PyMapping::check(&subject) { |
|
let keys = keys_tuple.downcast_ref::<PyTuple>().unwrap(); |
|
let mut values = Vec::new(); |
|
let mut all_match = true; |
|
|
|
for key in keys { |
|
match subject.get_item(key.as_object(), vm) { |
|
Ok(value) => values.push(value), |
|
Err(_) => { |
|
all_match = false; |
|
break; |
|
} |
|
} |
|
} |
|
|
|
if all_match { |
|
// Push keys_or_none (the original keys) and values_or_none |
|
// Keys should remain as they were for potential **rest handling |
|
self.push_value(keys_tuple); // keys_or_none |
|
self.push_value(vm.ctx.new_tuple(values).into()); // values_or_none |
|
} else { |
|
// No match - push None twice |
|
self.push_value(vm.ctx.none()); |
|
self.push_value(vm.ctx.none()); |
|
} |
|
} else { |
|
// Push a placeholder to indicate no match |
|
self.push_value(vm.ctx.new_bool(false).into()); |
|
// Not a mapping - push None twice |
|
self.push_value(vm.ctx.none()); |
|
self.push_value(vm.ctx.none()); |
|
} |
|
Ok(None) |
|
} |
|
bytecode::Instruction::MatchKeys => { |
|
- // Pop keys tuple and subject |
|
- let keys_tuple = self.pop_value(); |
|
+ let keys_tuple = self.pop_value(); |
|
let subject = self.pop_value(); |
|
|
|
- // Push the subject back first |
|
self.push_value(subject.clone()); |
|
|
|
- // Check if subject is a mapping and extract values for keys |
|
if PyMapping::check(&subject) { |
|
- let keys = keys_tuple.downcast_ref::<PyTuple>().unwrap(); |
|
+ let keys = keys_tuple.downcast_ref::<PyTuple>() |
|
+ .ok_or_else(|| vm.new_runtime_error("MatchKeys expects tuple of keys"))?; |
|
let mut values = Vec::new(); |
|
let mut all_match = true; |
|
|
|
for key in keys { |
|
match subject.get_item(key.as_object(), vm) { |
|
Ok(value) => values.push(value), |
|
Err(_) => { |
|
all_match = false; |
|
break; |
|
} |
|
} |
|
} |
|
|
|
if all_match { |
|
- self.push_value(keys_tuple); // keys_or_none |
|
- self.push_value(vm.ctx.new_tuple(values).into()); // values_or_none |
|
+ self.push_value(keys_tuple); |
|
+ self.push_value(vm.ctx.new_tuple(values).into()); |
|
} else { |
|
- // No match - push None twice |
|
self.push_value(vm.ctx.none()); |
|
self.push_value(vm.ctx.none()); |
|
} |
|
} else { |
|
- // Not a mapping - push None twice |
|
self.push_value(vm.ctx.none()); |
|
self.push_value(vm.ctx.none()); |
|
} |
|
Ok(None) |
|
} |