From 671301383b965bb3d59bcda03e0775733e96d398 Mon Sep 17 00:00:00 2001 From: Freya Murphy Date: Tue, 20 Feb 2024 18:58:54 -0500 Subject: [PATCH] lang is not expr based --- matrix-bin/src/main.rs | 1 - matrix/src/ast.rs | 231 +++++++---------- matrix/src/chunk.rs | 21 +- matrix/src/compiler.rs | 409 +++++++++++++---------------- matrix/src/parse.rs | 575 ++++++++++++++++++++--------------------- matrix/src/vm.rs | 34 ++- 6 files changed, 590 insertions(+), 681 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), @@ -52,34 +54,24 @@ pub enum Expr { And(Box, Box), Or(Box, Box), -} -#[derive(Debug, Clone, PartialEq)] -pub enum Assign { - Expr(Expr), - Assign(Expr, Box) -} + Assign(Box, Box), -#[derive(Debug, Clone, PartialEq)] -pub enum Stmt { - NoOp, + If(Box, Box, Option>), + Function(Rc, Vec>, Box), - If(Expr, Box, Option>), - Function(Rc, Vec>, Box), - Loop(Box), - While(Expr, Box), - DoWhile(Expr, Box), + Loop(Box), + While(Box, Box), + DoWhile(Box, Box), - Block(Vec), - Expr(Expr), + Block(Vec), - Let(Rc, Expr), - Assign(Assign), + Let(Rc, Box), Continue, Break, - Return(Expr), + Return(Box), } impl Neg for BinaryOp { @@ -156,181 +148,156 @@ impl Not for Expr { } } -fn optimize_expr(expr: Expr) -> Result { - use Expr::*; +pub fn optimize(expr: Expr) -> Result { + 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::>>()?) } - 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::>>()?), - 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::>>()?)), - 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::>>()?), - 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 { - 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 { - use Stmt::*; - Ok(match stmt { - Block(b) => { - let b: Vec = + E::Block(b) => { + let len = b.len(); + let b: Vec = b.into_iter() .map(optimize) - .collect::>>()? + .collect::>>()? .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 { - 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>>>; +use Instruction as I; +use Value as V; +use Expr as E; pub struct CompilerBuilder<'c> { - globals: Globals, + globals: Rc>>>, repl: bool, debug: bool, name: Rc, @@ -33,7 +35,7 @@ impl<'c> CompilerBuilder<'c> { self } - pub fn globals(mut self, globals: Globals) -> Self { + pub fn globals(mut self, globals: Rc>>>) -> 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, chunk: Chunk, loop_top: Vec<(usize, usize)>, @@ -94,8 +96,10 @@ struct Local { pub enum Error { Undefined(Rc), Redefined(Rc), + 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; - } + fn collapse_scopes(&mut self, top_scope: usize) { + let mut cutoff = usize::MAX; + while self.scopes.len() > top_scope { + cutoff = self.scopes.pop().unwrap() } - if let Some(cutoff) = stack_cutoff { - cutoff - } else { - self.locals.len() - } - } - - 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) -> Rc { - let local = Local { name, idx: self.locals.len(), scope: self.scope }; + fn create_local(&mut self, name: Rc) { + 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) -> usize { @@ -174,13 +169,14 @@ impl<'c> Compiler<'c> { c } - fn create_local_checked(&mut self, name: Rc) -> Result> { + fn create_local_checked(&mut self, name: Rc) -> 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) -> Result { @@ -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,65 +235,194 @@ impl<'c> Compiler<'c> { + fn finish_loop(&mut self) { + self.loop_top.pop(); + while let Some(tmp) = self.loop_bot.pop() { + self.re_emit(I::Jump(self.cur()), tmp as usize); + } + } + fn compile_expr(&mut self, expr: &Expr) -> Result<()> { - use Expr::*; - use Instruction as I; match expr { - Literal(val) => self.compile_value(val), - Ident(name) => { + E::NoOp => {}, + E::If(cond, ifb, elseb) => { + self.compile_expr(cond)?; + let jmpidx = self.emit_temp(); + self.compile_expr(ifb)?; + self.re_emit(I::JumpFalse(self.cur()), jmpidx); + if let Some(elseb) = elseb { + self.compile_expr(elseb)?; + } + }, + E::Function(name, params, body) => { + let chunk = self.compile_function(name.clone(), params, body)?; + let fun = Value::Function(Rc::new( + chunk::Function { + name: name.clone(), + arity: params.len(), + body: chunk + } + )); + 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); + } + }, + E::Loop(expr) => { + let idx = self.cur(); + 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); + }, + 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.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); + }, + E::DoWhile(expr, cond) => { + let top = self.cur(); + 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); + }, + E::Block(block) => { + self.begin_scope(); + for (i, expr) in block.iter().enumerate() { + self.compile_expr(expr)?; + if i + 1 != block.len() { + self.emit(I::Discard(1)); + } + } + self.end_scope(); + }, + 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); + } + }, + E::Continue => { + let top = self.loop_top.pop(); + if let Some((top, scope)) = top { + self.collapse_scopes(scope); + self.emit(I::Jump(top as u16)); + } else { + return Err(Error::InvContinue.into()) + } + }, + E::Break => { + let top = self.loop_top.pop(); + if let Some((_, scope)) = top { + self.collapse_scopes(scope); + let tmpidx = self.emit_temp(); + self.loop_bot.push(tmpidx); + } else { + return Err(Error::InvBreak.into()) + } + }, + 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::Load(local.idx as u16)); + 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(Error::Undefined(name.clone()).into()) + return Err(self::Error::Undefined(name.clone()).into()) }; }, - UnaryOp(expr, op) => { + 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)); }, - BinaryOp(lhs, rhs, op) => { + E::BinaryOp(lhs, rhs, op) => { self.compile_expr(lhs)?; self.compile_expr(rhs)?; self.emit(I::BinaryOp(*op)); }, - Index(_, _) => todo!("index"), - FnCall(fun, params) => { + 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)); }, - FieldAccess(_, _) => todo!("field access"), - List(list) => { + 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)); }, - Matrix(mat) => { + 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)); }, - Table(table) => { + E::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) => { + 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); }, - Or(lhs, rhs) => { + E::Or(lhs, rhs) => { self.compile_expr(lhs)?; self.emit(I::Dup); let jmpidx = self.emit_temp(); @@ -310,164 +433,13 @@ impl<'c> Compiler<'c> { 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) => { - self.compile_expr(cond)?; - let jmpidx = self.emit_temp(); - self.compile_stmt(ifb)?; - self.re_emit(I::JumpFalse(self.cur()), jmpidx); - if let Some(elseb) = elseb { - self.compile_stmt(elseb)?; - } - }, - Function(name, params, body) => { - let chunk = self.compile_function(name.clone(), params, body)?; - let fun = Value::Function(Rc::new( - chunk::Function { - name: name.clone(), - arity: params.len(), - body: chunk - } - )); - self.emit_const(fun); - 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())?; - } - }, - Loop(stmt) => { - let idx = self.cur(); - self.loop_top.push((idx as usize, self.scope)); - self.compile_stmt(stmt)?; - self.emit(I::Jump(idx)); - self.finish_loop(); - }, - While(cond, stmt) => { - 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.emit(I::Jump(top)); - self.re_emit(I::JumpFalse(self.cur()), jmpidx); - self.finish_loop(); - }, - DoWhile(cond, stmt) => { - let top = self.cur(); - self.loop_top.push((top as usize, self.scope)); - self.compile_stmt(stmt)?; - self.compile_expr(cond)?; - self.emit(I::JumpTrue(top)); - self.finish_loop(); - }, - Block(block) => { - self.begin_scope(); - for stmt in block { - self.compile_stmt(stmt)?; - } - 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) => { - self.compile_expr(expr)?; - 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())?; - } - }, - 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.emit(I::Jump(top as u16)); - } else { - return Err(Error::InvContinue.into()) - } - }, - Break => { - let top = self.loop_top.pop(); - if let Some((_, scope)) = top { - self.emit(I::Discard(self.get_scope_diff(scope) as u16)); - let tmpidx = self.emit_temp(); - self.loop_bot.push(tmpidx); - } else { - return Err(Error::InvBreak.into()) - } - }, - Return(expr) => { - self.compile_expr(expr)?; - self.emit(I::Return); - }, - }; - Ok(()) - } - - fn compile_function(&mut self, name: Rc, params: &Vec>, body: &Box) -> Result { + fn compile_function(&mut self, name: Rc, params: &Vec>, body: &Box) -> Result { 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> { - 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> { - 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> { - 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 { - 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,216 +211,55 @@ 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 { 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 { - 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 { - 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 { - use Token::*; - let tok = self.lexer.peek_token()?; - match tok { - LeftBrack => return self.parse_matrix(), - LeftLeftBrace => return self.parse_table(), - LeftParen => return self.parse_paren(), - _ => () - } - 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), - _ => return Err(Error::UnexpectedToken(tok).into()), - }) - } - - fn parse_expr_expr_access(&mut self) -> Result { - let mut expr = self.parse_term()?; - loop { - let tok = self.lexer.peek_token()?; - match tok { - Token::Access => { - self.force_token(Token::Access)?; - let temp = self.parse_term()?; - expr = Expr::FieldAccess(Box::new(expr), Box::new(temp)); - }, - _ => break - } - } - Ok(expr) - } - - fn parse_expr_call(&mut self) -> Result { - let mut expr = self.parse_expr_expr_access()?; - loop { - let tok = self.lexer.peek_token()?; - match tok { - Token::LeftBrack => { - let index = self.parse_index()?; - expr = Expr::Index(Box::new(expr), index); - }, - Token::LeftParen => { - let params = self.parse_fn_call()?; - expr = Expr::FnCall(Box::new(expr), params); - } - _ => break - } - } - Ok(expr) - } - - fn parse_expr_unary(&mut self) -> Result { - let tok = self.lexer.peek_token_nl()?; - Ok(match tok { - Token::Not => { - self.lexer.next_token()?; - Expr::UnaryOp(Box::new(self.parse_expr_unary()?), UnaryOp::Not) - } - Token::Subtract => { - self.lexer.next_token()?; - Expr::UnaryOp(Box::new(self.parse_expr_unary()?), UnaryOp::Negate) - } - _ => self.parse_expr_call()? - }) - } - - fn parse_expr_pow(&mut self) -> Result { - expr_parser_reverse!( - self, - Token::Power, - parse_expr_unary, - parse_expr_pow - ) - } - - fn parse_expr_mult(&mut self) -> Result { - expr_parser!(self, Token::Multiply | Token::Divide | Token::Modulo, parse_expr_pow) - } - - fn parse_expr_add(&mut self) -> Result { - expr_parser!(self, Token::Add | Token::Subtract, parse_expr_mult) - } - - fn parse_expr_shift(&mut self) -> Result { - expr_parser!( - self, - Token::BitwiseShiftLeft | Token::BitwiseShiftRight, - parse_expr_add - ) - } - - fn parse_expr_bit_and(&mut self) -> Result { - expr_parser!(self, Token::BitwiseAnd, parse_expr_shift) - } - - fn parse_expr_bit_or(&mut self) -> Result { - expr_parser!(self, Token::BitwiseOr, parse_expr_bit_and) - } - - fn parse_expr_compare(&mut self) -> Result { - expr_parser!( - self, - Token::Equal | Token::NotEqual | - Token::LessThan | Token::GreaterThan | - Token::LessEqual | Token::GreaterEqual, - parse_expr_bit_or - ) - } - - fn parse_expr_and(&mut self) -> Result { - let mut expr = self.parse_expr_compare()?; - loop { - let tok = self.lexer.peek_token()?; - match tok { - Token::And => { - self.force_token(Token::And)?; - let temp = self.parse_expr_compare()?; - expr = Expr::And(Box::new(expr), Box::new(temp)); - }, - _ => break - } - } - Ok(expr) - } - - fn parse_expr(&mut self) -> Result { - let mut expr = self.parse_expr_and()?; - loop { - let tok = self.lexer.peek_token()?; - match tok { - Token::Or => { - self.force_token(Token::Or)?; - let temp = self.parse_expr_and()?; - expr = Expr::Or(Box::new(expr), Box::new(temp)); - }, - _ => break - } - } - Ok(expr) - } - - fn parse_assign(&mut self) -> Result { - 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>> { - use Token::*; + use T::*; let tok = self.lexer.next_token()?; match tok { Ident(ident) => return Ok(vec![ident]), @@ -426,7 +269,7 @@ impl Parser { let mut params = Vec::new(); - if self.lexer.peek_token()? == Token::RightParen { + if self.lexer.peek_token()? == T::RightParen { self.lexer.next_token()?; return Ok(params); } @@ -446,7 +289,7 @@ impl Parser { } fn parse_ident(&mut self) -> Result> { - if let Token::Ident(ident) = self.lexer.next_token()? { + if let T::Ident(ident) = self.lexer.next_token()? { Ok(ident) } else { Err(Error::ExpectedTokenName("Ident").into()) @@ -454,81 +297,124 @@ impl Parser { } fn parse_ident_nl(&mut self) -> Result> { - if let Token::Ident(ident) = self.lexer.next_token_nl()? { + if let T::Ident(ident) = self.lexer.next_token_nl()? { Ok(ident) } else { Err(Error::ExpectedTokenName("Ident").into()) } } - fn parse_function(&mut self) -> Result { - self.force_token(Token::Function)?; + fn parse_function(&mut self) -> Result { + self.force_token(T::Function)?; let ident = self.parse_ident()?; let params = match self.lexer.peek_token()? { - Token::LeftBrace => vec![], + T::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 { - 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))) + Ok(E::Function(ident, params, Box::new(expr))) } - fn parse_while(&mut self) -> Result { - self.force_token(Token::While)?; + fn parse_do_while(&mut self) -> Result { + 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 { + 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 { + self.force_token(T::Loop)?; let expr = self.parse_expr()?; - let stmt = self.parse_stmt()?; - Ok(Stmt::While(expr, Box::new(stmt))) + Ok(E::Loop(Box::new(expr))) } - fn parse_loop(&mut self) -> Result { - self.force_token(Token::Loop)?; - let stmt = self.parse_stmt()?; - Ok(Stmt::Loop(Box::new(stmt))) - } + fn parse_if(&mut self) -> Result { + self.force_token(T::If)?; + let cond = Box::new(self.parse_expr()?); + let expr = Box::new(self.parse_expr()?); - fn parse_if(&mut self) -> Result { - 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)) + if self.lexer.peek_token()? != T::Else { + return Ok(E::If(cond, expr, None)) } self.lexer.next_token()?; - if self.lexer.peek_token()? == Token::If { - Ok(Stmt::If(expr, stmt, Some(Box::new(self.parse_if()?)))) + if self.lexer.peek_token()? == T::If { + Ok(E::If(cond, expr, Some(Box::new(self.parse_if()?)))) } else { - Ok(Stmt::If(expr, stmt, Some(Box::new(self.parse_stmt()?)))) + Ok(E::If(cond, expr, Some(Box::new(self.parse_expr()?)))) } } - fn parse_let(&mut self) -> Result { - self.force_token(Token::Let)?; + fn parse_let(&mut self) -> Result { + self.force_token(T::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()?)) + 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(Stmt::Let(ident, Expr::Literal(Value::Nil))) + Ok(E::Let(ident, Box::new(E::Literal(V::Nil)))) } } - fn parse_return(&mut self) -> Result { - self.force_token(Token::Return)?; - Ok(Stmt::Return(self.parse_expr()?)) + fn parse_return(&mut self) -> Result { + self.force_token(T::Return)?; + Ok(E::Return(Box::new(self.parse_expr()?))) } - fn parse_stmt(&mut self) -> Result { - use Token::*; + fn parse_block(&mut self) -> Result { + 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 { + let tok = self.lexer.next_token()?; + Ok(match tok { + 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 { + use T::*; match self.lexer.peek_token()? { + Function => self.parse_function(), Do => self.parse_do_while(), While => self.parse_while(), Let => self.parse_let(), @@ -538,80 +424,177 @@ impl Parser { Loop => self.parse_loop(), Break => { self.lexer.next_token()?; - Ok(Stmt::Break) + Ok(E::Break) }, Continue => { self.lexer.next_token()?; - Ok(Stmt::Continue) + Ok(E::Continue) }, - _ => { - let assign = self.parse_assign()?; - Ok(match assign { - ast::Assign::Expr(expr) => Stmt::Expr(expr), - _ => Stmt::Assign(assign), - }) - } + LeftBrack => self.parse_matrix(), + LeftLeftBrace => self.parse_table(), + LeftParen => self.parse_paren(), + _ => self.parse_value(), } } - fn parse_block(&mut self) -> Result { - let mut block = Vec::new(); - self.force_token(Token::LeftBrace)?; + fn parse_expr_expr_access(&mut self) -> Result { + let mut expr = self.parse_term()?; loop { - let stmt = match self.lexer.peek_token()? { - Token::RightBrace => break, - Token::SemiColon => { - self.lexer.next_token()?; - 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()) + let tok = self.lexer.peek_token()?; + match tok { + T::Access => { + self.force_token(T::Access)?; + let temp = self.parse_term()?; + expr = E::FieldAccess(Box::new(expr), Box::new(temp)); + }, + _ => break } } - if self.lexer.peek_token()? == Token::RightBrace { - self.lexer.next_token()?; - } - Ok(Stmt::Block(block)) + Ok(expr) } - fn parse_root_stmt(&mut self) -> Result { - if self.lexer.peek_token()? == Token::Function { - self.parse_function() - } else { - self.parse_stmt() + fn parse_expr_call(&mut self) -> Result { + let mut expr = self.parse_expr_expr_access()?; + loop { + let tok = self.lexer.peek_token()?; + match tok { + T::LeftBrack => { + let index = self.parse_index()?; + expr = E::Index(Box::new(expr), index); + }, + T::LeftParen => { + let params = self.parse_fn_call()?; + expr = E::FnCall(Box::new(expr), params); + } + _ => break + } } + Ok(expr) } - pub fn parse>(&mut self, into: T) -> Result { + fn parse_expr_unary(&mut self) -> Result { + let tok = self.lexer.peek_token_nl()?; + Ok(match tok { + T::Not => { + self.lexer.next_token()?; + E::UnaryOp(Box::new(self.parse_expr_unary()?), UnaryOp::Not) + } + T::Subtract => { + self.lexer.next_token()?; + E::UnaryOp(Box::new(self.parse_expr_unary()?), UnaryOp::Negate) + } + _ => self.parse_expr_call()? + }) + } + + fn parse_expr_pow(&mut self) -> Result { + expr_parser_reverse!( + self, + T::Power, + parse_expr_unary, + parse_expr_pow + ) + } + + fn parse_expr_mult(&mut self) -> Result { + expr_parser!(self, T::Multiply | T::Divide | T::Modulo, parse_expr_pow) + } + + fn parse_expr_add(&mut self) -> Result { + expr_parser!(self, T::Add | T::Subtract, parse_expr_mult) + } + + fn parse_expr_shift(&mut self) -> Result { + expr_parser!( + self, + T::BitwiseShiftLeft | T::BitwiseShiftRight, + parse_expr_add + ) + } + + fn parse_expr_bit_and(&mut self) -> Result { + expr_parser!(self, T::BitwiseAnd, parse_expr_shift) + } + + fn parse_expr_bit_or(&mut self) -> Result { + expr_parser!(self, T::BitwiseOr, parse_expr_bit_and) + } + + fn parse_expr_compare(&mut self) -> Result { + expr_parser!( + self, + T::Equal | T::NotEqual | + T::LessThan | T::GreaterThan | + T::LessEqual | T::GreaterEqual, + parse_expr_bit_or + ) + } + + fn parse_expr_and(&mut self) -> Result { + let mut expr = self.parse_expr_compare()?; + loop { + let tok = self.lexer.peek_token()?; + match tok { + T::And => { + self.force_token(T::And)?; + let temp = self.parse_expr_compare()?; + expr = E::And(Box::new(expr), Box::new(temp)); + }, + _ => break + } + } + Ok(expr) + } + + fn parse_expr_or(&mut self) -> Result { + let mut expr = self.parse_expr_and()?; + loop { + let tok = self.lexer.peek_token()?; + match tok { + T::Or => { + self.force_token(T::Or)?; + let temp = self.parse_expr_and()?; + expr = E::Or(Box::new(expr), Box::new(temp)); + }, + _ => break + } + } + Ok(expr) + } + + fn parse_expr(&mut self) -> Result { + 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_root(&mut self) -> Result { + let mut block = Vec::new(); + loop { + match self.lexer.peek_token()? { + T::Eof => break, + T::SemiColon => { + self.lexer.next_token()?; + continue + } + _ => {} + }; + let expr = self.parse_expr()?; + block.push(expr); + } + Ok(E::Block(block)) + } + + pub fn parse>(&mut self, into: T) -> Result { 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, + locals: Stack, frames: Vec, - global: HashMap, - global_table: Globals, + globals: HashMap, } 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) -> Result { 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)),