add list splats
This commit is contained in:
parent
b8b720b877
commit
b557c487cc
|
@ -41,6 +41,8 @@ pub enum Op {
|
||||||
MatchList,
|
MatchList,
|
||||||
LoadList,
|
LoadList,
|
||||||
PushList,
|
PushList,
|
||||||
|
AppendList,
|
||||||
|
ConcatList,
|
||||||
PushDict,
|
PushDict,
|
||||||
LoadDictValue,
|
LoadDictValue,
|
||||||
MatchDict,
|
MatchDict,
|
||||||
|
@ -153,6 +155,8 @@ impl std::fmt::Display for Op {
|
||||||
MatchList => "match_list",
|
MatchList => "match_list",
|
||||||
LoadList => "load_list",
|
LoadList => "load_list",
|
||||||
PushList => "push_list",
|
PushList => "push_list",
|
||||||
|
AppendList => "append_list",
|
||||||
|
ConcatList => "concat_list",
|
||||||
PushDict => "push_dict",
|
PushDict => "push_dict",
|
||||||
LoadDictValue => "load_dict_value",
|
LoadDictValue => "load_dict_value",
|
||||||
MatchDict => "match_dict",
|
MatchDict => "match_dict",
|
||||||
|
@ -228,7 +232,8 @@ impl Chunk {
|
||||||
| PanicIfNoMatch | ResetMatch | GetKey | PanicNoWhen | PanicNoMatch | TypeOf
|
| PanicIfNoMatch | ResetMatch | GetKey | PanicNoWhen | PanicNoMatch | TypeOf
|
||||||
| Duplicate | Decrement | Truncate | Noop | LoadTuple | LoadList | Eq | Add | Sub
|
| Duplicate | Decrement | Truncate | Noop | LoadTuple | LoadList | Eq | Add | Sub
|
||||||
| Mult | Div | Unbox | BoxStore | Assert | Get | At | Not | Panic | EmptyString
|
| Mult | Div | Unbox | BoxStore | Assert | Get | At | Not | Panic | EmptyString
|
||||||
| ConcatStrings | Stringify | MatchType | Return | Match | Print => {
|
| ConcatStrings | Stringify | MatchType | Return | Match | Print | AppendList
|
||||||
|
| ConcatList | PushList => {
|
||||||
println!("{i:04}: {op}")
|
println!("{i:04}: {op}")
|
||||||
}
|
}
|
||||||
Constant | MatchConstant => {
|
Constant | MatchConstant => {
|
||||||
|
@ -238,7 +243,7 @@ impl Chunk {
|
||||||
*i += 1;
|
*i += 1;
|
||||||
}
|
}
|
||||||
PushBinding | MatchTuple | MatchList | MatchDict | LoadDictValue | PushTuple
|
PushBinding | MatchTuple | MatchList | MatchDict | LoadDictValue | PushTuple
|
||||||
| PushDict | PushList | PushBox | Jump | JumpIfFalse | JumpIfTrue | JumpIfNoMatch
|
| PushDict | PushBox | Jump | JumpIfFalse | JumpIfTrue | JumpIfNoMatch
|
||||||
| JumpIfMatch | JumpBack | JumpIfZero | MatchDepth | PopN | StoreAt | Call
|
| JumpIfMatch | JumpBack | JumpIfZero | MatchDepth | PopN | StoreAt | Call
|
||||||
| SetUpvalue | GetUpvalue => {
|
| SetUpvalue | GetUpvalue => {
|
||||||
let next = self.bytecode[*i + 1];
|
let next = self.bytecode[*i + 1];
|
||||||
|
@ -590,7 +595,7 @@ impl<'a> Compiler<'a> {
|
||||||
self.emit_op(Op::Match);
|
self.emit_op(Op::Match);
|
||||||
self.bind(name);
|
self.bind(name);
|
||||||
}
|
}
|
||||||
Word(name) => match self.resolve_local(name) {
|
Word(name) | Splat(name) => match self.resolve_local(name) {
|
||||||
Some(position) => {
|
Some(position) => {
|
||||||
self.emit_op(Op::PushBinding);
|
self.emit_op(Op::PushBinding);
|
||||||
self.emit_byte(position);
|
self.emit_byte(position);
|
||||||
|
@ -757,12 +762,17 @@ impl<'a> Compiler<'a> {
|
||||||
self.stack_depth = self.stack_depth + 1 - members.len();
|
self.stack_depth = self.stack_depth + 1 - members.len();
|
||||||
}
|
}
|
||||||
List(members) => {
|
List(members) => {
|
||||||
|
self.emit_op(Op::PushList);
|
||||||
|
self.stack_depth += 1;
|
||||||
for member in members {
|
for member in members {
|
||||||
self.visit(member);
|
self.visit(member);
|
||||||
|
if matches!(member, (Splat(..), _)) {
|
||||||
|
self.emit_op(Op::ConcatList);
|
||||||
|
} else {
|
||||||
|
self.emit_op(Op::AppendList);
|
||||||
|
}
|
||||||
|
self.stack_depth -= 1;
|
||||||
}
|
}
|
||||||
self.emit_op(Op::PushList);
|
|
||||||
self.emit_byte(members.len());
|
|
||||||
self.stack_depth = self.stack_depth + 1 - members.len();
|
|
||||||
}
|
}
|
||||||
LBox(name, expr) => {
|
LBox(name, expr) => {
|
||||||
self.visit(expr);
|
self.visit(expr);
|
||||||
|
@ -1273,7 +1283,7 @@ impl<'a> Compiler<'a> {
|
||||||
self.stack_depth -= 1;
|
self.stack_depth -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Arguments(..) | Placeholder | Splat(..) | InterpolatedPattern(..) | Splattern(..) => {
|
Arguments(..) | Placeholder | InterpolatedPattern(..) | Splattern(..) => {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
And | Or => unreachable!(),
|
And | Or => unreachable!(),
|
||||||
|
|
11
src/main.rs
11
src/main.rs
|
@ -76,14 +76,11 @@ 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 = "
|
||||||
fn increase (x) -> add (x, 1)
|
let x = []
|
||||||
|
let y = [1, 2, 3]
|
||||||
fn double (x) -> mult (x, 2)
|
let z = [...y, 4, ...x]
|
||||||
|
|
||||||
fn halve (x) -> div (x, 2)
|
|
||||||
|
|
||||||
do 1 > increase > double > increase > halve
|
|
||||||
|
|
||||||
|
z
|
||||||
|
|
||||||
";
|
";
|
||||||
run(src);
|
run(src);
|
||||||
|
|
37
src/vm.rs
37
src/vm.rs
|
@ -368,12 +368,39 @@ impl Vm {
|
||||||
};
|
};
|
||||||
self.ip += 1;
|
self.ip += 1;
|
||||||
}
|
}
|
||||||
|
// PushList => {
|
||||||
|
// let list_len = self.chunk().bytecode[self.ip + 1];
|
||||||
|
// let list_members = self.stack.split_off(self.stack.len() - list_len as usize);
|
||||||
|
// let list = Value::List(Box::new(Vector::from(list_members)));
|
||||||
|
// self.push(list);
|
||||||
|
// self.ip += 2;
|
||||||
|
// }
|
||||||
PushList => {
|
PushList => {
|
||||||
let list_len = self.chunk().bytecode[self.ip + 1];
|
self.push(Value::List(Box::new(Vector::new())));
|
||||||
let list_members = self.stack.split_off(self.stack.len() - list_len as usize);
|
self.ip += 1;
|
||||||
let list = Value::List(Box::new(Vector::from(list_members)));
|
}
|
||||||
self.push(list);
|
AppendList => {
|
||||||
self.ip += 2;
|
let value = self.pop();
|
||||||
|
let list = self.pop();
|
||||||
|
let Value::List(mut list) = list else {
|
||||||
|
return self.panic("only lists may be splatted into lists");
|
||||||
|
};
|
||||||
|
list.push_back(value);
|
||||||
|
self.push(Value::List(list));
|
||||||
|
self.ip += 1;
|
||||||
|
}
|
||||||
|
ConcatList => {
|
||||||
|
let splatted = self.pop();
|
||||||
|
let target = self.pop();
|
||||||
|
let Value::List(mut target) = target else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
let Value::List(splatted) = splatted else {
|
||||||
|
return self.panic("only lists may be splatted into lists");
|
||||||
|
};
|
||||||
|
target.append(*splatted);
|
||||||
|
self.push(Value::List(target));
|
||||||
|
self.ip += 1;
|
||||||
}
|
}
|
||||||
MatchList => {
|
MatchList => {
|
||||||
let idx = self.stack.len() - self.match_depth as usize - 1;
|
let idx = self.stack.len() - self.match_depth as usize - 1;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user