Fix augassign double-loading the container of the target

This commit is contained in:
Noa 2022-03-10 13:27:38 -06:00
parent d9653b4895
commit e5eb2739b7

View file

@ -763,14 +763,7 @@ impl Compiler {
self.compile_store(target)?;
}
}
AugAssign { target, op, value } => {
self.compile_expression(target)?;
self.compile_expression(value)?;
// Perform operation:
self.compile_op(op, true);
self.compile_store(target)?;
}
AugAssign { target, op, value } => self.compile_augassign(target, op, value)?,
AnnAssign {
target,
annotation,
@ -1652,6 +1645,66 @@ impl Compiler {
Ok(())
}
fn compile_augassign(
&mut self,
target: &ast::Expr,
op: &ast::Operator,
value: &ast::Expr,
) -> CompileResult<()> {
enum AugAssignKind<'a> {
Name { id: &'a str },
Subscript,
Attr { idx: bytecode::NameIdx },
}
let kind = match &target.node {
ast::ExprKind::Name { id, .. } => {
self.compile_name(id, NameUsage::Load)?;
AugAssignKind::Name { id }
}
ast::ExprKind::Subscript { value, slice, .. } => {
self.compile_expression(value)?;
self.compile_expression(slice)?;
self.emit(Instruction::Duplicate2);
self.emit(Instruction::Subscript);
AugAssignKind::Subscript
}
ast::ExprKind::Attribute { value, attr, .. } => {
self.check_forbidden_name(attr, NameUsage::Store)?;
self.compile_expression(value)?;
self.emit(Instruction::Duplicate);
let idx = self.name(attr);
self.emit(Instruction::LoadAttr { idx });
AugAssignKind::Attr { idx }
}
_ => {
return Err(self.error(CompileErrorType::Assign(target.node.name())));
}
};
self.compile_expression(value)?;
self.compile_op(op, true);
match kind {
AugAssignKind::Name { id } => {
// stack: RESULT
self.compile_name(id, NameUsage::Store)?;
}
AugAssignKind::Subscript => {
// stack: CONTAINER SLICE RESULT
self.emit(Instruction::Rotate { amount: 3 });
self.emit(Instruction::StoreSubscript);
}
AugAssignKind::Attr { idx } => {
// stack: CONTAINER RESULT
self.emit(Instruction::Rotate { amount: 2 });
self.emit(Instruction::StoreAttr { idx });
}
}
Ok(())
}
fn compile_op(&mut self, op: &ast::Operator, inplace: bool) {
let op = match op {
ast::Operator::Add => bytecode::BinaryOperator::Add,