Interpreter: switch statement lowering#72
Conversation
Add AST lowering for switch: evaluate the scrutinee once into a register, emit a branch chain for each case, and jump to the default branch or past the statement when nothing matches. Match literal cases with Eq; match regex and typed-regex cases with Matches. Support default placed anywhere in the case list, including before later cases. Fixes uutils#70
Alonely0
left a comment
There was a problem hiding this comment.
At a first glance this looks great, but my head aches a bit too much for me to continue looking at a screen today, sorry. I'll push the review comments I have and try to do some more tomorrow.
| pub fn matches_regex(&self, pattern: &[u8]) -> bool { | ||
| let mut subject = Vec::with_capacity(self.string_size_hint()); | ||
| self.write_string(&mut subject); | ||
| let Ok(subject) = str::from_utf8(&subject) else { | ||
| return false; | ||
| }; | ||
| let Ok(pattern) = str::from_utf8(pattern) else { | ||
| return false; | ||
| }; | ||
| regex::Regex::new(pattern) | ||
| .ok() | ||
| .is_some_and(|re| re.is_match(subject)) | ||
| } | ||
|
|
There was a problem hiding this comment.
If only life were so simple. gawk has regex extensions, so we will probably have to build our own regex layer on top of regex-automata, or at the very least do a pre-processing pass. We can keep as-is this for now so it's testable, tho.
| case: &Atom<'_>, | ||
| case_ix: usize, | ||
| ) -> (Label, usize) { | ||
| let cmp = self.alloc_reg(); |
There was a problem hiding this comment.
Pretty sure we could reuse this destination register for all comparisons. Would it not be better to allocate it once in lower_switch and pass it as an argument?
|
|
||
| for (br_label, case_ix) in pending_branches { | ||
| self.bc.nth(br_label).set_then_label(case_labels[case_ix]); | ||
| self.bc.nth(br_label).set_label(Label(br_label.0 + 1)); |
There was a problem hiding this comment.
I think we should be able to set the else_label at the time of generation of each branch in emit_switch_case_match(). Notice this is just the position of the next instruction, which is known when it is emitted.
Add AST lowering for switch: evaluate the scrutinee once into a register, emit a branch chain for each case, and jump to the default branch or past the statement when nothing matches.
Match literal cases with Eq; match regex and typed-regex cases with Matches. Support default placed anywhere in the case list, including before later cases.
Fixes #70