match/case: literals, captures, wildcards, OR, guards, sequences; emits subject-load + pattern + guard + Jump-end. */
(&mut self)
| 51 | |
| 52 | /* match/case: literals, captures, wildcards, OR, guards, sequences; emits subject-load + pattern + guard + Jump-end. */ |
| 53 | pub(super) fn match_stmt(&mut self) { |
| 54 | self.advance(); |
| 55 | self.expr(); |
| 56 | |
| 57 | let ver = self.increment_version(super::SSA_TMP_MATCH); |
| 58 | let subj = self.chunk.push_name(&s!(str super::SSA_TMP_MATCH, int ver)); |
| 59 | self.chunk.emit(OpCode::StoreName, subj); |
| 60 | |
| 61 | self.eat(TokenType::Colon); |
| 62 | self.eat_if(TokenType::Indent); |
| 63 | |
| 64 | let mut end_jumps = Vec::new(); |
| 65 | |
| 66 | while matches!(self.peek(), Some(TokenType::Case)) { |
| 67 | self.advance(); |
| 68 | |
| 69 | let mut fail_jumps: Vec<usize> = Vec::new(); |
| 70 | self.parse_pattern(subj, &mut fail_jumps); |
| 71 | |
| 72 | // Guard fail joins pattern fails; both land at the next case. |
| 73 | if self.eat_if(TokenType::If) { |
| 74 | self.expr(); |
| 75 | fail_jumps.push(self.emit_jump(OpCode::JumpIfFalse)); |
| 76 | } |
| 77 | |
| 78 | self.eat(TokenType::Colon); |
| 79 | self.compile_block(); |
| 80 | |
| 81 | end_jumps.push(self.emit_jump(OpCode::Jump)); |
| 82 | |
| 83 | for j in fail_jumps { self.patch(j); } |
| 84 | } |
| 85 | |
| 86 | self.eat_if(TokenType::Dedent); |
| 87 | |
| 88 | for pos in end_jumps { self.patch(pos); } |
| 89 | } |
| 90 | |
| 91 | /* Emits bytecode for one pattern; appends case-fail jumps to `fail_jumps`; reloads subject from subj. */ |
| 92 | pub(super) fn parse_pattern(&mut self, subj: u16, fail_jumps: &mut Vec<usize>) { |
no test coverage detected