add match_depth to vm
This commit is contained in:
parent
6f582bff06
commit
8908630a21
|
@ -141,6 +141,7 @@ pub struct Compiler {
|
|||
pub span: SimpleSpan,
|
||||
pub src: &'static str,
|
||||
pub name: &'static str,
|
||||
loop_idxes: Vec<usize>,
|
||||
}
|
||||
|
||||
fn is_binding(expr: &Spanned<Ast>) -> bool {
|
||||
|
@ -172,6 +173,7 @@ impl Compiler {
|
|||
nodes: vec![],
|
||||
ast: &ast.0,
|
||||
span: ast.1,
|
||||
loop_idxes: vec![],
|
||||
src,
|
||||
name,
|
||||
}
|
||||
|
@ -253,6 +255,18 @@ impl Compiler {
|
|||
});
|
||||
}
|
||||
|
||||
fn enter_loop(&mut self) {
|
||||
self.loop_idxes.push(self.len());
|
||||
}
|
||||
|
||||
fn leave_loop(&mut self) {
|
||||
self.loop_idxes.pop();
|
||||
}
|
||||
|
||||
fn loop_idx(&mut self) -> usize {
|
||||
*self.loop_idxes.last().unwrap()
|
||||
}
|
||||
|
||||
pub fn compile(&mut self) {
|
||||
use Ast::*;
|
||||
match self.ast {
|
||||
|
@ -472,7 +486,6 @@ impl Compiler {
|
|||
self.visit(scrutinee.as_ref());
|
||||
let mut jump_idxes = vec![];
|
||||
let mut clauses = clauses.iter();
|
||||
// TODO: add guard checking
|
||||
while let Some((MatchClause(pattern, guard, body), _)) = clauses.next() {
|
||||
self.scope_depth += 1;
|
||||
self.visit(pattern);
|
||||
|
@ -592,14 +605,38 @@ impl Compiler {
|
|||
// and emit nil
|
||||
self.emit_constant(Value::Nil);
|
||||
}
|
||||
Loop(value, clauses) => {
|
||||
//algo:
|
||||
//first, put the values on the stack
|
||||
let (Ast::Tuple(members), _) = value.as_ref() else {
|
||||
unreachable!()
|
||||
};
|
||||
for member in members {
|
||||
self.visit(member);
|
||||
}
|
||||
let arity = members.len();
|
||||
//then, save the beginning of the loop
|
||||
self.enter_loop();
|
||||
self.emit_op(Op::ResetMatch);
|
||||
//next, compile each clause:
|
||||
let mut clauses = clauses.iter();
|
||||
while let Some((Ast::MatchClause(pattern, _, body), _)) = clauses.next() {
|
||||
self.scope_depth += 1;
|
||||
let (Ast::TuplePattern(members), _) = pattern.as_ref() else {
|
||||
unreachable!()
|
||||
};
|
||||
}
|
||||
//match against the values on the stack
|
||||
//we know the (fixed) arity, so we should know where to look
|
||||
//compile the clauses exactly as in `match`
|
||||
}
|
||||
Recur(args) => {}
|
||||
Interpolated(..)
|
||||
| Arguments(..)
|
||||
| Placeholder
|
||||
| Panic(..)
|
||||
| Do(..)
|
||||
| Splat(..)
|
||||
| Loop(..)
|
||||
| Recur(..)
|
||||
| InterpolatedPattern(..)
|
||||
| AsPattern(..)
|
||||
| Splattern(..)
|
||||
|
|
|
@ -69,9 +69,8 @@ pub fn run(src: &'static str) {
|
|||
pub fn main() {
|
||||
let src = "
|
||||
match :foo with {
|
||||
:foo if nil -> :oops
|
||||
:foo if true -> :yay!
|
||||
:bar -> :thing
|
||||
:bar -> :no
|
||||
:foo -> :yes
|
||||
}
|
||||
";
|
||||
run(src);
|
||||
|
|
16
src/vm.rs
16
src/vm.rs
|
@ -36,6 +36,7 @@ pub struct Vm<'a> {
|
|||
pub ip: usize,
|
||||
pub return_register: Value,
|
||||
pub matches: bool,
|
||||
pub match_depth: u8,
|
||||
}
|
||||
|
||||
impl<'a> Vm<'a> {
|
||||
|
@ -46,6 +47,7 @@ impl<'a> Vm<'a> {
|
|||
ip: 0,
|
||||
return_register: Value::Nil,
|
||||
matches: false,
|
||||
match_depth: 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -174,6 +176,7 @@ impl<'a> Vm<'a> {
|
|||
}
|
||||
ResetMatch => {
|
||||
self.matches = false;
|
||||
self.match_depth = 0;
|
||||
self.ip += 1;
|
||||
self.interpret()
|
||||
}
|
||||
|
@ -183,21 +186,24 @@ impl<'a> Vm<'a> {
|
|||
self.interpret()
|
||||
}
|
||||
MatchNil => {
|
||||
if *self.stack.last().unwrap() == Value::Nil {
|
||||
let idx = self.stack.len() - self.match_depth as usize - 1;
|
||||
if self.stack[idx] == Value::Nil {
|
||||
self.matches = true;
|
||||
};
|
||||
self.ip += 1;
|
||||
self.interpret()
|
||||
}
|
||||
MatchTrue => {
|
||||
if *self.stack.last().unwrap() == Value::True {
|
||||
let idx = self.stack.len() - self.match_depth as usize - 1;
|
||||
if self.stack[idx] == Value::True {
|
||||
self.matches = true;
|
||||
};
|
||||
self.ip += 1;
|
||||
self.interpret()
|
||||
}
|
||||
MatchFalse => {
|
||||
if *self.stack.last().unwrap() == Value::False {
|
||||
let idx = self.stack.len() - self.match_depth as usize - 1;
|
||||
if self.stack[idx] == Value::False {
|
||||
self.matches = true;
|
||||
}
|
||||
self.ip += 1;
|
||||
|
@ -213,8 +219,8 @@ impl<'a> Vm<'a> {
|
|||
}
|
||||
MatchConstant => {
|
||||
let const_idx = self.chunk.bytecode[self.ip + 1];
|
||||
let value = self.stack.last().unwrap();
|
||||
self.matches = *value == self.chunk.constants[const_idx as usize];
|
||||
let idx = self.stack.len() - self.match_depth as usize - 1;
|
||||
self.matches = self.stack[idx] == self.chunk.constants[const_idx as usize];
|
||||
self.ip += 2;
|
||||
self.interpret()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user