get simple match forms done
This commit is contained in:
parent
d943185db8
commit
be23ee6c44
|
@ -31,6 +31,8 @@ pub enum Op {
|
||||||
PushBox,
|
PushBox,
|
||||||
GetKey,
|
GetKey,
|
||||||
PanicNoWhen,
|
PanicNoWhen,
|
||||||
|
JumpIfNoMatch,
|
||||||
|
PanicNoMatch,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for Op {
|
impl std::fmt::Display for Op {
|
||||||
|
@ -61,6 +63,8 @@ impl std::fmt::Display for Op {
|
||||||
PushBox => "push_box",
|
PushBox => "push_box",
|
||||||
GetKey => "get_key",
|
GetKey => "get_key",
|
||||||
PanicNoWhen => "panic_no_when",
|
PanicNoWhen => "panic_no_when",
|
||||||
|
JumpIfNoMatch => "jump_if_no_match",
|
||||||
|
PanicNoMatch => "panic_no_match",
|
||||||
};
|
};
|
||||||
write!(f, "{rep}")
|
write!(f, "{rep}")
|
||||||
}
|
}
|
||||||
|
@ -393,6 +397,40 @@ impl<'a> Chunk<'a> {
|
||||||
self.bytecode[idx] = self.bytecode.len() as u8 - idx as u8 + 1;
|
self.bytecode[idx] = self.bytecode.len() as u8 - idx as u8 + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Match(scrutinee, clauses) => {
|
||||||
|
dbg!(&scrutinee);
|
||||||
|
self.visit(scrutinee.as_ref());
|
||||||
|
let mut jump_idxes = vec![];
|
||||||
|
let mut clauses = clauses.iter();
|
||||||
|
while let Some((MatchClause(pattern, _, body), _)) = clauses.next() {
|
||||||
|
self.scope_depth += 1;
|
||||||
|
self.visit(pattern);
|
||||||
|
self.emit_op(Op::JumpIfNoMatch);
|
||||||
|
let jnm_jump_idx = self.bytecode.len();
|
||||||
|
self.bytecode.push(0xff);
|
||||||
|
self.visit(body);
|
||||||
|
self.emit_op(Op::Store);
|
||||||
|
self.scope_depth -= 1;
|
||||||
|
while let Some(binding) = self.bindings.last() {
|
||||||
|
if binding.depth > self.scope_depth {
|
||||||
|
self.emit_op(Op::Pop);
|
||||||
|
self.bindings.pop();
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.emit_op(Op::Jump);
|
||||||
|
jump_idxes.push(self.bytecode.len());
|
||||||
|
self.bytecode.push(0xff);
|
||||||
|
self.bytecode[jnm_jump_idx] =
|
||||||
|
self.bytecode.len() as u8 - jnm_jump_idx as u8 - 1;
|
||||||
|
}
|
||||||
|
self.emit_op(Op::PanicNoMatch);
|
||||||
|
self.emit_op(Op::Load);
|
||||||
|
for idx in jump_idxes {
|
||||||
|
self.bytecode[idx] = self.bytecode.len() as u8 - idx as u8 + 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -406,7 +444,7 @@ impl<'a> Chunk<'a> {
|
||||||
use Op::*;
|
use Op::*;
|
||||||
match op {
|
match op {
|
||||||
Pop | Store | Load | Nil | True | False | MatchNil | MatchTrue | MatchFalse
|
Pop | Store | Load | Nil | True | False | MatchNil | MatchTrue | MatchFalse
|
||||||
| MatchWord | ResetMatch | PanicIfNoMatch | GetKey | PanicNoWhen => {
|
| MatchWord | ResetMatch | PanicIfNoMatch | GetKey | PanicNoWhen | PanicNoMatch => {
|
||||||
println!("{i:04}: {op}")
|
println!("{i:04}: {op}")
|
||||||
}
|
}
|
||||||
Constant | MatchConstant => {
|
Constant | MatchConstant => {
|
||||||
|
@ -414,14 +452,11 @@ impl<'a> Chunk<'a> {
|
||||||
let value = &self.constants[*next as usize].show(self);
|
let value = &self.constants[*next as usize].show(self);
|
||||||
println!("{i:04}: {:16} {next:04}: {value}", op.to_string());
|
println!("{i:04}: {:16} {next:04}: {value}", op.to_string());
|
||||||
}
|
}
|
||||||
PushBinding | MatchTuple | PushTuple | PushDict | PushList | PushBox => {
|
PushBinding | MatchTuple | PushTuple | PushDict | PushList | PushBox | Jump
|
||||||
|
| JumpIfFalse | JumpIfNoMatch => {
|
||||||
let (_, next) = codes.next().unwrap();
|
let (_, next) = codes.next().unwrap();
|
||||||
println!("{i:04}: {:16} {next:04}", op.to_string());
|
println!("{i:04}: {:16} {next:04}", op.to_string());
|
||||||
}
|
}
|
||||||
Jump | JumpIfFalse => {
|
|
||||||
let (_, next) = codes.next().unwrap();
|
|
||||||
println!("{i:04}: {:16} {next:04}", op.to_string())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -431,7 +466,7 @@ impl<'a> Chunk<'a> {
|
||||||
use Op::*;
|
use Op::*;
|
||||||
match op {
|
match op {
|
||||||
Pop | Store | Load | Nil | True | False | MatchNil | MatchTrue | MatchFalse
|
Pop | Store | Load | Nil | True | False | MatchNil | MatchTrue | MatchFalse
|
||||||
| PanicIfNoMatch | MatchWord | ResetMatch | GetKey | PanicNoWhen => {
|
| PanicIfNoMatch | MatchWord | ResetMatch | GetKey | PanicNoWhen | PanicNoMatch => {
|
||||||
println!("{i:04}: {op}")
|
println!("{i:04}: {op}")
|
||||||
}
|
}
|
||||||
Constant | MatchConstant => {
|
Constant | MatchConstant => {
|
||||||
|
@ -439,14 +474,11 @@ impl<'a> Chunk<'a> {
|
||||||
let value = &self.constants[next as usize].show(self);
|
let value = &self.constants[next as usize].show(self);
|
||||||
println!("{i:04}: {:16} {next:04}: {value}", op.to_string());
|
println!("{i:04}: {:16} {next:04}: {value}", op.to_string());
|
||||||
}
|
}
|
||||||
PushBinding | MatchTuple | PushTuple | PushDict | PushList | PushBox => {
|
PushBinding | MatchTuple | PushTuple | PushDict | PushList | PushBox | Jump
|
||||||
|
| JumpIfFalse | JumpIfNoMatch => {
|
||||||
let next = self.bytecode[i + 1];
|
let next = self.bytecode[i + 1];
|
||||||
println!("{i:04}: {:16} {next:04}", op.to_string());
|
println!("{i:04}: {:16} {next:04}", op.to_string());
|
||||||
}
|
}
|
||||||
Jump | JumpIfFalse => {
|
|
||||||
let next = self.bytecode[i + 1];
|
|
||||||
println!("{i:04}: {:16} {next:04}", op.to_string())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
13
src/main.rs
13
src/main.rs
|
@ -65,10 +65,15 @@ pub fn run(src: &'static str) {
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let src = "
|
let src = "
|
||||||
let foo = 42
|
let foo = 42
|
||||||
when {
|
match foo with {
|
||||||
foo -> :two
|
:foo -> {
|
||||||
false -> :four
|
1
|
||||||
:else -> :thing
|
2
|
||||||
|
x
|
||||||
|
}
|
||||||
|
2 -> :two
|
||||||
|
42 -> :everything
|
||||||
|
_ -> :something_else
|
||||||
}
|
}
|
||||||
";
|
";
|
||||||
run(src);
|
run(src);
|
||||||
|
|
11
src/vm.rs
11
src/vm.rs
|
@ -249,7 +249,16 @@ impl<'a> Vm<'a> {
|
||||||
MatchTuple => {
|
MatchTuple => {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
PanicNoWhen => Err(Panic("no match")),
|
JumpIfNoMatch => {
|
||||||
|
let jump_len = self.chunk.bytecode[self.ip + 1] as usize;
|
||||||
|
if !self.matches {
|
||||||
|
self.ip += jump_len + 2;
|
||||||
|
} else {
|
||||||
|
self.ip += 2;
|
||||||
|
}
|
||||||
|
self.interpret()
|
||||||
|
}
|
||||||
|
PanicNoWhen | PanicNoMatch => Err(Panic("no match")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user