diff --git a/crates/codegen/src/compile.rs b/crates/codegen/src/compile.rs index b2dc10cda6c..4a4f17edcfa 100644 --- a/crates/codegen/src/compile.rs +++ b/crates/codegen/src/compile.rs @@ -36,7 +36,7 @@ use rustpython_compiler_core::{ Mode, OneIndexed, PositionEncoding, SourceFile, SourceLocation, bytecode::{ self, Arg as OpArgMarker, BinaryOperator, CodeObject, ComparisonOperator, ConstantData, - Instruction, OpArg, OpArgType, UnpackExArgs, + Instruction, Invert, OpArg, OpArgType, UnpackExArgs, }, }; use rustpython_wtf8::Wtf8Buf; @@ -2034,20 +2034,7 @@ impl Compiler { // Check exception type: self.compile_expression(exc_type)?; - emit!( - self, - Instruction::TestOperation { - op: bytecode::TestOperator::ExceptionMatch, - } - ); - - // We cannot handle this exception type: - emit!( - self, - Instruction::PopJumpIfFalse { - target: next_handler, - } - ); + emit!(self, Instruction::JumpIfNotExcMatch(next_handler)); // We have a match, store in name (except x as y) if let Some(alias) = name { @@ -3477,12 +3464,7 @@ impl Compiler { // 4. Load None. self.emit_load_const(ConstantData::None); // 5. Compare with IS_OP 1. - emit!( - self, - Instruction::TestOperation { - op: bytecode::TestOperator::IsNot - } - ); + emit!(self, Instruction::IsOp(Invert::Yes)); // At this point the TOS is a tuple of (nargs + n_attrs) attributes (or None). pc.on_top += 1; @@ -3648,12 +3630,8 @@ impl Compiler { // Check if copy is None (consumes the copy like POP_JUMP_IF_NONE) self.emit_load_const(ConstantData::None); - emit!( - self, - Instruction::TestOperation { - op: bytecode::TestOperator::IsNot - } - ); + emit!(self, Instruction::IsOp(Invert::Yes)); + // Stack: [subject, keys_tuple, values_tuple, bool] self.jump_to_fail_pop(pc, JumpOp::PopJumpIfFalse)?; // Stack: [subject, keys_tuple, values_tuple] @@ -3948,12 +3926,7 @@ impl Compiler { Singleton::True => ConstantData::Boolean { value: true }, }); // Compare using the "Is" operator. - emit!( - self, - Instruction::TestOperation { - op: bytecode::TestOperator::Is - } - ); + emit!(self, Instruction::IsOp(Invert::No)); // Jump to the failure label if the comparison is false. self.jump_to_fail_pop(pc, JumpOp::PopJumpIfFalse)?; Ok(()) @@ -4082,7 +4055,6 @@ impl Compiler { let (last_val, mid_exprs) = exprs.split_last().unwrap(); use bytecode::ComparisonOperator::*; - use bytecode::TestOperator::*; let compile_cmpop = |c: &mut Self, op: &CmpOp| match op { CmpOp::Eq => emit!(c, Instruction::CompareOperation { op: Equal }), CmpOp::NotEq => emit!(c, Instruction::CompareOperation { op: NotEqual }), @@ -4092,10 +4064,10 @@ impl Compiler { CmpOp::GtE => { emit!(c, Instruction::CompareOperation { op: GreaterOrEqual }) } - CmpOp::In => emit!(c, Instruction::TestOperation { op: In }), - CmpOp::NotIn => emit!(c, Instruction::TestOperation { op: NotIn }), - CmpOp::Is => emit!(c, Instruction::TestOperation { op: Is }), - CmpOp::IsNot => emit!(c, Instruction::TestOperation { op: IsNot }), + CmpOp::In => emit!(c, Instruction::ContainsOp(Invert::No)), + CmpOp::NotIn => emit!(c, Instruction::ContainsOp(Invert::Yes)), + CmpOp::Is => emit!(c, Instruction::IsOp(Invert::No)), + CmpOp::IsNot => emit!(c, Instruction::IsOp(Invert::Yes)), }; // a == b == c == d diff --git a/crates/codegen/src/snapshots/rustpython_codegen__compile__tests__nested_double_async_with.snap b/crates/codegen/src/snapshots/rustpython_codegen__compile__tests__nested_double_async_with.snap index dc624c7b6a1..3042e35f179 100644 --- a/crates/codegen/src/snapshots/rustpython_codegen__compile__tests__nested_double_async_with.snap +++ b/crates/codegen/src/snapshots/rustpython_codegen__compile__tests__nested_double_async_with.snap @@ -1,5 +1,5 @@ --- -source: compiler/codegen/src/compile.rs +source: crates/codegen/src/compile.rs expression: "compile_exec(\"\\\nfor stop_exc in (StopIteration('spam'), StopAsyncIteration('ham')):\n with self.subTest(type=type(stop_exc)):\n try:\n async with egg():\n raise stop_exc\n except Exception as ex:\n self.assertIs(ex, stop_exc)\n else:\n self.fail(f'{stop_exc} was suppressed')\n\")" --- 1 0 SetupLoop @@ -11,7 +11,7 @@ expression: "compile_exec(\"\\\nfor stop_exc in (StopIteration('spam'), StopAsyn 6 CallFunctionPositional(1) 7 BuildTuple (2) 8 GetIter - >> 9 ForIter (73) + >> 9 ForIter (72) 10 StoreLocal (2, stop_exc) 2 11 LoadNameAny (3, self) @@ -21,7 +21,7 @@ expression: "compile_exec(\"\\\nfor stop_exc in (StopIteration('spam'), StopAsyn 15 CallFunctionPositional(1) 16 LoadConst (("type")) 17 CallMethodKeyword (1) - 18 SetupWith (70) + 18 SetupWith (69) 19 Pop 3 20 SetupExcept (42) @@ -48,41 +48,40 @@ expression: "compile_exec(\"\\\nfor stop_exc in (StopIteration('spam'), StopAsyn 38 Resume (3) 39 WithCleanupFinish 40 PopBlock - 41 Jump (59) + 41 Jump (58) >> 42 CopyItem (1) 6 43 LoadNameAny (7, Exception) - 44 TestOperation (ExceptionMatch) - 45 PopJumpIfFalse (58) - 46 StoreLocal (8, ex) + 44 JUMP_IF_NOT_EXC_MATCH(57) + 45 StoreLocal (8, ex) - 7 47 LoadNameAny (3, self) - 48 LoadMethod (9, assertIs) - 49 LoadNameAny (8, ex) - 50 LoadNameAny (2, stop_exc) - 51 CallMethodPositional (2) - 52 Pop - 53 PopException - 54 LoadConst (None) - 55 StoreLocal (8, ex) - 56 DeleteLocal (8, ex) - 57 Jump (68) - >> 58 Raise (Reraise) + 7 46 LoadNameAny (3, self) + 47 LoadMethod (9, assertIs) + 48 LoadNameAny (8, ex) + 49 LoadNameAny (2, stop_exc) + 50 CallMethodPositional (2) + 51 Pop + 52 PopException + 53 LoadConst (None) + 54 StoreLocal (8, ex) + 55 DeleteLocal (8, ex) + 56 Jump (67) + >> 57 Raise (Reraise) - 9 >> 59 LoadNameAny (3, self) - 60 LoadMethod (10, fail) - 61 LoadConst ("") - 62 LoadNameAny (2, stop_exc) - 63 FormatValue (None) - 64 LoadConst (" was suppressed") - 65 BuildString (2) - 66 CallMethodPositional (1) - 67 Pop + 9 >> 58 LoadNameAny (3, self) + 59 LoadMethod (10, fail) + 60 LoadConst ("") + 61 LoadNameAny (2, stop_exc) + 62 FormatValue (None) + 63 LoadConst (" was suppressed") + 64 BuildString (2) + 65 CallMethodPositional (1) + 66 Pop - 2 >> 68 PopBlock - 69 EnterFinally - >> 70 WithCleanupStart - 71 WithCleanupFinish - 72 Jump (9) - >> 73 PopBlock - 74 ReturnConst (None) + 2 >> 67 PopBlock + 68 EnterFinally + >> 69 WithCleanupStart + 70 WithCleanupFinish + 71 Jump (9) + >> 72 PopBlock + 73 ReturnConst (None) diff --git a/crates/compiler-core/src/bytecode.rs b/crates/compiler-core/src/bytecode.rs index fe28517cda8..144054860e4 100644 --- a/crates/compiler-core/src/bytecode.rs +++ b/crates/compiler-core/src/bytecode.rs @@ -577,6 +577,10 @@ pub enum Instruction { Subscript, StoreSubscript, DeleteSubscript, + /// Performs `is` comparison, or `is not` if `invert` is 1. + IsOp(Arg), + /// Performs `in` comparison, or `not in` if `invert` is 1. + ContainsOp(Arg), StoreAttr { idx: Arg, }, @@ -600,9 +604,6 @@ pub enum Instruction { LoadAttr { idx: Arg, }, - TestOperation { - op: Arg, - }, CompareOperation { op: Arg, }, @@ -628,6 +629,10 @@ pub enum Instruction { Break { target: Arg