summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--matrix-bin/src/main.rs1
-rw-r--r--matrix/src/ast.rs231
-rw-r--r--matrix/src/chunk.rs21
-rw-r--r--matrix/src/compiler.rs357
-rw-r--r--matrix/src/parse.rs525
-rw-r--r--matrix/src/vm.rs34
6 files changed, 539 insertions, 630 deletions
diff --git a/matrix-bin/src/main.rs b/matrix-bin/src/main.rs
index 7e3c3c6..3ae8135 100644
--- a/matrix-bin/src/main.rs
+++ b/matrix-bin/src/main.rs
@@ -54,7 +54,6 @@ impl<'a> State<'a> {
let compiler = CompilerBuilder::new()
.repl(repl)
.debug(args.debug)
- .globals(vm.globals())
.build();
(Self { parser, vm, compiler, repl }, file)
diff --git a/matrix/src/ast.rs b/matrix/src/ast.rs
index 9a0dfaa..594cd48 100644
--- a/matrix/src/ast.rs
+++ b/matrix/src/ast.rs
@@ -36,6 +36,8 @@ pub enum BinaryOp {
#[derive(Debug, Clone, PartialEq)]
pub enum Expr {
+ NoOp,
+
Literal(Value),
Ident(Rc<str>),
@@ -52,34 +54,24 @@ pub enum Expr {
And(Box<Expr>, Box<Expr>),
Or(Box<Expr>, Box<Expr>),
-}
-#[derive(Debug, Clone, PartialEq)]
-pub enum Assign {
- Expr(Expr),
- Assign(Expr, Box<Assign>)
-}
+ Assign(Box<Expr>, Box<Expr>),
-#[derive(Debug, Clone, PartialEq)]
-pub enum Stmt {
- NoOp,
+ If(Box<Expr>, Box<Expr>, Option<Box<Expr>>),
+ Function(Rc<str>, Vec<Rc<str>>, Box<Expr>),
- If(Expr, Box<Stmt>, Option<Box<Stmt>>),
- Function(Rc<str>, Vec<Rc<str>>, Box<Stmt>),
- Loop(Box<Stmt>),
- While(Expr, Box<Stmt>),
- DoWhile(Expr, Box<Stmt>),
+ Loop(Box<Expr>),
+ While(Box<Expr>, Box<Expr>),
+ DoWhile(Box<Expr>, Box<Expr>),
- Block(Vec<Stmt>),
- Expr(Expr),
+ Block(Vec<Expr>),
- Let(Rc<str>, Expr),
- Assign(Assign),
+ Let(Rc<str>, Box<Expr>),
Continue,
Break,
- Return(Expr),
+ Return(Box<Expr>),
}
impl Neg for BinaryOp {
@@ -156,181 +148,156 @@ impl Not for Expr {
}
}
-fn optimize_expr(expr: Expr) -> Result<Expr> {
- use Expr::*;
+pub fn optimize(expr: Expr) -> Result<Expr> {
+ use Expr as E;
Ok(match expr {
- UnaryOp(expr, op) => {
- let expr = optimize_expr(*expr)?;
+ E::UnaryOp(expr, op) => {
+ let expr = optimize(*expr)?;
match match op {
- self::UnaryOp::Negate => -expr,
- self::UnaryOp::Not => !expr,
+ UnaryOp::Negate => -expr,
+ UnaryOp::Not => !expr,
} {
Ok(expr) => expr,
- Err(expr) => UnaryOp(Box::new(expr), op)
+ Err(expr) => E::UnaryOp(Box::new(expr), op)
}
},
- BinaryOp(lhs, rhs, op) => {
- let lhs = optimize_expr(*lhs)?;
- let rhs = optimize_expr(*rhs)?;
- if let (Literal(l), Literal(r)) = (lhs.clone(), rhs.clone()) {
+ E::BinaryOp(lhs, rhs, op) => {
+ let lhs = optimize(*lhs)?;
+ let rhs = optimize(*rhs)?;
+ if let (E::Literal(l), E::Literal(r)) = (lhs.clone(), rhs.clone()) {
match Value::binary_op(op, l, r) {
Err(err) => return Err(err),
Ok(value) => return Ok(Expr::Literal(value)),
}
}
- BinaryOp(Box::new(lhs), Box::new(rhs), op)
+ E::BinaryOp(Box::new(lhs), Box::new(rhs), op)
},
- FnCall(ident, values) => {
- FnCall(ident, values
+ E::FnCall(ident, values) => {
+ E::FnCall(ident, values
.into_iter()
- .map(optimize_expr)
+ .map(optimize)
.collect::<Result<Vec<Expr>>>()?)
}
- FieldAccess(key, val) => {
- let key = optimize_expr(*key)?;
- let val = optimize_expr(*val)?;
- FieldAccess(Box::new(key), Box::new(val))
+ E::FieldAccess(key, val) => {
+ let key = optimize(*key)?;
+ let val = optimize(*val)?;
+ E::FieldAccess(Box::new(key), Box::new(val))
},
- List(list) =>
- List(list.into_iter()
- .map(optimize_expr)
+ E::List(list) =>
+ E::List(list.into_iter()
+ .map(optimize)
.collect::<Result<Vec<Expr>>>()?),
- Matrix(mat) =>
- Matrix((mat.0, mat.1,
- mat.2.into_iter().map(optimize_expr)
+ E::Matrix(mat) =>
+ E::Matrix((mat.0, mat.1,
+ mat.2.into_iter().map(optimize)
.collect::<Result<Vec<Expr>>>()?)),
- Table(table) =>
- Table(table
+ E::Table(table) =>
+ E::Table(table
.into_iter()
.map(|(k, v)| {
- let k = optimize_expr(k)?;
- let v = optimize_expr(v)?;
+ let k = optimize(k)?;
+ let v = optimize(v)?;
Ok((k, v))
}).collect::<Result<Vec<(Expr, Expr)>>>()?),
- And(lhs, rhs) => {
- let lhs = optimize_expr(*lhs)?;
- let rhs = optimize_expr(*rhs)?;
- if let (Literal(l), r) = (lhs.clone(), rhs.clone()) {
+ E::And(lhs, rhs) => {
+ let lhs = optimize(*lhs)?;
+ let rhs = optimize(*rhs)?;
+ if let (E::Literal(l), r) = (lhs.clone(), rhs.clone()) {
match !!l.clone() {
true => r,
- false => Literal(l),
+ false => E::Literal(l),
}
} else {
- And(Box::new(lhs), Box::new(rhs))
+ E::And(Box::new(lhs), Box::new(rhs))
}
},
- Or(lhs, rhs) => {
- let lhs = optimize_expr(*lhs)?;
- let rhs = optimize_expr(*rhs)?;
- if let (Literal(l), r) = (lhs.clone(), rhs.clone()) {
+ E::Or(lhs, rhs) => {
+ let lhs = optimize(*lhs)?;
+ let rhs = optimize(*rhs)?;
+ if let (E::Literal(l), r) = (lhs.clone(), rhs.clone()) {
match !l.clone() {
true => r,
- false => Literal(l),
+ false => E::Literal(l),
}
} else {
- And(Box::new(lhs), Box::new(rhs))
+ E::And(Box::new(lhs), Box::new(rhs))
}
},
- _ => expr
- })
-}
-
-fn optimize_assign(assign: Assign) -> Result<Assign> {
- use self::Assign::*;
- Ok(match assign {
- Expr(expr) => {
- let expr = optimize_expr(expr)?;
- Expr(expr)
- },
- Assign(expr, assign) => {
- let expr = optimize_expr(expr)?;
- let assign = optimize_assign(*assign)?;
- Assign(expr, Box::new(assign))
- }
- })
-}
-
-pub fn optimize(stmt: Stmt) -> Result<Stmt> {
- use Stmt::*;
- Ok(match stmt {
- Block(b) => {
- let b: Vec<Stmt> =
+ E::Block(b) => {
+ let len = b.len();
+ let b: Vec<Expr> =
b.into_iter()
.map(optimize)
- .collect::<Result<Vec<Stmt>>>()?
+ .collect::<Result<Vec<Expr>>>()?
.into_iter()
- .filter(|e| NoOp != *e)
+ .enumerate()
+ .filter(|(i, e)| {
+ if let E::Literal(_) = e {
+ return i + 1 == len
+ }
+ E::NoOp != *e
+ })
+ .map(|e| e.1)
.collect();
if b.is_empty() {
- NoOp
+ E::NoOp
} else {
- Block(b)
+ E::Block(b)
}
},
- If(cond, block, else_block) => {
- let cond = optimize_expr(cond)?;
+ E::If(cond, block, else_block) => {
+ let cond = optimize(*cond)?;
let block = optimize(*block)?;
let else_block = else_block.map(|e| optimize(*e)).transpose()?;
- if let self::Expr::Literal(lit) = cond {
+ if let E::Literal(lit) = cond {
if !!lit {
return Ok(block)
}
- return Ok(else_block.unwrap_or(NoOp))
+ return Ok(else_block.unwrap_or(E::NoOp))
}
- If(cond, Box::new(block), else_block.map(|e| Box::new(e)))
+ E::If(Box::new(cond), Box::new(block), else_block.map(|e| Box::new(e)))
},
- While(cond, block) => {
- let cond = optimize_expr(cond)?;
+ E::While(cond, block) => {
+ let cond = optimize(*cond)?;
let block = optimize(*block)?;
- if let self::Expr::Literal(lit) = cond {
+ if let E::Literal(lit) = cond {
if !!lit {
- return Ok(Loop(Box::new(block)))
+ return Ok(E::Loop(Box::new(block)))
}
- return Ok(NoOp)
+ return Ok(E::NoOp)
}
- While(cond, Box::new(block))
+ E::While(Box::new(cond), Box::new(block))
},
- DoWhile(cond, block) => {
- let cond = optimize_expr(cond)?;
+ E::DoWhile(block, cond) => {
+ let cond = optimize(*cond)?;
let block = optimize(*block)?;
- if let self::Expr::Literal(lit) = cond.clone() {
+ if let E::Literal(lit) = cond.clone() {
if !!lit {
- return Ok(Loop(Box::new(block)))
+ return Ok(E::Loop(Box::new(block)))
}
}
- DoWhile(cond, Box::new(block))
+ E::DoWhile(Box::new(block), Box::new(cond))
}
- Loop(block) => {
- let block = optimize(*block)?;
- Loop(Box::new(block))
+ E::Loop(block) => {
+ let block = Box::new(optimize(*block)?);
+ E::Loop(block)
},
- Function(ident, params, stmt) => {
- let stmt = optimize(*stmt)?;
- Function(ident, params, Box::new(stmt))
+ E::Function(ident, params, stmt) => {
+ let stmt = Box::new(optimize(*stmt)?);
+ E::Function(ident, params, stmt)
}
- Expr(expr) => {
- Expr(optimize_expr(expr)?)
+ E::Let(ident, expr) => {
+ E::Let(ident, Box::new(optimize(*expr)?))
},
- Let(ident, expr) => {
- Let(ident, optimize_expr(expr)?)
- }
- Assign(assign) => {
- use self::Assign as A;
- match assign {
- A::Expr(expr) => {
- let expr = optimize_expr(expr)?;
- Expr(expr)
- },
- A::Assign(lhs, rhs) => {
- let assign = optimize_assign(A::Assign(lhs, rhs))?;
- Assign(assign)
- },
- }
- }
- Return(expr) => {
- Return(optimize_expr(expr)?)
- }
- _ => stmt
+ E::Assign(lhs, rhs) => {
+ let lhs = Box::new(optimize(*lhs)?);
+ let rhs = Box::new(optimize(*rhs)?);
+ E::Assign(lhs, rhs)
+ },
+ E::Return(expr) => {
+ E::Return(Box::new(optimize(*expr)?))
+ },
+ _ => expr
})
}
diff --git a/matrix/src/chunk.rs b/matrix/src/chunk.rs
index d3d4bc8..3906535 100644
--- a/matrix/src/chunk.rs
+++ b/matrix/src/chunk.rs
@@ -1,4 +1,4 @@
-use crate::{value::Value, ast::{UnaryOp, BinaryOp}, Result};
+use crate::{value::Value, ast::{UnaryOp, BinaryOp}};
use std::{fmt::{Debug, Display}, rc::Rc};
#[derive(Clone)]
@@ -14,10 +14,6 @@ impl Chunk {
code: Vec::new()
}
}
-
- pub fn from_compiled(_buf: &[u8]) -> Result<Self> {
- todo!()
- }
}
impl Debug for Chunk {
@@ -52,8 +48,11 @@ pub struct Function {
pub enum Instruction {
NoOp,
- Load(u16),
- Store(u16),
+ CreateLocal,
+ LoadLocal(u16),
+ StoreLocal(u16),
+ DiscardLocals(u16),
+
LoadGlobal(u16),
StoreGlobal(u16),
@@ -88,8 +87,10 @@ impl Display for Instruction {
use Instruction::*;
match self {
NoOp => write!(f, "noop"),
- Load(idx) => write!(f, "load \x1b[33m{idx}\x1b[0m"),
- Store(idx) => write!(f, "store \x1b[33m{idx}\x1b[0m"),
+ CreateLocal => write!(f, "create local"),
+ LoadLocal(idx) => write!(f, "load local \x1b[33m{idx}\x1b[0m"),
+ StoreLocal(idx) => write!(f, "store local \x1b[33m{idx}\x1b[0m"),
+ DiscardLocals(count) => write!(f, "discard locals \x1b[35m{count}\x1b[0m"),
LoadGlobal(name) => write!(f, "load global \x1b[36m{name}\x1b[0m"),
StoreGlobal(name) => write!(f, "store global \x1b[36m{name}\x1b[0m"),
Const(idx) => write!(f, "const \x1b[33m{idx}\x1b[0m"),
@@ -98,7 +99,7 @@ impl Display for Instruction {
False => write!(f, "push \x1b[34mfalse\x1b[0m"),
Nil => write!(f, "push \x1b[34mnil\x1b[0m"),
Dup => write!(f, "duplicate"),
- Discard(count) => write!(f, "discard \x1b[33m{count}\x1b[0m"),
+ Discard(count) => write!(f, "discard \x1b[35m{count}\x1b[0m"),
UnaryOp(op) => write!(f, "unary \x1b[32m{op:?}\x1b[0m"),
BinaryOp(op) => write!(f, "binary \x1b[32m{op:?}\x1b[0m"),
NewList(len) => write!(f, "list \x1b[35m{len}\x1b[0m"),
diff --git a/matrix/src/compiler.rs b/matrix/src/compiler.rs
index b535369..49594ad 100644
--- a/matrix/src/compiler.rs
+++ b/matrix/src/compiler.rs
@@ -1,10 +1,12 @@
use std::{fmt::Display, rc::Rc, cell::RefCell};
-use crate::{ast::{Stmt, Expr, Assign}, chunk::{Function, Instruction}, chunk::{Chunk, self}, value::Value, Result};
+use crate::{ast::Expr, chunk::{Function, Instruction}, chunk::{Chunk, self}, value::Value, Result};
-pub type Globals = Rc<RefCell<Vec<Rc<str>>>>;
+use Instruction as I;
+use Value as V;
+use Expr as E;
pub struct CompilerBuilder<'c> {
- globals: Globals,
+ globals: Rc<RefCell<Vec<Rc<str>>>>,
repl: bool,
debug: bool,
name: Rc<str>,
@@ -33,7 +35,7 @@ impl<'c> CompilerBuilder<'c> {
self
}
- pub fn globals(mut self, globals: Globals) -> Self {
+ pub fn globals(mut self, globals: Rc<RefCell<Vec<Rc<str>>>>) -> Self {
self.globals = globals;
self
}
@@ -55,7 +57,7 @@ impl<'c> CompilerBuilder<'c> {
globals: self.globals,
repl: self.repl,
debug: self.debug,
- scope: 0,
+ scopes: Vec::new(),
locals: Vec::new(),
chunk: Chunk::new(),
loop_top: Vec::new(),
@@ -74,7 +76,7 @@ pub struct Compiler<'c> {
root_is_block: bool,
- scope: usize,
+ scopes: Vec<usize>,
chunk: Chunk,
loop_top: Vec<(usize, usize)>,
@@ -94,8 +96,10 @@ struct Local {
pub enum Error {
Undefined(Rc<str>),
Redefined(Rc<str>),
+ InvAssign(Expr),
InvContinue,
InvBreak,
+ NotImplemented(&'static str),
}
impl std::error::Error for self::Error {}
@@ -106,8 +110,10 @@ impl Display for self::Error {
match self {
Undefined(name) => write!(f, "value {name} is undefined"),
Redefined(name) => write!(f, "cannot redefine {name} in the same scope"),
+ InvAssign(expr) => write!(f, "cannot assign to {expr:?}"),
InvContinue => write!(f, "cannot continue outside a loop"),
InvBreak => write!(f, "cannot break outside a loop"),
+ NotImplemented(str) => write!(f, "{str} is not implemented yet")
}
}
}
@@ -127,45 +133,34 @@ impl<'c> Compiler<'c> {
if self.root_is_block {
self.root_is_block = false;
} else {
- self.scope += 1;
+ self.scopes.push(self.locals.len())
}
}
- fn get_scope_start(&self, scope: usize) -> usize {
- let mut stack_cutoff = None;
- for (i, local) in self.locals.iter().enumerate() {
- if local.scope == scope {
- stack_cutoff = Some(i);
- break;
- }
- }
- if let Some(cutoff) = stack_cutoff {
- cutoff
- } else {
- self.locals.len()
+ fn collapse_scopes(&mut self, top_scope: usize) {
+ let mut cutoff = usize::MAX;
+ while self.scopes.len() > top_scope {
+ cutoff = self.scopes.pop().unwrap()
}
- }
-
- fn get_scope_diff(&self, scope: usize) -> usize {
- let cutoff = self.get_scope_start(scope);
- self.locals.len() - cutoff
+ if cutoff < self.locals.len() {
+ self.emit(Instruction::DiscardLocals((self.locals.len() - cutoff) as u16));
+ self.locals.truncate(cutoff);
+ };
}
fn end_scope(&mut self) {
- let cutoff = self.get_scope_start(self.scope);
+ let Some(cutoff) = self.scopes.pop() else {
+ return;
+ };
if cutoff < self.locals.len() {
- self.emit(Instruction::Discard((self.locals.len() - cutoff) as u16));
+ self.emit(Instruction::DiscardLocals((self.locals.len() - cutoff) as u16));
self.locals.truncate(cutoff);
};
- if self.scope != 0 {
- self.scope -= 1;
- }
}
- fn create_local(&mut self, name: Rc<str>) -> Rc<Local> {
- let local = Local { name, idx: self.locals.len(), scope: self.scope };
+ fn create_local(&mut self, name: Rc<str>) {
+ let local = Local { name, idx: self.locals.len(), scope: self.scopes.len()};
self.locals.push(Rc::new(local));
- self.locals[self.locals.len() - 1].clone()
}
fn create_global(&mut self, name: Rc<str>) -> usize {
@@ -174,13 +169,14 @@ impl<'c> Compiler<'c> {
c
}
- fn create_local_checked(&mut self, name: Rc<str>) -> Result<Rc<Local>> {
+ fn create_local_checked(&mut self, name: Rc<str>) -> Result<()> {
if let Some(local) = self.find_local(&name) {
- if local.scope == self.scope {
+ if local.scope == self.scopes.len() {
return Err(Error::Redefined(name).into())
}
};
- Ok(self.create_local(name))
+ self.create_local(name);
+ Ok(())
}
fn create_global_checked(&mut self, name: Rc<str>) -> Result<usize> {
@@ -219,16 +215,14 @@ impl<'c> Compiler<'c> {
}
fn can_make_globals(&self) -> bool {
- self.repl && self.parent.is_none() && self.scope == 0
+ self.repl && self.parent.is_none() && self.scopes.len() == 0
}
fn compile_value(&mut self, val: &Value) {
- use Value::*;
- use Instruction as I;
match val {
- Nil => self.emit(I::Nil),
- Bool(b) => if *b { self.emit(I::True) } else { self.emit(I::False) },
- Int(i) => {
+ V::Nil => self.emit(I::Nil),
+ V::Bool(b) => if *b { self.emit(I::True) } else { self.emit(I::False) },
+ V::Int(i) => {
if let Ok(i) = i16::try_from(*i) {
self.emit(I::Int(i));
} else {
@@ -241,132 +235,26 @@ impl<'c> Compiler<'c> {
- fn compile_expr(&mut self, expr: &Expr) -> Result<()> {
- use Expr::*;
- use Instruction as I;
- match expr {
- Literal(val) => self.compile_value(val),
- Ident(name) => {
- if let Some(local) = self.find_local(name) {
- self.emit(I::Load(local.idx as u16));
- } else if let Some(global) = self.find_global(name) {
- self.emit(I::LoadGlobal(global as u16));
- } else {
- return Err(Error::Undefined(name.clone()).into())
- };
- },
- UnaryOp(expr, op) => {
- self.compile_expr(expr)?;
- self.emit(I::UnaryOp(*op));
- },
- BinaryOp(lhs, rhs, op) => {
- self.compile_expr(lhs)?;
- self.compile_expr(rhs)?;
- self.emit(I::BinaryOp(*op));
- },
- Index(_, _) => todo!("index"),
- FnCall(fun, params) => {
- for expr in params {
- self.compile_expr(expr)?;
- }
- self.compile_expr(fun)?;
- self.emit(I::Call(params.len() as u8));
- },
- FieldAccess(_, _) => todo!("field access"),
- List(list) => {
- for expr in list {
- self.compile_expr(expr)?;
- }
- self.emit(I::NewList(list.len() as u16));
- },
- Matrix(mat) => {
- for expr in &mat.2 {
- self.compile_expr(expr)?;
- }
- self.emit(I::NewMatrix(mat.2.len() as u16, mat.1 as u8));
- },
- Table(table) => {
- for (key, value) in table {
- self.compile_expr(key)?;
- self.compile_expr(value)?;
- }
- self.emit(I::NewTable(table.len() as u16));
- },
- And(lhs, rhs) => {
- self.compile_expr(lhs)?;
- self.emit(I::Dup);
- let jmpidx = self.emit_temp();
- self.compile_expr(rhs)?;
- self.re_emit(I::JumpFalse(self.cur()), jmpidx);
- },
- Or(lhs, rhs) => {
- self.compile_expr(lhs)?;
- self.emit(I::Dup);
- let jmpidx = self.emit_temp();
- self.compile_expr(rhs)?;
- self.re_emit(I::JumpTrue(self.cur()), jmpidx);
- },
- };
- Ok(())
- }
-
fn finish_loop(&mut self) {
- use Instruction as I;
self.loop_top.pop();
while let Some(tmp) = self.loop_bot.pop() {
self.re_emit(I::Jump(self.cur()), tmp as usize);
}
}
- fn compile_assign(&mut self, assign: &Assign) -> Result<()> {
- use Assign as A;
- use Expr as E;
- use Instruction as I;
- match assign {
- A::Expr(expr) => self.compile_expr(expr)?,
- A::Assign(lhs, rhs) => {
- self.compile_assign(rhs)?;
- match lhs {
- E::Ident(name) => {
- if let Some(global) = self.find_global(&name) {
- self.emit(I::Dup);
- self.emit(I::StoreGlobal(global as u16));
- } else if let Some(local) = self.find_local(&name) {
- self.emit(I::Dup);
- self.emit(I::Store(local.idx as u16));
- } else if self.can_make_globals() {
- let global = self.create_global(name.clone());
- self.emit(I::Dup);
- self.emit(I::StoreGlobal(global as u16));
- } else {
- self.create_local(name.clone());
- self.emit(I::Dup);
- }
- },
- E::Index(_, _) => todo!("index"),
- E::FieldAccess(_, _) => todo!("field access"),
- _ => panic!("this should be handeled by the parser!!!")
- }
- }
- };
- Ok(())
- }
-
- fn compile_stmt(&mut self, stmt: &Stmt) -> Result<()> {
- use Stmt::*;
- use Instruction as I;
- match stmt {
- NoOp => {},
- If(cond, ifb, elseb) => {
+ fn compile_expr(&mut self, expr: &Expr) -> Result<()> {
+ match expr {
+ E::NoOp => {},
+ E::If(cond, ifb, elseb) => {
self.compile_expr(cond)?;
let jmpidx = self.emit_temp();
- self.compile_stmt(ifb)?;
+ self.compile_expr(ifb)?;
self.re_emit(I::JumpFalse(self.cur()), jmpidx);
if let Some(elseb) = elseb {
- self.compile_stmt(elseb)?;
+ self.compile_expr(elseb)?;
}
},
- Function(name, params, body) => {
+ E::Function(name, params, body) => {
let chunk = self.compile_function(name.clone(), params, body)?;
let fun = Value::Function(Rc::new(
chunk::Function {
@@ -376,98 +264,182 @@ impl<'c> Compiler<'c> {
}
));
self.emit_const(fun);
+ self.emit(I::Dup);
if self.can_make_globals() {
let idx = self.create_global_checked(name.clone())?;
self.emit(I::StoreGlobal(idx as u16));
} else {
self.create_local_checked(name.clone())?;
+ self.emit(I::CreateLocal);
}
},
- Loop(stmt) => {
+ E::Loop(expr) => {
let idx = self.cur();
- self.loop_top.push((idx as usize, self.scope));
- self.compile_stmt(stmt)?;
+ self.loop_top.push((idx as usize, self.scopes.len()));
+ self.compile_expr(expr)?;
+ self.emit(I::Discard(1));
self.emit(I::Jump(idx));
self.finish_loop();
+ self.emit(I::Nil);
},
- While(cond, stmt) => {
+ E::While(cond, expr) => {
let top = self.cur();
self.compile_expr(cond)?;
let jmpidx = self.emit_temp();
- self.loop_top.push((top as usize, self.scope));
- self.compile_stmt(stmt)?;
+ self.loop_top.push((top as usize, self.scopes.len()));
+ self.compile_expr(expr)?;
+ self.emit(I::Discard(1));
self.emit(I::Jump(top));
self.re_emit(I::JumpFalse(self.cur()), jmpidx);
self.finish_loop();
+ self.emit(I::Nil);
},
- DoWhile(cond, stmt) => {
+ E::DoWhile(expr, cond) => {
let top = self.cur();
- self.loop_top.push((top as usize, self.scope));
- self.compile_stmt(stmt)?;
+ self.loop_top.push((top as usize, self.scopes.len()));
+ self.compile_expr(expr)?;
+ self.emit(I::Discard(1));
self.compile_expr(cond)?;
self.emit(I::JumpTrue(top));
self.finish_loop();
+ self.emit(I::Nil);
},
- Block(block) => {
+ E::Block(block) => {
self.begin_scope();
- for stmt in block {
- self.compile_stmt(stmt)?;
+ for (i, expr) in block.iter().enumerate() {
+ self.compile_expr(expr)?;
+ if i + 1 != block.len() {
+ self.emit(I::Discard(1));
+ }
}
self.end_scope();
},
- Expr(expr) => {
- self.compile_expr(expr)?;
- self.emit(I::Discard(1));
- },
- Assign(assign) => {
- self.compile_assign(assign)?;
- self.emit(I::Discard(1));
- }
- Let(name, expr) => {
+ E::Let(name, expr) => {
self.compile_expr(expr)?;
+ self.emit(I::Dup);
if self.can_make_globals() {
let global = self.create_global_checked(name.clone())?;
self.emit(I::StoreGlobal(global as u16));
} else {
self.create_local_checked(name.clone())?;
+ self.emit(I::CreateLocal);
}
},
- Continue => {
+ E::Continue => {
let top = self.loop_top.pop();
if let Some((top, scope)) = top {
- let diff = self.get_scope_diff(scope) as u16;
- if diff > 0 {
- self.emit(I::Discard(diff));
- }
+ self.collapse_scopes(scope);
self.emit(I::Jump(top as u16));
} else {
return Err(Error::InvContinue.into())
}
},
- Break => {
+ E::Break => {
let top = self.loop_top.pop();
if let Some((_, scope)) = top {
- self.emit(I::Discard(self.get_scope_diff(scope) as u16));
+ self.collapse_scopes(scope);
let tmpidx = self.emit_temp();
self.loop_bot.push(tmpidx);
} else {
return Err(Error::InvBreak.into())
}
},
- Return(expr) => {
+ E::Return(expr) => {
self.compile_expr(expr)?;
self.emit(I::Return);
},
+ E::Literal(val) => self.compile_value(val),
+ E::Ident(name) => {
+ if let Some(local) = self.find_local(name) {
+ self.emit(I::LoadLocal(local.idx as u16));
+ } else if let Some(global) = self.find_global(name) {
+ self.emit(I::LoadGlobal(global as u16));
+ } else {
+ return Err(self::Error::Undefined(name.clone()).into())
+ };
+ },
+ E::Assign(lhs, rhs) => {
+ self.compile_expr(rhs)?;
+ self.emit(I::Dup);
+ match lhs.as_ref() {
+ E::Ident(name) => {
+ if let Some(local) = self.find_local(&name) {
+ self.emit(I::StoreLocal(local.idx as u16));
+ } else if let Some(global) = self.find_global(&name) {
+ self.emit(I::StoreGlobal(global as u16));
+ } else if self.can_make_globals() {
+ let global = self.create_global_checked(name.clone())?;
+ self.emit(I::StoreGlobal(global as u16));
+ } else {
+ self.create_local_checked(name.clone())?;
+ self.emit(I::CreateLocal);
+ }
+ },
+ _ => return Err(self::Error::InvAssign(*lhs.clone()).into())
+ }
+ }
+ E::UnaryOp(expr, op) => {
+ self.compile_expr(expr)?;
+ self.emit(I::UnaryOp(*op));
+ },
+ E::BinaryOp(lhs, rhs, op) => {
+ self.compile_expr(lhs)?;
+ self.compile_expr(rhs)?;
+ self.emit(I::BinaryOp(*op));
+ },
+ E::Index(_, _) => return Err(self::Error::NotImplemented("indexing").into()),
+ E::FnCall(fun, params) => {
+ for expr in params {
+ self.compile_expr(expr)?;
+ }
+ self.compile_expr(fun)?;
+ self.emit(I::Call(params.len() as u8));
+ },
+ E::FieldAccess(_, _) => return Err(self::Error::NotImplemented("filed access").into()),
+ E::List(list) => {
+ for expr in list {
+ self.compile_expr(expr)?;
+ }
+ self.emit(I::NewList(list.len() as u16));
+ },
+ E::Matrix(mat) => {
+ for expr in &mat.2 {
+ self.compile_expr(expr)?;
+ }
+ self.emit(I::NewMatrix(mat.2.len() as u16, mat.1 as u8));
+ },
+ E::Table(table) => {
+ for (key, value) in table {
+ self.compile_expr(key)?;
+ self.compile_expr(value)?;
+ }
+ self.emit(I::NewTable(table.len() as u16));
+ },
+ E::And(lhs, rhs) => {
+ self.compile_expr(lhs)?;
+ self.emit(I::Dup);
+ let jmpidx = self.emit_temp();
+ self.compile_expr(rhs)?;
+ self.re_emit(I::JumpFalse(self.cur()), jmpidx);
+ },
+ E::Or(lhs, rhs) => {
+ self.compile_expr(lhs)?;
+ self.emit(I::Dup);
+ let jmpidx = self.emit_temp();
+ self.compile_expr(rhs)?;
+ self.re_emit(I::JumpTrue(self.cur()), jmpidx);
+ },
};
Ok(())
}
- fn compile_function(&mut self, name: Rc<str>, params: &Vec<Rc<str>>, body: &Box<Stmt>) -> Result<Chunk> {
+ fn compile_function(&mut self, name: Rc<str>, params: &Vec<Rc<str>>, body: &Box<Expr>) -> Result<Chunk> {
let mut compiler = self.child(name);
for name in params {
compiler.create_local(name.clone());
+ compiler.emit(I::CreateLocal);
}
- compiler.compile_stmt(body)?;
+ compiler.compile_expr(body)?;
compiler.finish()?;
Ok(compiler.chunk)
}
@@ -493,7 +465,6 @@ impl<'c> Compiler<'c> {
}
fn finish(&mut self) -> Result<()> {
- use Instruction as I;
let ins = match self.chunk.code.last() {
Some(ins) => ins.clone(),
None => {
@@ -506,16 +477,8 @@ impl<'c> Compiler<'c> {
}
};
match ins {
- I::Discard(amt) if self.repl => {
- self.chunk.code.pop().unwrap();
- if amt > 1 {
- self.emit(I::Discard(amt - 1));
- }
- self.emit(I::Return);
- }
I::Return => {},
_ => {
- self.emit(I::Nil);
self.emit(I::Return);
}
};
@@ -532,13 +495,13 @@ impl<'c> Compiler<'c> {
pub fn compile(
&mut self,
- body: &Stmt,
+ body: &Expr,
) -> Result<Rc<Function>> {
- if let Stmt::Block(_) = body {
+ if let Expr::Block(_) = body {
self.root_is_block = true;
}
self.chunk = Chunk::new();
- self.compile_stmt(body)?;
+ self.compile_expr(body)?;
self.finish()?;
let fun = Function { name: self.name.clone(), body: self.chunk.clone(), arity: 0 };
Ok(Rc::new(fun))
diff --git a/matrix/src/parse.rs b/matrix/src/parse.rs
index 9d1237b..046b86d 100644
--- a/matrix/src/parse.rs
+++ b/matrix/src/parse.rs
@@ -1,7 +1,11 @@
use std::{fmt::Display, rc::Rc};
use num_complex::Complex64;
-use crate::{lex::{Lexer, self, Token}, ast::{Expr, BinaryOp, UnaryOp, Stmt, Assign, optimize, self}, gc::Gc, value::{Value, self}, Result};
+use crate::{lex::{Lexer, self, Token}, ast::{Expr, BinaryOp, UnaryOp, optimize}, gc::Gc, value::{Value, self}, Result};
+
+use Value as V;
+use Expr as E;
+use Token as T;
pub struct ParserBuilder {
optimize: bool
@@ -73,7 +77,7 @@ macro_rules! expr_parser {
$pattern => {
$parser.lexer.next_token_nl()?;
let temp = $parser.$fn()?;
- expr = Expr::BinaryOp(Box::new(expr), Box::new(temp), BinaryOp::from(tok))
+ expr = E::BinaryOp(Box::new(expr), Box::new(temp), BinaryOp::from(tok))
}
_ => break
}
@@ -89,7 +93,7 @@ macro_rules! expr_parser_reverse {
Ok(match tok {
$pattern => {
$parser.lexer.next_token_nl()?;
- Expr::BinaryOp(Box::new(expr), Box::new($parser.$cur()?), BinaryOp::from(tok))
+ E::BinaryOp(Box::new(expr), Box::new($parser.$cur()?), BinaryOp::from(tok))
}
_ => expr
})
@@ -117,11 +121,11 @@ impl Parser {
}
fn parse_fn_call(&mut self) -> Result<Vec<Expr>> {
- self.force_token(Token::LeftParen)?;
+ self.force_token(T::LeftParen)?;
let mut params = Vec::new();
loop {
let expr = match self.lexer.peek_token()? {
- Token::RightParen => {
+ T::RightParen => {
self.lexer.next_token()?;
break
},
@@ -130,8 +134,8 @@ impl Parser {
params.push(expr);
let next = self.lexer.next_token()?;
match next {
- Token::Comma => continue,
- Token::RightParen => break,
+ T::Comma => continue,
+ T::RightParen => break,
_ => return Err(Error::UnexpectedToken(next).into())
};
}
@@ -139,11 +143,11 @@ impl Parser {
}
fn parse_index(&mut self) -> Result<Vec<Expr>> {
- self.force_token(Token::LeftBrack)?;
+ self.force_token(T::LeftBrack)?;
let mut indicies = Vec::new();
loop {
let expr = match self.lexer.peek_token()? {
- Token::RightBrack => {
+ T::RightBrack => {
self.lexer.next_token()?;
break
},
@@ -152,8 +156,8 @@ impl Parser {
indicies.push(expr);
let next = self.lexer.next_token()?;
match next {
- Token::SemiColon => continue,
- Token::RightBrack => break,
+ T::SemiColon => continue,
+ T::RightBrack => break,
_ => return Err(Error::UnexpectedToken(next).into())
};
}
@@ -164,13 +168,13 @@ impl Parser {
let mut part = Vec::new();
loop {
let expr = match self.lexer.peek_token()? {
- Token::SemiColon => break,
- Token::RightBrack => break,
+ T::SemiColon => break,
+ T::RightBrack => break,
_ => self.parse_expr()?
};
part.push(expr);
match self.lexer.peek_token()? {
- Token::Comma => {
+ T::Comma => {
self.lexer.next_token()?;
},
_ => {},
@@ -180,20 +184,20 @@ impl Parser {
}
fn parse_matrix(&mut self) -> Result<Expr> {
- self.force_token(Token::LeftBrack)?;
+ self.force_token(T::LeftBrack)?;
let mut parts = Vec::new();
loop {
let part = self.parse_matrix_part()?;
parts.push(part);
let next = self.lexer.next_token()?;
match next {
- Token::SemiColon => continue,
- Token::RightBrack => break,
+ T::SemiColon => continue,
+ T::RightBrack => break,
_ => return Err(Error::UnexpectedToken(next).into()),
};
}
if parts.len() == 1 {
- Ok(Expr::List(parts.pop().unwrap()))
+ Ok(E::List(parts.pop().unwrap()))
} else {
let codomain = parts[0].len();
let domain = parts.len();
@@ -207,86 +211,241 @@ impl Parser {
while let Some(part) = parts.pop() {
data.extend(part);
}
- Ok(Expr::Matrix((domain, codomain, data)))
+ Ok(E::Matrix((domain, codomain, data)))
}
}
fn parse_table_key(&mut self) -> Result<Expr> {
let tok = self.lexer.next_token()?;
Ok(match tok {
- Token::LeftBrack => {
+ T::LeftBrack => {
let expr = self.parse_expr()?;
- self.force_token(Token::RightBrack)?;
+ self.force_token(T::RightBrack)?;
expr
},
- Token::Ident(ident) => Expr::Ident(ident),
- Token::String(string) => Expr::Literal(Value::String(string.to_string().into())),
+ T::Ident(ident) => E::Ident(ident),
+ T::String(string) => E::Literal(V::String(string.to_string().into())),
_ => return Err(Error::UnexpectedToken(tok).into())
})
}
fn parse_table(&mut self) -> Result<Expr> {
- self.force_token(Token::LeftLeftBrace)?;
+ self.force_token(T::LeftLeftBrace)?;
let mut table = Vec::new();
- if self.lexer.peek_token()? == Token::RightRightBrace {
+ if self.lexer.peek_token()? == T::RightRightBrace {
self.lexer.next_token()?;
- return Ok(Expr::Table(table))
+ return Ok(E::Table(table))
}
loop {
let key = self.parse_table_key()?;
- self.force_token(Token::Assign)?;
+ self.force_token(T::Assign)?;
let value = self.parse_expr()?;
table.push((key, value));
let next = self.lexer.next_token()?;
match next {
- Token::Comma => continue,
- Token::RightRightBrace => break,
+ T::Comma => continue,
+ T::RightRightBrace => break,
_ => return Err(Error::UnexpectedToken(next).into())
}
}
- Ok(Expr::Table(table))
+ Ok(E::Table(table))
}
fn parse_paren(&mut self) -> Result<Expr> {
- self.force_token(Token::LeftParen)?;
+ self.force_token(T::LeftParen)?;
let expr = self.parse_expr()?;
- self.force_token(Token::RightParen)?;
+ self.force_token(T::RightParen)?;
Ok(expr)
}
- fn parse_term(&mut self) -> Result<Expr> {
- use Token::*;
- let tok = self.lexer.peek_token()?;
+ fn parse_params(&mut self) -> Result<Vec<Rc<str>>> {
+ use T::*;
+ let tok = self.lexer.next_token()?;
match tok {
- LeftBrack => return self.parse_matrix(),
- LeftLeftBrace => return self.parse_table(),
- LeftParen => return self.parse_paren(),
- _ => ()
+ Ident(ident) => return Ok(vec![ident]),
+ LeftParen => (),
+ _ => return Err(Error::UnexpectedToken(tok).into()),
+ }
+
+ let mut params = Vec::new();
+
+ if self.lexer.peek_token()? == T::RightParen {
+ self.lexer.next_token()?;
+ return Ok(params);
+ }
+
+ loop {
+ let ident = self.parse_ident()?;
+ params.push(ident);
+ let next = self.lexer.next_token()?;
+ match next {
+ Comma => continue,
+ RightParen => break,
+ _ => return Err(Error::UnexpectedToken(next).into()),
+ }
+ }
+
+ Ok(params)
+ }
+
+ fn parse_ident(&mut self) -> Result<Rc<str>> {
+ if let T::Ident(ident) = self.lexer.next_token()? {
+ Ok(ident)
+ } else {
+ Err(Error::ExpectedTokenName("Ident").into())
+ }
+ }
+
+ fn parse_ident_nl(&mut self) -> Result<Rc<str>> {
+ if let T::Ident(ident) = self.lexer.next_token_nl()? {
+ Ok(ident)
+ } else {
+ Err(Error::ExpectedTokenName("Ident").into())
+ }
+ }
+
+ fn parse_function(&mut self) -> Result<Expr> {
+ self.force_token(T::Function)?;
+ let ident = self.parse_ident()?;
+ let params = match self.lexer.peek_token()? {
+ T::LeftBrace => vec![],
+ _ => self.parse_params()?,
+ };
+ let expr = self.parse_expr()?;
+ Ok(E::Function(ident, params, Box::new(expr)))
+ }
+
+ fn parse_do_while(&mut self) -> Result<Expr> {
+ self.force_token(T::Do)?;
+ let expr = Box::new(self.parse_expr()?);
+ self.force_token(T::While)?;
+ let cond = Box::new(self.parse_expr()?);
+ Ok(E::DoWhile(expr, cond))
+ }
+
+ fn parse_while(&mut self) -> Result<Expr> {
+ self.force_token(T::While)?;
+ let cond = Box::new(self.parse_expr()?);
+ let expr = Box::new(self.parse_expr()?);
+ Ok(E::While(cond, expr))
+ }
+
+ fn parse_loop(&mut self) -> Result<Expr> {
+ self.force_token(T::Loop)?;
+ let expr = self.parse_expr()?;
+ Ok(E::Loop(Box::new(expr)))
+ }
+
+ fn parse_if(&mut self) -> Result<Expr> {
+ self.force_token(T::If)?;
+ let cond = Box::new(self.parse_expr()?);
+ let expr = Box::new(self.parse_expr()?);
+
+ if self.lexer.peek_token()? != T::Else {
+ return Ok(E::If(cond, expr, None))
}
self.lexer.next_token()?;
+
+ if self.lexer.peek_token()? == T::If {
+ Ok(E::If(cond, expr, Some(Box::new(self.parse_if()?))))
+ } else {
+ Ok(E::If(cond, expr, Some(Box::new(self.parse_expr()?))))
+ }
+ }
+
+ fn parse_let(&mut self) -> Result<Expr> {
+ self.force_token(T::Let)?;
+ let ident = self.parse_ident_nl()?;
+ if self.lexer.peek_token_nl()? == T::Assign {
+ self.force_token_nl(T::Assign)?;
+ Ok(E::Let(ident, Box::new(self.parse_expr()?)))
+ } else {
+ Ok(E::Let(ident, Box::new(E::Literal(V::Nil))))
+ }
+ }
+
+ fn parse_return(&mut self) -> Result<Expr> {
+ self.force_token(T::Return)?;
+ Ok(E::Return(Box::new(self.parse_expr()?)))
+ }
+
+ fn parse_block(&mut self) -> Result<Expr> {
+ let mut block = Vec::new();
+ self.force_token(T::LeftBrace)?;
+ loop {
+ let expr = match self.lexer.peek_token()? {
+ T::RightBrace => break,
+ T::SemiColon => {
+ self.lexer.next_token()?;
+ continue;
+ }
+ _ => self.parse_expr()?
+ };
+ block.push(expr);
+ let next = self.lexer.next_token()?;
+ match next {
+ T::SemiColon => continue,
+ T::RightBrace => break,
+ _ => return Err(Error::UnexpectedToken(next).into())
+ }
+ }
+ if self.lexer.peek_token()? == T::RightBrace {
+ self.lexer.next_token()?;
+ }
+ Ok(E::Block(block))
+ }
+
+ fn parse_value(&mut self) -> Result<Expr> {
+ let tok = self.lexer.next_token()?;
Ok(match tok {
- Nil => Expr::Literal(Value::Nil),
- Int(i) => Expr::Literal(Value::Int(i)),
- Float(f) => Expr::Literal(Value::Float(f)),
- Complex(c) => Expr::Literal(Value::Complex(Complex64::new(0.0, c))),
- Regex(r) => Expr::Literal(Value::Regex(Gc::new(r.into()))),
- String(s) => Expr::Literal(Value::String(s.to_string().into())),
- True => Expr::Literal(Value::Bool(true)),
- False => Expr::Literal(Value::Bool(false)),
- Ident(ident) => Expr::Ident(ident),
+ T::Nil => E::Literal(V::Nil),
+ T::Int(i) => E::Literal(V::Int(i)),
+ T::Float(f) => E::Literal(V::Float(f)),
+ T::Complex(c) => E::Literal(V::Complex(Complex64::new(0.0, c))),
+ T::Regex(r) => E::Literal(V::Regex(Gc::new(r.into()))),
+ T::String(s) => E::Literal(V::String(s.to_string().into())),
+ T::True => E::Literal(V::Bool(true)),
+ T::False => E::Literal(V::Bool(false)),
+ T::Ident(ident) => E::Ident(ident),
_ => return Err(Error::UnexpectedToken(tok).into()),
})
}
+ fn parse_term(&mut self) -> Result<Expr> {
+ use T::*;
+ match self.lexer.peek_token()? {
+ Function => self.parse_function(),
+ Do => self.parse_do_while(),
+ While => self.parse_while(),
+ Let => self.parse_let(),
+ LeftBrace => self.parse_block(),
+ Return => self.parse_return(),
+ If => self.parse_if(),
+ Loop => self.parse_loop(),
+ Break => {
+ self.lexer.next_token()?;
+ Ok(E::Break)
+ },
+ Continue => {
+ self.lexer.next_token()?;
+ Ok(E::Continue)
+ },
+ LeftBrack => self.parse_matrix(),
+ LeftLeftBrace => self.parse_table(),
+ LeftParen => self.parse_paren(),
+ _ => self.parse_value(),
+ }
+ }
+
fn parse_expr_expr_access(&mut self) -> Result<Expr> {
let mut expr = self.parse_term()?;
loop {
let tok = self.lexer.peek_token()?;
match tok {
- Token::Access => {
- self.force_token(Token::Access)?;
+ T::Access => {
+ self.force_token(T::Access)?;
let temp = self.parse_term()?;
- expr = Expr::FieldAccess(Box::new(expr), Box::new(temp));
+ expr = E::FieldAccess(Box::new(expr), Box::new(temp));
},
_ => break
}
@@ -299,13 +458,13 @@ impl Parser {
loop {
let tok = self.lexer.peek_token()?;
match tok {
- Token::LeftBrack => {
+ T::LeftBrack => {
let index = self.parse_index()?;
- expr = Expr::Index(Box::new(expr), index);
+ expr = E::Index(Box::new(expr), index);
},
- Token::LeftParen => {
+ T::LeftParen => {
let params = self.parse_fn_call()?;
- expr = Expr::FnCall(Box::new(expr), params);
+ expr = E::FnCall(Box::new(expr), params);
}
_ => break
}
@@ -316,13 +475,13 @@ impl Parser {
fn parse_expr_unary(&mut self) -> Result<Expr> {
let tok = self.lexer.peek_token_nl()?;
Ok(match tok {
- Token::Not => {
+ T::Not => {
self.lexer.next_token()?;
- Expr::UnaryOp(Box::new(self.parse_expr_unary()?), UnaryOp::Not)
+ E::UnaryOp(Box::new(self.parse_expr_unary()?), UnaryOp::Not)
}
- Token::Subtract => {
+ T::Subtract => {
self.lexer.next_token()?;
- Expr::UnaryOp(Box::new(self.parse_expr_unary()?), UnaryOp::Negate)
+ E::UnaryOp(Box::new(self.parse_expr_unary()?), UnaryOp::Negate)
}
_ => self.parse_expr_call()?
})
@@ -331,42 +490,42 @@ impl Parser {
fn parse_expr_pow(&mut self) -> Result<Expr> {
expr_parser_reverse!(
self,
- Token::Power,
+ T::Power,
parse_expr_unary,
parse_expr_pow
)
}
fn parse_expr_mult(&mut self) -> Result<Expr> {
- expr_parser!(self, Token::Multiply | Token::Divide | Token::Modulo, parse_expr_pow)
+ expr_parser!(self, T::Multiply | T::Divide | T::Modulo, parse_expr_pow)
}
fn parse_expr_add(&mut self) -> Result<Expr> {
- expr_parser!(self, Token::Add | Token::Subtract, parse_expr_mult)
+ expr_parser!(self, T::Add | T::Subtract, parse_expr_mult)
}
fn parse_expr_shift(&mut self) -> Result<Expr> {
expr_parser!(
self,
- Token::BitwiseShiftLeft | Token::BitwiseShiftRight,
+ T::BitwiseShiftLeft | T::BitwiseShiftRight,
parse_expr_add
)
}
fn parse_expr_bit_and(&mut self) -> Result<Expr> {
- expr_parser!(self, Token::BitwiseAnd, parse_expr_shift)
+ expr_parser!(self, T::BitwiseAnd, parse_expr_shift)
}
fn parse_expr_bit_or(&mut self) -> Result<Expr> {
- expr_parser!(self, Token::BitwiseOr, parse_expr_bit_and)
+ expr_parser!(self, T::BitwiseOr, parse_expr_bit_and)
}
fn parse_expr_compare(&mut self) -> Result<Expr> {
expr_parser!(
self,
- Token::Equal | Token::NotEqual |
- Token::LessThan | Token::GreaterThan |
- Token::LessEqual | Token::GreaterEqual,
+ T::Equal | T::NotEqual |
+ T::LessThan | T::GreaterThan |
+ T::LessEqual | T::GreaterEqual,
parse_expr_bit_or
)
}
@@ -376,10 +535,10 @@ impl Parser {
loop {
let tok = self.lexer.peek_token()?;
match tok {
- Token::And => {
- self.force_token(Token::And)?;
+ T::And => {
+ self.force_token(T::And)?;
let temp = self.parse_expr_compare()?;
- expr = Expr::And(Box::new(expr), Box::new(temp));
+ expr = E::And(Box::new(expr), Box::new(temp));
},
_ => break
}
@@ -387,15 +546,15 @@ impl Parser {
Ok(expr)
}
- fn parse_expr(&mut self) -> Result<Expr> {
+ fn parse_expr_or(&mut self) -> Result<Expr> {
let mut expr = self.parse_expr_and()?;
loop {
let tok = self.lexer.peek_token()?;
match tok {
- Token::Or => {
- self.force_token(Token::Or)?;
+ T::Or => {
+ self.force_token(T::Or)?;
let temp = self.parse_expr_and()?;
- expr = Expr::Or(Box::new(expr), Box::new(temp));
+ expr = E::Or(Box::new(expr), Box::new(temp));
},
_ => break
}
@@ -403,215 +562,39 @@ impl Parser {
Ok(expr)
}
- fn parse_assign(&mut self) -> Result<Assign> {
- let expr = self.parse_expr()?;
- if !expr.is_assignable() {
- return Ok(Assign::Expr(expr));
- }
- if self.lexer.peek_token()? != Token::Assign {
- return Ok(Assign::Expr(expr));
- }
- self.lexer.next_token()?;
- Ok(Assign::Assign(expr, Box::new(self.parse_assign()?)))
- }
-
- fn parse_params(&mut self) -> Result<Vec<Rc<str>>> {
- use Token::*;
- let tok = self.lexer.next_token()?;
- match tok {
- Ident(ident) => return Ok(vec![ident]),
- LeftParen => (),
- _ => return Err(Error::UnexpectedToken(tok).into()),
- }
-
- let mut params = Vec::new();
-
- if self.lexer.peek_token()? == Token::RightParen {
- self.lexer.next_token()?;
- return Ok(params);
- }
-
- loop {
- let ident = self.parse_ident()?;
- params.push(ident);
- let next = self.lexer.next_token()?;
- match next {
- Comma => continue,
- RightParen => break,
- _ => return Err(Error::UnexpectedToken(next).into()),
- }
- }
-
- Ok(params)
- }
-
- fn parse_ident(&mut self) -> Result<Rc<str>> {
- if let Token::Ident(ident) = self.lexer.next_token()? {
- Ok(ident)
- } else {
- Err(Error::ExpectedTokenName("Ident").into())
- }
- }
-
- fn parse_ident_nl(&mut self) -> Result<Rc<str>> {
- if let Token::Ident(ident) = self.lexer.next_token_nl()? {
- Ok(ident)
- } else {
- Err(Error::ExpectedTokenName("Ident").into())
- }
- }
-
- fn parse_function(&mut self) -> Result<Stmt> {
- self.force_token(Token::Function)?;
- let ident = self.parse_ident()?;
- let params = match self.lexer.peek_token()? {
- Token::LeftBrace => vec![],
- _ => self.parse_params()?,
- };
- let stmt = self.parse_stmt()?;
- Ok(Stmt::Function(ident, params, Box::new(stmt)))
- }
-
- fn parse_do_while(&mut self) -> Result<Stmt> {
- self.force_token(Token::Do)?;
- let stmt = self.parse_stmt()?;
- self.force_token(Token::While)?;
- let expr = self.parse_expr()?;
- Ok(Stmt::DoWhile(expr, Box::new(stmt)))
- }
-
- fn parse_while(&mut self) -> Result<Stmt> {
- self.force_token(Token::While)?;
- let expr = self.parse_expr()?;
- let stmt = self.parse_stmt()?;
- Ok(Stmt::While(expr, Box::new(stmt)))
- }
-
- fn parse_loop(&mut self) -> Result<Stmt> {
- self.force_token(Token::Loop)?;
- let stmt = self.parse_stmt()?;
- Ok(Stmt::Loop(Box::new(stmt)))
- }
-
- fn parse_if(&mut self) -> Result<Stmt> {
- self.force_token(Token::If)?;
- let expr = self.parse_expr()?;
- let stmt = Box::new(self.parse_stmt()?);
-
- if self.lexer.peek_token()? != Token::Else {
- return Ok(Stmt::If(expr, stmt, None))
- }
- self.lexer.next_token()?;
-
- if self.lexer.peek_token()? == Token::If {
- Ok(Stmt::If(expr, stmt, Some(Box::new(self.parse_if()?))))
- } else {
- Ok(Stmt::If(expr, stmt, Some(Box::new(self.parse_stmt()?))))
- }
- }
-
- fn parse_let(&mut self) -> Result<Stmt> {
- self.force_token(Token::Let)?;
- let ident = self.parse_ident_nl()?;
- if self.lexer.peek_token_nl()? == Token::Assign {
- self.force_token_nl(Token::Assign)?;
- Ok(Stmt::Let(ident, self.parse_expr()?))
- } else {
- Ok(Stmt::Let(ident, Expr::Literal(Value::Nil)))
- }
- }
-
- fn parse_return(&mut self) -> Result<Stmt> {
- self.force_token(Token::Return)?;
- Ok(Stmt::Return(self.parse_expr()?))
- }
-
- fn parse_stmt(&mut self) -> Result<Stmt> {
- use Token::*;
- match self.lexer.peek_token()? {
- Do => self.parse_do_while(),
- While => self.parse_while(),
- Let => self.parse_let(),
- LeftBrace => self.parse_block(),
- Return => self.parse_return(),
- If => self.parse_if(),
- Loop => self.parse_loop(),
- Break => {
- self.lexer.next_token()?;
- Ok(Stmt::Break)
- },
- Continue => {
- self.lexer.next_token()?;
- Ok(Stmt::Continue)
- },
- _ => {
- let assign = self.parse_assign()?;
- Ok(match assign {
- ast::Assign::Expr(expr) => Stmt::Expr(expr),
- _ => Stmt::Assign(assign),
- })
+ fn parse_expr(&mut self) -> Result<Expr> {
+ let expr = self.parse_expr_or()?;
+ let tok = self.lexer.peek_token_nl()?;
+ Ok(match tok {
+ T::Assign => {
+ self.lexer.next_token_nl()?;
+ E::Assign(Box::new(expr),Box::new(self.parse_expr()?))
}
- }
+ _ => expr
+ })
}
- fn parse_block(&mut self) -> Result<Stmt> {
+ fn parse_root(&mut self) -> Result<Expr> {
let mut block = Vec::new();
- self.force_token(Token::LeftBrace)?;
loop {
- let stmt = match self.lexer.peek_token()? {
- Token::RightBrace => break,
- Token::SemiColon => {
+ match self.lexer.peek_token()? {
+ T::Eof => break,
+ T::SemiColon => {
self.lexer.next_token()?;
- continue;
+ continue
}
- _ => self.parse_stmt()?
+ _ => {}
};
- block.push(stmt);
- let next = self.lexer.next_token()?;
- match next {
- Token::SemiColon => continue,
- Token::RightBrace => break,
- _ => return Err(Error::UnexpectedToken(next).into())
- }
- }
- if self.lexer.peek_token()? == Token::RightBrace {
- self.lexer.next_token()?;
- }
- Ok(Stmt::Block(block))
- }
-
- fn parse_root_stmt(&mut self) -> Result<Stmt> {
- if self.lexer.peek_token()? == Token::Function {
- self.parse_function()
- } else {
- self.parse_stmt()
+ let expr = self.parse_expr()?;
+ block.push(expr);
}
+ Ok(E::Block(block))
}
- pub fn parse<T: Into<String>>(&mut self, into: T) -> Result<Stmt> {
+ pub fn parse<T: Into<String>>(&mut self, into: T) -> Result<Expr> {
let lexer = Lexer::new(into);
self.lexer = lexer;
-
- let mut block = Vec::new();
- loop {
- let expr = match self.lexer.peek_token()? {
- Token::Eof => break,
- Token::SemiColon => {
- self.lexer.next_token()?;
- continue;
- }
- _ => self.parse_root_stmt()?
- };
- block.push(expr);
- let next = self.lexer.next_token()?;
- match next {
- Token::SemiColon => continue,
- Token::Eof => break,
- _ => return Err(Error::UnexpectedToken(next).into())
- }
- }
-
- let ast = Stmt::Block(block);
+ let ast = self.parse_root()?;
if self.optimize {
Ok(optimize(ast)?)
} else {
diff --git a/matrix/src/vm.rs b/matrix/src/vm.rs
index c63761f..d5408c9 100644
--- a/matrix/src/vm.rs
+++ b/matrix/src/vm.rs
@@ -1,5 +1,5 @@
-use std::{collections::HashMap, rc::Rc, fmt::{Debug, Display}, usize, cell::RefCell, ops::{Index, IndexMut}};
-use crate::{value::{Value, self, ValueMap}, gc::Gc, chunk::{Function, Instruction}, compiler::Globals, Result};
+use std::{rc::Rc, fmt::{Debug, Display}, usize, ops::{Index, IndexMut}, collections::HashMap};
+use crate::{value::{Value, self, ValueMap}, gc::Gc, chunk::{Function, Instruction}, Result};
#[derive(Debug)]
pub enum Error {
@@ -105,9 +105,9 @@ impl StackFrame {
pub struct Vm {
stack: Stack<Value>,
+ locals: Stack<Value>,
frames: Vec<StackFrame>,
- global: HashMap<String, Value>,
- global_table: Globals,
+ globals: HashMap<u16, Value>,
}
impl Vm {
@@ -123,16 +123,12 @@ impl Vm {
pub fn new() -> Self {
Self {
stack: Stack::new(),
+ locals: Stack::new(),
frames: Vec::new(),
- global: HashMap::new(),
- global_table: Rc::new(RefCell::new(Vec::new()))
+ globals: HashMap::new(),
}
}
- pub fn globals(&self) -> Globals {
- self.global_table.clone()
- }
-
pub fn run(&mut self, fun: Rc<Function>) -> Result<Value> {
let mut frame = StackFrame::new(&self, fun);
loop {
@@ -141,20 +137,20 @@ impl Vm {
frame.ip += 1;
match ins {
NoOp => {},
- Load(idx) => self.push(self.stack[frame.bp + idx as usize].clone()),
- Store(idx) => self.stack[frame.bp + idx as usize] = self.pop(),
+ CreateLocal => self.locals.push(self.stack.pop()),
+ LoadLocal(idx) => {self.stack.push(self.locals[idx as usize].clone());},
+ StoreLocal(idx) => self.stack[frame.bp + idx as usize] = self.pop(),
+ DiscardLocals(count) => {self.locals.truncate(self.locals.len() - count as usize)},
LoadGlobal(idx) => {
- let name = self.global_table.borrow()[idx as usize].clone();
- let val = self.global
- .get(name.as_ref())
- .ok_or(self::Error::UndefinedGlobal(name.into()))?
+ let val = self.globals
+ .get(&idx)
+ .unwrap()
.clone();
self.stack.push(val);
},
StoreGlobal(idx) => {
- let name = self.global_table.borrow()[idx as usize].clone();
- let store = self.pop();
- self.global.insert(name.to_string(), store);
+ let val = self.pop();
+ self.globals.insert(idx, val);
},
Const(idx) => self.push(frame.fun.body.constants[idx as usize].clone()),
Int(i) => self.push(Value::Int(i as i64)),