MCPcopy Index your code
hub / github.com/RustPython/RustPython / compile_compare

Method compile_compare

crates/codegen/src/compile.rs:6941–6996  ·  view source on GitHub ↗

Compile a chained comparison. ```py a == b == c == d ``` Will compile into (pseudo code): ```py result = a == b if result: result = b == c if result: result = c == d ``` # See Also - [CPython `compiler_compare`](https://github.com/python/cpython/blob/627894459a84be3488a1789919679c997056a03c/Python/compile.c#L4678-L4717)

(
        &mut self,
        left: &ast::Expr,
        ops: &[ast::CmpOp],
        comparators: &[ast::Expr],
    )

Source from the content-addressed store, hash-verified

6939 /// # See Also
6940 /// - [CPython `compiler_compare`](https://github.com/python/cpython/blob/627894459a84be3488a1789919679c997056a03c/Python/compile.c#L4678-L4717)
6941 fn compile_compare(
6942 &mut self,
6943 left: &ast::Expr,
6944 ops: &[ast::CmpOp],
6945 comparators: &[ast::Expr],
6946 ) -> CompileResult<()> {
6947 // Save the full Compare expression range for COMPARE_OP positions
6948 let compare_range = self.current_source_range;
6949 let (last_op, mid_ops) = ops.split_last().unwrap();
6950 let (last_comparator, mid_comparators) = comparators.split_last().unwrap();
6951
6952 // initialize lhs outside of loop
6953 self.compile_expression(left)?;
6954
6955 if mid_comparators.is_empty() {
6956 self.compile_expression(last_comparator)?;
6957 self.set_source_range(compare_range);
6958 self.compile_addcompare(last_op);
6959
6960 return Ok(());
6961 }
6962
6963 let cleanup = self.new_block();
6964
6965 // for all comparisons except the last (as the last one doesn't need a conditional jump)
6966 for (op, comparator) in mid_ops.iter().zip(mid_comparators) {
6967 self.compile_expression(comparator)?;
6968
6969 // store rhs for the next comparison in chain
6970 self.set_source_range(compare_range);
6971 emit!(self, Instruction::Swap { i: 2 });
6972 emit!(self, Instruction::Copy { i: 2 });
6973
6974 self.compile_addcompare(op);
6975
6976 // if comparison result is false, we break with this value; if true, try the next one.
6977 emit!(self, Instruction::Copy { i: 1 });
6978 emit!(self, Instruction::PopJumpIfFalse { delta: cleanup });
6979 emit!(self, Instruction::PopTop);
6980 }
6981
6982 self.compile_expression(last_comparator)?;
6983 self.set_source_range(compare_range);
6984 self.compile_addcompare(last_op);
6985
6986 let end = self.new_block();
6987 emit!(self, PseudoInstruction::Jump { delta: end });
6988
6989 // early exit left us with stack: `rhs, comparison_result`. We need to clean up rhs.
6990 self.switch_to_block(cleanup);
6991 emit!(self, Instruction::Swap { i: 2 });
6992 emit!(self, Instruction::PopTop);
6993
6994 self.switch_to_block(end);
6995 Ok(())
6996 }
6997
6998 fn compile_jump_if_compare(

Callers 1

compile_expressionMethod · 0.80

Calls 8

compile_expressionMethod · 0.80
set_source_rangeMethod · 0.80
compile_addcompareMethod · 0.80
new_blockMethod · 0.80
switch_to_blockMethod · 0.80
unwrapMethod · 0.45
is_emptyMethod · 0.45
iterMethod · 0.45

Tested by

no test coverage detected