(
&mut self,
p: &ast::PatternMatchSequence,
pc: &mut PatternContext,
)
| 6648 | } |
| 6649 | |
| 6650 | fn compile_pattern_sequence( |
| 6651 | &mut self, |
| 6652 | p: &ast::PatternMatchSequence, |
| 6653 | pc: &mut PatternContext, |
| 6654 | ) -> CompileResult<()> { |
| 6655 | // Ensure the pattern is a MatchSequence. |
| 6656 | let patterns = &p.patterns; // a slice of ast::Pattern |
| 6657 | let size = patterns.len(); |
| 6658 | let mut star: Option<usize> = None; |
| 6659 | let mut only_wildcard = true; |
| 6660 | let mut star_wildcard = false; |
| 6661 | |
| 6662 | // Find a starred pattern, if it exists. There may be at most one. |
| 6663 | for (i, pattern) in patterns.iter().enumerate() { |
| 6664 | if pattern.is_match_star() { |
| 6665 | if star.is_some() { |
| 6666 | // TODO: Fix error msg |
| 6667 | return Err(self.error(CodegenErrorType::MultipleStarArgs)); |
| 6668 | } |
| 6669 | // star wildcard check |
| 6670 | star_wildcard = pattern |
| 6671 | .as_match_star() |
| 6672 | .map(|m| m.name.is_none()) |
| 6673 | .unwrap_or(false); |
| 6674 | only_wildcard &= star_wildcard; |
| 6675 | star = Some(i); |
| 6676 | continue; |
| 6677 | } |
| 6678 | // wildcard check |
| 6679 | only_wildcard &= pattern |
| 6680 | .as_match_as() |
| 6681 | .map(|m| m.name.is_none()) |
| 6682 | .unwrap_or(false); |
| 6683 | } |
| 6684 | |
| 6685 | // Keep the subject on top during the sequence and length checks. |
| 6686 | pc.on_top += 1; |
| 6687 | emit!(self, Instruction::MatchSequence); |
| 6688 | self.jump_to_fail_pop(pc, JumpOp::PopJumpIfFalse)?; |
| 6689 | |
| 6690 | if star.is_none() { |
| 6691 | // No star: len(subject) == size |
| 6692 | emit!(self, Instruction::GetLen); |
| 6693 | self.emit_load_const(ConstantData::Integer { value: size.into() }); |
| 6694 | emit!( |
| 6695 | self, |
| 6696 | Instruction::CompareOp { |
| 6697 | opname: ComparisonOperator::Equal |
| 6698 | } |
| 6699 | ); |
| 6700 | self.jump_to_fail_pop(pc, JumpOp::PopJumpIfFalse)?; |
| 6701 | } else if size > 1 { |
| 6702 | // Star exists: len(subject) >= size - 1 |
| 6703 | emit!(self, Instruction::GetLen); |
| 6704 | self.emit_load_const(ConstantData::Integer { |
| 6705 | value: (size - 1).into(), |
| 6706 | }); |
| 6707 | emit!( |
no test coverage detected