add match splatted list opcode

This commit is contained in:
Scott Richmond 2025-06-19 11:54:26 -04:00
parent 647f3d4463
commit 4871dbd048
3 changed files with 16 additions and 13 deletions

View File

@ -42,6 +42,7 @@ pub enum Op {
PushTuple, PushTuple,
LoadTuple, LoadTuple,
MatchList, MatchList,
MatchSplattedList,
LoadList, LoadList,
PushList, PushList,
AppendList, AppendList,
@ -162,6 +163,7 @@ impl std::fmt::Display for Op {
PushTuple => "push_tuple", PushTuple => "push_tuple",
LoadTuple => "load_tuple", LoadTuple => "load_tuple",
MatchList => "match_list", MatchList => "match_list",
MatchSplattedList => "match_splatted_list",
LoadList => "load_list", LoadList => "load_list",
PushList => "push_list", PushList => "push_list",
AppendList => "append_list", AppendList => "append_list",
@ -260,9 +262,9 @@ impl Chunk {
println!("{i:04}: {:16} {next:03}: {value}", op.to_string()); println!("{i:04}: {:16} {next:03}: {value}", op.to_string());
*i += 1; *i += 1;
} }
PushBinding | MatchTuple | MatchList | MatchDict | LoadDictValue | PushTuple PushBinding | MatchTuple | MatchList | MatchSplattedList | MatchDict
| PushBox | MatchDepth | PopN | StoreAt | Call | SetUpvalue | GetUpvalue | Partial | LoadDictValue | PushTuple | PushBox | MatchDepth | PopN | StoreAt | Call
| MatchString | PushStringMatches => { | SetUpvalue | GetUpvalue | Partial | MatchString | PushStringMatches => {
let next = self.bytecode[*i + 1]; let next = self.bytecode[*i + 1];
println!("{i:04}: {:16} {next:03}", op.to_string()); println!("{i:04}: {:16} {next:03}", op.to_string());
*i += 1; *i += 1;
@ -778,7 +780,12 @@ impl<'a> Compiler<'a> {
self.match_depth = match_depth + members.len(); self.match_depth = match_depth + members.len();
} }
ListPattern(members) => { ListPattern(members) => {
self.emit_op(Op::MatchList); if let Some((Splattern(patt), _)) = members.last() {
self.emit_op(Op::MatchSplattedList)
} else {
self.emit_op(Op::MatchList);
}
// TODO: lists must be able to be longer than 256 elements; fix this
self.emit_byte(members.len()); self.emit_byte(members.len());
let before_load_tup_idx = self.stub_jump(Op::JumpIfNoMatch); let before_load_tup_idx = self.stub_jump(Op::JumpIfNoMatch);

View File

@ -75,14 +75,7 @@ pub fn run(src: &'static str) {
pub fn main() { pub fn main() {
env::set_var("RUST_BACKTRACE", "1"); env::set_var("RUST_BACKTRACE", "1");
let src = " let src = "
let foo = loop (1, 2, 3) with { let [] = []
(0, 0, 1) -> :done ";
(1, 2, 3) -> recur (4, 5, 6)
(4, 5, 6) -> recur (:foo, :bar, :baz)
(:foo, :bar, :baz) -> recur (0, 0, 0)
}
(foo, 42)
";
run(src); run(src);
} }

View File

@ -466,6 +466,9 @@ impl Vm {
}; };
self.ip += 2; self.ip += 2;
} }
MatchSplattedList => {
todo!()
}
LoadList => { LoadList => {
let idx = self.stack.len() - self.match_depth as usize - 1; let idx = self.stack.len() - self.match_depth as usize - 1;
let tuple = self.stack[idx].clone(); let tuple = self.stack[idx].clone();