mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
DictUpdate instruction
This commit is contained in:
1 parent
33ea50c2e9
commit
d56fcd0774
3 files changed
+29
-13
No files matched your search
@@ -4398,7 +4398,7 @@ impl Compiler {
|
||||
|
||||
for item in unpacked {
|
||||
self.compile_expression(&item.value)?;
|
||||
emit!(self, Instruction::DictUpdate);
|
||||
emit!(self, Instruction::DictUpdate { index: 1 });
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -667,7 +667,9 @@ pub enum Instruction {
|
||||
BuildMapForCall {
|
||||
size: Arg<u32>,
|
||||
},
|
||||
DictUpdate,
|
||||
DictUpdate {
|
||||
index: Arg<u32>,
|
||||
},
|
||||
BuildSlice {
|
||||
/// whether build a slice with a third step argument
|
||||
step: Arg<bool>,
|
||||
@@ -1397,7 +1399,7 @@ impl Instruction {
|
||||
let nargs = size.get(arg);
|
||||
-(nargs as i32) + 1
|
||||
}
|
||||
DictUpdate => -1,
|
||||
DictUpdate { .. } => -1,
|
||||
BuildSlice { step } => -2 - (step.get(arg) as i32) + 1,
|
||||
ListAppend { .. } | SetAdd { .. } => -1,
|
||||
MapAdd { .. } => -2,
|
||||
@@ -1586,7 +1588,7 @@ impl Instruction {
|
||||
BuildSetFromTuples { size } => w!(BuildSetFromTuples, size),
|
||||
BuildMap { size } => w!(BuildMap, size),
|
||||
BuildMapForCall { size } => w!(BuildMapForCall, size),
|
||||
DictUpdate => w!(DictUpdate),
|
||||
DictUpdate { index } => w!(DictUpdate, index),
|
||||
BuildSlice { step } => w!(BuildSlice, step),
|
||||
ListAppend { i } => w!(ListAppend, i),
|
||||
SetAdd { i } => w!(SetAdd, i),
|
||||
|
||||
+23
-9
@@ -800,26 +800,40 @@ impl ExecutingFrame<'_> {
|
||||
bytecode::Instruction::BuildMapForCall { size } => {
|
||||
self.execute_build_map_for_call(vm, size.get(arg))
|
||||
}
|
||||
bytecode::Instruction::DictUpdate => {
|
||||
let other = self.pop_value();
|
||||
let dict = self
|
||||
.top_value()
|
||||
.downcast_ref::<PyDict>()
|
||||
.expect("exact dict expected");
|
||||
bytecode::Instruction::DictUpdate { index } => {
|
||||
// Stack before: [..., dict, ..., source] (source at TOS)
|
||||
// Stack after: [..., dict, ...] (source consumed)
|
||||
// The dict to update is at position TOS-i (before popping source)
|
||||
|
||||
let idx = index.get(arg);
|
||||
|
||||
// Pop the source from TOS
|
||||
let source = self.pop_value();
|
||||
|
||||
// Get the dict to update (it's now at TOS-(i-1) after popping source)
|
||||
let dict = if idx <= 1 {
|
||||
// DICT_UPDATE 0 or 1: dict is at TOS (after popping source)
|
||||
self.top_value()
|
||||
} else {
|
||||
// DICT_UPDATE n: dict is at TOS-(n-1)
|
||||
self.nth_value(idx - 1)
|
||||
};
|
||||
|
||||
let dict = dict.downcast_ref::<PyDict>().expect("exact dict expected");
|
||||
|
||||
// For dictionary unpacking {**x}, x must be a mapping
|
||||
// Check if the object has the mapping protocol (keys method)
|
||||
if vm
|
||||
.get_method(other.clone(), vm.ctx.intern_str("keys"))
|
||||
.get_method(source.clone(), vm.ctx.intern_str("keys"))
|
||||
.is_none()
|
||||
{
|
||||
return Err(vm.new_type_error(format!(
|
||||
"'{}' object is not a mapping",
|
||||
other.class().name()
|
||||
source.class().name()
|
||||
)));
|
||||
}
|
||||
|
||||
dict.merge_object(other, vm)?;
|
||||
dict.merge_object(source, vm)?;
|
||||
Ok(None)
|
||||
}
|
||||
bytecode::Instruction::BuildSlice { step } => {
|
||||
|
||||
Reference in new issue
Block a user