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 span: SimpleSpan,
|
||||||
pub src: &'static str,
|
pub src: &'static str,
|
||||||
pub name: &'static str,
|
pub name: &'static str,
|
||||||
|
loop_idxes: Vec<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_binding(expr: &Spanned<Ast>) -> bool {
|
fn is_binding(expr: &Spanned<Ast>) -> bool {
|
||||||
|
@ -172,6 +173,7 @@ impl Compiler {
|
||||||
nodes: vec![],
|
nodes: vec![],
|
||||||
ast: &ast.0,
|
ast: &ast.0,
|
||||||
span: ast.1,
|
span: ast.1,
|
||||||
|
loop_idxes: vec![],
|
||||||
src,
|
src,
|
||||||
name,
|
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) {
|
pub fn compile(&mut self) {
|
||||||
use Ast::*;
|
use Ast::*;
|
||||||
match self.ast {
|
match self.ast {
|
||||||
|
@ -472,7 +486,6 @@ impl Compiler {
|
||||||
self.visit(scrutinee.as_ref());
|
self.visit(scrutinee.as_ref());
|
||||||
let mut jump_idxes = vec![];
|
let mut jump_idxes = vec![];
|
||||||
let mut clauses = clauses.iter();
|
let mut clauses = clauses.iter();
|
||||||
// TODO: add guard checking
|
|
||||||
while let Some((MatchClause(pattern, guard, body), _)) = clauses.next() {
|
while let Some((MatchClause(pattern, guard, body), _)) = clauses.next() {
|
||||||
self.scope_depth += 1;
|
self.scope_depth += 1;
|
||||||
self.visit(pattern);
|
self.visit(pattern);
|
||||||
|
@ -592,14 +605,38 @@ impl Compiler {
|
||||||
// and emit nil
|
// and emit nil
|
||||||
self.emit_constant(Value::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(..)
|
Interpolated(..)
|
||||||
| Arguments(..)
|
| Arguments(..)
|
||||||
| Placeholder
|
| Placeholder
|
||||||
| Panic(..)
|
| Panic(..)
|
||||||
| Do(..)
|
| Do(..)
|
||||||
| Splat(..)
|
| Splat(..)
|
||||||
| Loop(..)
|
|
||||||
| Recur(..)
|
|
||||||
| InterpolatedPattern(..)
|
| InterpolatedPattern(..)
|
||||||
| AsPattern(..)
|
| AsPattern(..)
|
||||||
| Splattern(..)
|
| Splattern(..)
|
||||||
|
|
|
@ -69,9 +69,8 @@ pub fn run(src: &'static str) {
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let src = "
|
let src = "
|
||||||
match :foo with {
|
match :foo with {
|
||||||
:foo if nil -> :oops
|
:bar -> :no
|
||||||
:foo if true -> :yay!
|
:foo -> :yes
|
||||||
:bar -> :thing
|
|
||||||
}
|
}
|
||||||
";
|
";
|
||||||
run(src);
|
run(src);
|
||||||
|
|
16
src/vm.rs
16
src/vm.rs
|
@ -36,6 +36,7 @@ pub struct Vm<'a> {
|
||||||
pub ip: usize,
|
pub ip: usize,
|
||||||
pub return_register: Value,
|
pub return_register: Value,
|
||||||
pub matches: bool,
|
pub matches: bool,
|
||||||
|
pub match_depth: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Vm<'a> {
|
impl<'a> Vm<'a> {
|
||||||
|
@ -46,6 +47,7 @@ impl<'a> Vm<'a> {
|
||||||
ip: 0,
|
ip: 0,
|
||||||
return_register: Value::Nil,
|
return_register: Value::Nil,
|
||||||
matches: false,
|
matches: false,
|
||||||
|
match_depth: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,6 +176,7 @@ impl<'a> Vm<'a> {
|
||||||
}
|
}
|
||||||
ResetMatch => {
|
ResetMatch => {
|
||||||
self.matches = false;
|
self.matches = false;
|
||||||
|
self.match_depth = 0;
|
||||||
self.ip += 1;
|
self.ip += 1;
|
||||||
self.interpret()
|
self.interpret()
|
||||||
}
|
}
|
||||||
|
@ -183,21 +186,24 @@ impl<'a> Vm<'a> {
|
||||||
self.interpret()
|
self.interpret()
|
||||||
}
|
}
|
||||||
MatchNil => {
|
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.matches = true;
|
||||||
};
|
};
|
||||||
self.ip += 1;
|
self.ip += 1;
|
||||||
self.interpret()
|
self.interpret()
|
||||||
}
|
}
|
||||||
MatchTrue => {
|
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.matches = true;
|
||||||
};
|
};
|
||||||
self.ip += 1;
|
self.ip += 1;
|
||||||
self.interpret()
|
self.interpret()
|
||||||
}
|
}
|
||||||
MatchFalse => {
|
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.matches = true;
|
||||||
}
|
}
|
||||||
self.ip += 1;
|
self.ip += 1;
|
||||||
|
@ -213,8 +219,8 @@ impl<'a> Vm<'a> {
|
||||||
}
|
}
|
||||||
MatchConstant => {
|
MatchConstant => {
|
||||||
let const_idx = self.chunk.bytecode[self.ip + 1];
|
let const_idx = self.chunk.bytecode[self.ip + 1];
|
||||||
let value = self.stack.last().unwrap();
|
let idx = self.stack.len() - self.match_depth as usize - 1;
|
||||||
self.matches = *value == self.chunk.constants[const_idx as usize];
|
self.matches = self.stack[idx] == self.chunk.constants[const_idx as usize];
|
||||||
self.ip += 2;
|
self.ip += 2;
|
||||||
self.interpret()
|
self.interpret()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user