first stab at splatted lists

This commit is contained in:
Scott Richmond 2025-06-19 12:06:47 -04:00
parent 4871dbd048
commit 2b95094eca
2 changed files with 30 additions and 7 deletions

View File

@ -44,6 +44,7 @@ pub enum Op {
MatchList,
MatchSplattedList,
LoadList,
LoadSplattedList,
PushList,
AppendList,
ConcatList,
@ -165,6 +166,7 @@ impl std::fmt::Display for Op {
MatchList => "match_list",
MatchSplattedList => "match_splatted_list",
LoadList => "load_list",
LoadSplattedList => "load_splatted_list",
PushList => "push_list",
AppendList => "append_list",
ConcatList => "concat_list",
@ -262,9 +264,9 @@ impl Chunk {
println!("{i:04}: {:16} {next:03}: {value}", op.to_string());
*i += 1;
}
PushBinding | MatchTuple | MatchList | MatchSplattedList | MatchDict
| LoadDictValue | PushTuple | PushBox | MatchDepth | PopN | StoreAt | Call
| SetUpvalue | GetUpvalue | Partial | MatchString | PushStringMatches => {
PushBinding | MatchTuple | MatchList | MatchSplattedList | LoadSplattedList
| MatchDict | LoadDictValue | PushTuple | PushBox | MatchDepth | PopN | StoreAt
| Call | SetUpvalue | GetUpvalue | Partial | MatchString | PushStringMatches => {
let next = self.bytecode[*i + 1];
println!("{i:04}: {:16} {next:03}", op.to_string());
*i += 1;
@ -780,7 +782,9 @@ impl<'a> Compiler<'a> {
self.match_depth = match_depth + members.len();
}
ListPattern(members) => {
let mut is_splatted = false;
if let Some((Splattern(patt), _)) = members.last() {
is_splatted = true;
self.emit_op(Op::MatchSplattedList)
} else {
self.emit_op(Op::MatchList);
@ -793,7 +797,11 @@ impl<'a> Compiler<'a> {
let match_depth = self.match_depth;
self.match_depth = members.len();
self.emit_op(Op::LoadList);
if is_splatted {
self.emit_op(Op::LoadSplattedList);
} else {
self.emit_op(Op::LoadList);
}
self.stack_depth += members.len();
for member in members {

View File

@ -471,17 +471,32 @@ impl Vm {
}
LoadList => {
let idx = self.stack.len() - self.match_depth as usize - 1;
let tuple = self.stack[idx].clone();
match tuple {
let list = self.stack[idx].clone();
match list {
Value::List(members) => {
for member in members.iter() {
self.push(member.clone());
}
}
_ => return self.panic("internal error: expected tuple"),
_ => return self.panic("internal error: expected list"),
};
self.ip += 1;
}
LoadSplattedList => {
let loaded_len = self.chunk().bytecode[self.ip + 1] as usize;
let idx = self.stack.len() - self.match_depth as usize - 1;
let list = self.stack[idx].clone();
let Value::List(members) = list else {
return self.panic("internal error: expected list");
};
for i in 0..loaded_len - 1 {
self.push(members[i].clone());
}
let splatted = Value::List(Box::new(members.skip(loaded_len - 1)));
self.push(splatted);
self.ip += 2;
todo!()
}
// PushDict => {
// let dict_len = self.chunk().bytecode[self.ip + 1] as usize * 2;
// let dict_members = self.stack.split_off(self.stack.len() - dict_len);