get simple match forms done
This commit is contained in:
parent
d943185db8
commit
be23ee6c44
|
@ -31,6 +31,8 @@ pub enum Op {
|
|||
PushBox,
|
||||
GetKey,
|
||||
PanicNoWhen,
|
||||
JumpIfNoMatch,
|
||||
PanicNoMatch,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Op {
|
||||
|
@ -61,6 +63,8 @@ impl std::fmt::Display for Op {
|
|||
PushBox => "push_box",
|
||||
GetKey => "get_key",
|
||||
PanicNoWhen => "panic_no_when",
|
||||
JumpIfNoMatch => "jump_if_no_match",
|
||||
PanicNoMatch => "panic_no_match",
|
||||
};
|
||||
write!(f, "{rep}")
|
||||
}
|
||||
|
@ -393,6 +397,40 @@ impl<'a> Chunk<'a> {
|
|||
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!(),
|
||||
}
|
||||
}
|
||||
|
@ -406,7 +444,7 @@ impl<'a> Chunk<'a> {
|
|||
use Op::*;
|
||||
match op {
|
||||
Pop | Store | Load | Nil | True | False | MatchNil | MatchTrue | MatchFalse
|
||||
| MatchWord | ResetMatch | PanicIfNoMatch | GetKey | PanicNoWhen => {
|
||||
| MatchWord | ResetMatch | PanicIfNoMatch | GetKey | PanicNoWhen | PanicNoMatch => {
|
||||
println!("{i:04}: {op}")
|
||||
}
|
||||
Constant | MatchConstant => {
|
||||
|
@ -414,14 +452,11 @@ impl<'a> Chunk<'a> {
|
|||
let value = &self.constants[*next as usize].show(self);
|
||||
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();
|
||||
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::*;
|
||||
match op {
|
||||
Pop | Store | Load | Nil | True | False | MatchNil | MatchTrue | MatchFalse
|
||||
| PanicIfNoMatch | MatchWord | ResetMatch | GetKey | PanicNoWhen => {
|
||||
| PanicIfNoMatch | MatchWord | ResetMatch | GetKey | PanicNoWhen | PanicNoMatch => {
|
||||
println!("{i:04}: {op}")
|
||||
}
|
||||
Constant | MatchConstant => {
|
||||
|
@ -439,14 +474,11 @@ impl<'a> Chunk<'a> {
|
|||
let value = &self.constants[next as usize].show(self);
|
||||
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];
|
||||
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() {
|
||||
let src = "
|
||||
let foo = 42
|
||||
when {
|
||||
foo -> :two
|
||||
false -> :four
|
||||
:else -> :thing
|
||||
match foo with {
|
||||
:foo -> {
|
||||
1
|
||||
2
|
||||
x
|
||||
}
|
||||
2 -> :two
|
||||
42 -> :everything
|
||||
_ -> :something_else
|
||||
}
|
||||
";
|
||||
run(src);
|
||||
|
|
11
src/vm.rs
11
src/vm.rs
|
@ -249,7 +249,16 @@ impl<'a> Vm<'a> {
|
|||
MatchTuple => {
|
||||
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