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

Method compile_pattern_or

crates/codegen/src/compile.rs:6538–6648  ·  view source on GitHub ↗
(
        &mut self,
        p: &ast::PatternMatchOr,
        pc: &mut PatternContext,
    )

Source from the content-addressed store, hash-verified

6536 }
6537
6538 fn compile_pattern_or(
6539 &mut self,
6540 p: &ast::PatternMatchOr,
6541 pc: &mut PatternContext,
6542 ) -> CompileResult<()> {
6543 // Ensure the pattern is a MatchOr.
6544 let end = self.new_block(); // Create a new jump target label.
6545 let size = p.patterns.len();
6546 if size <= 1 {
6547 return Err(self.error(CodegenErrorType::SyntaxError(
6548 "MatchOr requires at least 2 patterns".to_owned(),
6549 )));
6550 }
6551
6552 // Save the current pattern context.
6553 let old_pc = pc.clone();
6554 // Simulate Py_INCREF on pc.stores by cloning it.
6555 pc.stores = pc.stores.clone();
6556 let mut control: Option<Vec<String>> = None; // Will hold the capture list of the first alternative.
6557
6558 // Process each alternative.
6559 for (i, alt) in p.patterns.iter().enumerate() {
6560 // Create a fresh empty store for this alternative.
6561 pc.stores = Vec::new();
6562 // An irrefutable subpattern must be last (if allowed).
6563 pc.allow_irrefutable = (i == size - 1) && old_pc.allow_irrefutable;
6564 // Reset failure targets and the on_top counter.
6565 pc.fail_pop.clear();
6566 pc.on_top = 0;
6567 // Emit a COPY(1) instruction before compiling the alternative.
6568 emit!(self, Instruction::Copy { i: 1 });
6569 self.compile_pattern(alt, pc)?;
6570
6571 let n_stores = pc.stores.len();
6572 if i == 0 {
6573 // Save the captured names from the first alternative.
6574 control = Some(pc.stores.clone());
6575 } else {
6576 let control_vec = control.as_ref().unwrap();
6577 if n_stores != control_vec.len() {
6578 return Err(self.error(CodegenErrorType::ConflictingNameBindPattern));
6579 } else if n_stores > 0 {
6580 // Check that the names occur in the same order.
6581 for i_control in (0..n_stores).rev() {
6582 let name = &control_vec[i_control];
6583 // Find the index of `name` in the current stores.
6584 let i_stores =
6585 pc.stores.iter().position(|n| n == name).ok_or_else(|| {
6586 self.error(CodegenErrorType::ConflictingNameBindPattern)
6587 })?;
6588 if i_control != i_stores {
6589 // The orders differ; we must reorder.
6590 assert!(i_stores < i_control, "expected i_stores < i_control");
6591 let rotations = i_stores + 1;
6592 // Rotate pc.stores: take a slice of the first `rotations` items...
6593 let rotated = pc.stores[0..rotations].to_vec();
6594 // Remove those elements.
6595 for _ in 0..rotations {

Callers 1

compile_patternMethod · 0.80

Calls 15

newFunction · 0.85
new_blockMethod · 0.80
compile_patternMethod · 0.80
ok_or_elseMethod · 0.80
to_vecMethod · 0.80
pattern_helper_rotateMethod · 0.80
jump_to_fail_popMethod · 0.80
switch_to_blockMethod · 0.80
to_stringMethod · 0.80
ErrClass · 0.50
SomeClass · 0.50

Tested by

no test coverage detected