◐ Shell
clean mode source ↗

Fix match mapping pattern by youknowone · Pull Request #6081 · RustPython/RustPython

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)
}