first stab at splatted lists
This commit is contained in:
parent
4871dbd048
commit
2b95094eca
|
@ -44,6 +44,7 @@ pub enum Op {
|
||||||
MatchList,
|
MatchList,
|
||||||
MatchSplattedList,
|
MatchSplattedList,
|
||||||
LoadList,
|
LoadList,
|
||||||
|
LoadSplattedList,
|
||||||
PushList,
|
PushList,
|
||||||
AppendList,
|
AppendList,
|
||||||
ConcatList,
|
ConcatList,
|
||||||
|
@ -165,6 +166,7 @@ impl std::fmt::Display for Op {
|
||||||
MatchList => "match_list",
|
MatchList => "match_list",
|
||||||
MatchSplattedList => "match_splatted_list",
|
MatchSplattedList => "match_splatted_list",
|
||||||
LoadList => "load_list",
|
LoadList => "load_list",
|
||||||
|
LoadSplattedList => "load_splatted_list",
|
||||||
PushList => "push_list",
|
PushList => "push_list",
|
||||||
AppendList => "append_list",
|
AppendList => "append_list",
|
||||||
ConcatList => "concat_list",
|
ConcatList => "concat_list",
|
||||||
|
@ -262,9 +264,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 | MatchSplattedList | MatchDict
|
PushBinding | MatchTuple | MatchList | MatchSplattedList | LoadSplattedList
|
||||||
| LoadDictValue | PushTuple | PushBox | MatchDepth | PopN | StoreAt | Call
|
| MatchDict | LoadDictValue | PushTuple | PushBox | MatchDepth | PopN | StoreAt
|
||||||
| SetUpvalue | GetUpvalue | Partial | MatchString | PushStringMatches => {
|
| Call | 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;
|
||||||
|
@ -780,7 +782,9 @@ impl<'a> Compiler<'a> {
|
||||||
self.match_depth = match_depth + members.len();
|
self.match_depth = match_depth + members.len();
|
||||||
}
|
}
|
||||||
ListPattern(members) => {
|
ListPattern(members) => {
|
||||||
|
let mut is_splatted = false;
|
||||||
if let Some((Splattern(patt), _)) = members.last() {
|
if let Some((Splattern(patt), _)) = members.last() {
|
||||||
|
is_splatted = true;
|
||||||
self.emit_op(Op::MatchSplattedList)
|
self.emit_op(Op::MatchSplattedList)
|
||||||
} else {
|
} else {
|
||||||
self.emit_op(Op::MatchList);
|
self.emit_op(Op::MatchList);
|
||||||
|
@ -793,7 +797,11 @@ impl<'a> Compiler<'a> {
|
||||||
let match_depth = self.match_depth;
|
let match_depth = self.match_depth;
|
||||||
self.match_depth = members.len();
|
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();
|
self.stack_depth += members.len();
|
||||||
|
|
||||||
for member in members {
|
for member in members {
|
||||||
|
|
21
src/vm.rs
21
src/vm.rs
|
@ -471,17 +471,32 @@ impl Vm {
|
||||||
}
|
}
|
||||||
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 list = self.stack[idx].clone();
|
||||||
match tuple {
|
match list {
|
||||||
Value::List(members) => {
|
Value::List(members) => {
|
||||||
for member in members.iter() {
|
for member in members.iter() {
|
||||||
self.push(member.clone());
|
self.push(member.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => return self.panic("internal error: expected tuple"),
|
_ => return self.panic("internal error: expected list"),
|
||||||
};
|
};
|
||||||
self.ip += 1;
|
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 => {
|
// PushDict => {
|
||||||
// let dict_len = self.chunk().bytecode[self.ip + 1] as usize * 2;
|
// let dict_len = self.chunk().bytecode[self.ip + 1] as usize * 2;
|
||||||
// let dict_members = self.stack.split_off(self.stack.len() - dict_len);
|
// let dict_members = self.stack.split_off(self.stack.len() - dict_len);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user