Emits bytecode for one pattern; appends case-fail jumps to `fail_jumps`; reloads subject from subj. */
(&mut self, subj: u16, fail_jumps: &mut Vec<usize>)
| 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>) { |
| 93 | // OR pattern: each alt gets a success-jump landing past all alts. |
| 94 | let mut alts: Vec<Vec<usize>> = Vec::new(); |
| 95 | let mut succ_jumps: Vec<usize> = Vec::new(); |
| 96 | |
| 97 | loop { |
| 98 | let mut this_alt_fails: Vec<usize> = Vec::new(); |
| 99 | self.parse_simple_pattern(subj, &mut this_alt_fails); |
| 100 | // On match: jump past remaining alts. |
| 101 | succ_jumps.push(self.emit_jump(OpCode::Jump)); |
| 102 | // On mismatch: redirect fails to next alt; only last alt propagates to case-fail. |
| 103 | alts.push(this_alt_fails); |
| 104 | if !matches!(self.peek(), Some(TokenType::Vbar)) { |
| 105 | break; |
| 106 | } |
| 107 | // Previous alt's fails land at next alt entry. |
| 108 | let here = self.chunk.instructions.len(); |
| 109 | for j in alts.last_mut().unwrap().drain(..) { |
| 110 | let target = here as u16; |
| 111 | self.patch_to(j, target); |
| 112 | } |
| 113 | self.advance(); // consume `|` |
| 114 | } |
| 115 | |
| 116 | // Last alt's fails become the case-fail exits. |
| 117 | if let Some(last) = alts.last_mut() { |
| 118 | fail_jumps.append(last); |
| 119 | } |
| 120 | |
| 121 | // All success jumps land here, past the OR. |
| 122 | for j in succ_jumps { self.patch(j); } |
| 123 | } |
| 124 | |
| 125 | /* Dispatches single pattern alternative by token: wildcard, capture (StoreName), or literal equality. */ |
| 126 | fn parse_simple_pattern(&mut self, subj: u16, fail_jumps: &mut Vec<usize>) { |
no test coverage detected