diff --git a/src/executor.rs b/src/executor.rs index ef6fc50..8268c20 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -1,12 +1,12 @@ use super::{Value, Type, Object}; use super::parser::{ParseTree, ParseError}; +use super::tokenizer::Op; use std::collections::HashMap; use std::fmt::Display; use std::error::Error; use std::io; use std::sync::{Arc, Mutex}; -use std::cell::RefCell; #[derive(Debug)] pub enum RuntimeError { @@ -104,155 +104,236 @@ where Ok(v) } - fn obj_locals(obj: &Arc>) -> HashMap>> { + fn _obj_locals(obj: &Arc>) -> HashMap>> { let guard = obj.lock().unwrap(); - let locals = guard.locals(); + let locals = guard._locals(); locals } - fn obj_globals(obj: &Arc>) -> HashMap>> { + fn _obj_globals(obj: &Arc>) -> HashMap>> { let guard = obj.lock().unwrap(); - let locals = guard.globals(); + let locals = guard._globals(); locals } pub fn exec(&mut self, tree: Box) -> Result { match *tree { - ParseTree::Add(x, y) => match (self.exec(x)?, self.exec(y)?) { - (Value::Int(x), Value::Int(y)) => Ok(Value::Int(x + y)), - (Value::Float(x), Value::Int(y)) => Ok(Value::Float(x + y as f64)), - (Value::Int(x), Value::Float(y)) => Ok(Value::Float(x as f64 + y)), - (Value::Float(x), Value::Float(y)) => Ok(Value::Float(x + y)), - (Value::String(x), Value::String(y)) => Ok(Value::String(format!("{x}{y}"))), - (Value::Array(xtype, x), Value::Array(ytype, y)) => { - if xtype != ytype { - return Err(RuntimeError::TypeError(xtype, ytype)); + ParseTree::Operator(op, args) => { + let args: Vec = args.into_iter() + .map(|x| self.exec(Box::new(x))).collect::>()?; + + match op { + Op::Add => match &args[..] { + [Value::Int(x), Value::Int(y)] => Ok(Value::Int(x + y)), + [Value::Float(x), Value::Int(y)] => Ok(Value::Float(x + *y as f64)), + [Value::Int(x), Value::Float(y)] => Ok(Value::Float(*x as f64 + y)), + [Value::Float(x), Value::Float(y)] => Ok(Value::Float(x + y)), + [Value::String(x), Value::String(y)] => Ok(Value::String(format!("{x}{y}"))), + [Value::Array(xtype, x), Value::Array(ytype, y)] => { + if xtype != ytype { + return Err(RuntimeError::TypeError(xtype.clone(), ytype.clone())); + } + + Ok(Value::Array(xtype.clone(), [x.clone(), y.clone()].concat())) + }, + [Value::Nil, x] => Ok(x.clone()), + [x, Value::Nil] => Ok(x.clone()), + [Value::Array(t, x), y] => { + let ytype = y.get_type(); + + if *t != ytype { + return Err(RuntimeError::TypeError(t.clone(), ytype)); + } + + // NOTE: use y's type instead of the arrays type. + // an `empty` array has Any type, but any value will have a fixed type. + // this converts the empty array into a typed array. + Ok(Value::Array(ytype, [x.clone(), vec![y.clone()]].concat())) + }, + [x, Value::Array(t, y)] => { + let xtype = x.get_type(); + + if *t != xtype { + return Err(RuntimeError::TypeError(t.clone(), xtype)); + } + + // NOTE: read above + Ok(Value::Array(xtype, [vec![x.clone()], y.clone()].concat())) + }, + _ => Err(RuntimeError::NoOverloadForTypes("+".into(), args)), } - - Ok(Value::Array(xtype, [x, y].concat())) - }, - (Value::Array(t, x), y) => { - let ytype = y.get_type(); - - if t != ytype { - return Err(RuntimeError::TypeError(t, ytype)); + Op::Sub => match &args[..] { + [Value::Int(x), Value::Int(y)] => Ok(Value::Int(x - y)), + [Value::Int(x), Value::Float(y)] => Ok(Value::Float(*x as f64 - y)), + [Value::Float(x), Value::Int(y)] => Ok(Value::Float(x - *y as f64)), + [Value::Float(x), Value::Float(y)] => Ok(Value::Float(x - y)), + [Value::Nil, x] => Ok(x.clone()), + [x, Value::Nil] => Ok(x.clone()), + _ => Err(RuntimeError::NoOverloadForTypes("-".into(), args)), } - - // NOTE: use y's type instead of the arrays type. - // an `empty` array has Any type, but any value will have a fixed type. - // this converts the empty array into a typed array. - Ok(Value::Array(ytype, [x, vec![y]].concat())) - }, - (x, Value::Array(t, y)) => { - let xtype = x.get_type(); - - if t != xtype { - return Err(RuntimeError::TypeError(t, xtype)); + Op::Mul => match &args[..] { + [Value::Int(x), Value::Int(y)] => Ok(Value::Int(x * y)), + [Value::Int(x), Value::Float(y)] => Ok(Value::Float(*x as f64 * y)), + [Value::Float(x), Value::Int(y)] => Ok(Value::Float(x * *y as f64)), + [Value::Float(x), Value::Float(y)] => Ok(Value::Float(x * y)), + [Value::Nil, x] => Ok(x.clone()), + [x, Value::Nil] => Ok(x.clone()), + _ => Err(RuntimeError::NoOverloadForTypes("*".into(), args)), } - - // NOTE: read above - Ok(Value::Array(xtype, [vec![x], y].concat())) - }, - (x, y) => Err(RuntimeError::NoOverloadForTypes("+".into(), vec![x, y])) - }, - ParseTree::Sub(x, y) => match (self.exec(x)?, self.exec(y)?) { - (Value::Int(x), Value::Int(y)) => Ok(Value::Int(x - y)), - (Value::Float(x), Value::Int(y)) => Ok(Value::Float(x - y as f64)), - (Value::Int(x), Value::Float(y)) => Ok(Value::Float(x as f64 - y)), - (Value::Float(x), Value::Float(y)) => Ok(Value::Float(x - y)), - (x, y) => Err(RuntimeError::NoOverloadForTypes("-".into(), vec![x, y])) - }, - ParseTree::Mul(x, y) => match (self.exec(x)?, self.exec(y)?) { - (Value::Int(x), Value::Int(y)) => Ok(Value::Int(x * y)), - (Value::Float(x), Value::Int(y)) => Ok(Value::Float(x * y as f64)), - (Value::Int(x), Value::Float(y)) => Ok(Value::Float(x as f64 * y)), - (Value::Float(x), Value::Float(y)) => Ok(Value::Float(x * y)), - (Value::String(x), Value::Int(y)) => Ok(Value::String(x.repeat(y as usize))), - (x, y) => Err(RuntimeError::NoOverloadForTypes("*".into(), vec![x, y])) - }, - ParseTree::Div(x, y) => match (self.exec(x)?, self.exec(y)?) { - (Value::Int(x), Value::Int(y)) => Ok(Value::Int(x / y)), - (Value::Float(x), Value::Int(y)) => Ok(Value::Float(x / y as f64)), - (Value::Int(x), Value::Float(y)) => Ok(Value::Float(x as f64 / y)), - (Value::Float(x), Value::Float(y)) => Ok(Value::Float(x / y)), - (x, y) => Err(RuntimeError::NoOverloadForTypes("*".into(), vec![x, y])) - }, - ParseTree::Exp(x, y) => match (self.exec(x)?, self.exec(y)?) { - (Value::Int(x), Value::Int(y)) => Ok(Value::Int(x.pow(y as u32))), - (Value::Int(x), Value::Float(y)) => Ok(Value::Float((x as f64).powf(y))), - (Value::Float(x), Value::Int(y)) => Ok(Value::Float(x.powf(y as f64))), - (Value::Float(x), Value::Float(y)) => Ok(Value::Float(x.powf(y))), - (x, y) => Err(RuntimeError::NoOverloadForTypes("**".into(), vec![x, y])), - }, - ParseTree::Mod(x, y) => match (self.exec(x)?, self.exec(y)?) { - (Value::Int(x), Value::Int(y)) => Ok(Value::Int(x % y)), - (Value::Float(x), Value::Int(y)) => Ok(Value::Float(x % y as f64)), - (Value::Int(x), Value::Float(y)) => Ok(Value::Float(x as f64 % y)), - (Value::Float(x), Value::Float(y)) => Ok(Value::Float(x % y)), - (x, y) => Err(RuntimeError::NoOverloadForTypes("%".into(), vec![x, y])), - }, - ParseTree::EqualTo(x, y) => match (self.exec(x)?, self.exec(y)?) { - (Value::Int(x), Value::Int(y)) => Ok(Value::Bool(x == y)), - (Value::Int(x), Value::Float(y)) => Ok(Value::Bool(x as f64 == y)), - (Value::Float(x), Value::Int(y)) => Ok(Value::Bool(x == y as f64)), - (Value::Float(x), Value::Float(y)) => Ok(Value::Bool(x == y)), - (Value::Bool(x), Value::Bool(y)) => Ok(Value::Bool(x == y)), - (Value::String(x), Value::String(y)) => Ok(Value::Bool(x == y)), - (x, y) => Err(RuntimeError::NoOverloadForTypes("==".into(), vec![x, y])), - }, - ParseTree::NotEqualTo(x, y) => match (self.exec(x)?, self.exec(y)?) { - (Value::Int(x), Value::Int(y)) => Ok(Value::Bool(x != y)), - (Value::Int(x), Value::Float(y)) => Ok(Value::Bool(x as f64 != y)), - (Value::Float(x), Value::Int(y)) => Ok(Value::Bool(x != y as f64)), - (Value::Float(x), Value::Float(y)) => Ok(Value::Bool(x != y)), - (Value::Bool(x), Value::Bool(y)) => Ok(Value::Bool(x != y)), - (Value::String(x), Value::String(y)) => Ok(Value::Bool(x != y)), - (x, y) => Err(RuntimeError::NoOverloadForTypes("!=".into(), vec![x, y])), - }, - ParseTree::GreaterThan(x, y) => match (self.exec(x)?, self.exec(y)?) { - (Value::Int(x), Value::Int(y)) => Ok(Value::Bool(x > y)), - (Value::Int(x), Value::Float(y)) => Ok(Value::Bool(x as f64 > y)), - (Value::Float(x), Value::Int(y)) => Ok(Value::Bool(x > y as f64)), - (Value::Float(x), Value::Float(y)) => Ok(Value::Bool(x > y)), - (x, y) => Err(RuntimeError::NoOverloadForTypes(">".into(), vec![x, y])), - }, - ParseTree::GreaterThanOrEqualTo(x, y) => match (self.exec(x)?, self.exec(y)?) { - (Value::Int(x), Value::Int(y)) => Ok(Value::Bool(x >= y)), - (Value::Int(x), Value::Float(y)) => Ok(Value::Bool(x as f64 >= y)), - (Value::Float(x), Value::Int(y)) => Ok(Value::Bool(x >= y as f64)), - (Value::Float(x), Value::Float(y)) => Ok(Value::Bool(x >= y)), - (x, y) => Err(RuntimeError::NoOverloadForTypes(">=".into(), vec![x, y])), - }, - ParseTree::LessThan(x, y) => match (self.exec(x)?, self.exec(y)?) { - (Value::Int(x), Value::Int(y)) => Ok(Value::Bool(x < y)), - (Value::Int(x), Value::Float(y)) => Ok(Value::Bool((x as f64) < y)), - (Value::Float(x), Value::Int(y)) => Ok(Value::Bool(x < y as f64)), - (Value::Float(x), Value::Float(y)) => Ok(Value::Bool(x < y)), - (x, y) => Err(RuntimeError::NoOverloadForTypes("<".into(), vec![x, y])), - }, - ParseTree::LessThanOrEqualTo(x, y) => match (self.exec(x)?, self.exec(y)?) { - (Value::Int(x), Value::Int(y)) => Ok(Value::Bool(x <= y)), - (Value::Int(x), Value::Float(y)) => Ok(Value::Bool(x as f64 <= y)), - (Value::Float(x), Value::Int(y)) => Ok(Value::Bool(x <= y as f64)), - (Value::Float(x), Value::Float(y)) => Ok(Value::Bool(x <= y)), - (x, y) => Err(RuntimeError::NoOverloadForTypes("<=".into(), vec![x, y])), - }, - ParseTree::Not(x) => match self.exec(x)? { - Value::Bool(x) => Ok(Value::Bool(!x)), - x => Err(RuntimeError::NoOverloadForTypes("not".into(), vec![x])) - }, - ParseTree::And(x, y) => match (self.exec(x)?, self.exec(y)?) { - (Value::Bool(x), Value::Bool(y)) => Ok(Value::Bool(x && y)), - (x, y) => Err(RuntimeError::NoOverloadForTypes("&&".into(), vec![x, y])) - }, - ParseTree::Or(x, y) => match (self.exec(x)?, self.exec(y)?) { - (Value::Bool(x), Value::Bool(y)) => Ok(Value::Bool(x || y)), - (x, y) => Err(RuntimeError::NoOverloadForTypes("||".into(), vec![x, y])) - }, + Op::Div => match &args[..] { + [Value::Int(x), Value::Int(y)] => Ok(Value::Int(x / y)), + [Value::Float(x), Value::Int(y)] => Ok(Value::Float(x / *y as f64)), + [Value::Int(x), Value::Float(y)] => Ok(Value::Float(*x as f64 / y)), + [Value::Float(x), Value::Float(y)] => Ok(Value::Float(x / y)), + [Value::Nil, x] => Ok(x.clone()), + [x, Value::Nil] => Ok(x.clone()), + _ => Err(RuntimeError::NoOverloadForTypes("/".into(), args)), + } + Op::Exp => match &args[..] { + [Value::Int(x), Value::Int(y)] => Ok(Value::Float((*x as f64).powf(*y as f64))), + [Value::Float(x), Value::Int(y)] => Ok(Value::Float(x.powf(*y as f64))), + [Value::Int(x), Value::Float(y)] => Ok(Value::Float((*x as f64).powf(*y))), + [Value::Float(x), Value::Float(y)] => Ok(Value::Float(x.powf(*y))), + [Value::Nil, x] => Ok(x.clone()), + [x, Value::Nil] => Ok(x.clone()), + _ => Err(RuntimeError::NoOverloadForTypes("**".into(), args)), + } + Op::Mod => match &args[..] { + [Value::Int(x), Value::Int(y)] => Ok(Value::Int(x % y)), + [Value::Float(x), Value::Int(y)] => Ok(Value::Float(x % *y as f64)), + [Value::Int(x), Value::Float(y)] => Ok(Value::Float(*x as f64 % y)), + [Value::Float(x), Value::Float(y)] => Ok(Value::Float(x % y)), + [Value::Nil, x] => Ok(x.clone()), + [x, Value::Nil] => Ok(x.clone()), + _ => Err(RuntimeError::NoOverloadForTypes("%".into(), args)), + } + Op::GreaterThan => match &args[..] { + [Value::Int(x), Value::Int(y)] => Ok(Value::Bool(x > y)), + [Value::Float(x), Value::Int(y)] => Ok(Value::Bool(*x > *y as f64)), + [Value::Int(x), Value::Float(y)] => Ok(Value::Bool(*x as f64 > *y)), + [Value::Float(x), Value::Float(y)] => Ok(Value::Bool(x > y)), + _ => Err(RuntimeError::NoOverloadForTypes(">".into(), args)), + } + Op::GreaterThanOrEqualTo => match &args[..] { + [Value::Int(x), Value::Int(y)] => Ok(Value::Bool(x >= y)), + [Value::Float(x), Value::Int(y)] => Ok(Value::Bool(*x >= *y as f64)), + [Value::Int(x), Value::Float(y)] => Ok(Value::Bool(*x as f64 >= *y)), + [Value::Float(x), Value::Float(y)] => Ok(Value::Bool(x >= y)), + _ => Err(RuntimeError::NoOverloadForTypes(">=".into(), args)), + } + Op::LessThan => match &args[..] { + [Value::Int(x), Value::Int(y)] => Ok(Value::Bool(x < y)), + [Value::Float(x), Value::Int(y)] => Ok(Value::Bool(*x < *y as f64)), + [Value::Int(x), Value::Float(y)] => Ok(Value::Bool((*x as f64) < *y)), + [Value::Float(x), Value::Float(y)] => Ok(Value::Bool(x < y)), + _ => Err(RuntimeError::NoOverloadForTypes("<".into(), args)), + } + Op::LessThanOrEqualTo => match &args[..] { + [Value::Int(x), Value::Int(y)] => Ok(Value::Bool(x <= y)), + [Value::Float(x), Value::Int(y)] => Ok(Value::Bool(*x <= *y as f64)), + [Value::Int(x), Value::Float(y)] => Ok(Value::Bool(*x as f64 <= *y)), + [Value::Float(x), Value::Float(y)] => Ok(Value::Bool(x <= y)), + _ => Err(RuntimeError::NoOverloadForTypes("<=".into(), args)), + } + Op::EqualTo => match &args[..] { + [Value::Int(x), Value::Int(y)] => Ok(Value::Bool(x == y)), + [Value::Float(x), Value::Int(y)] => Ok(Value::Bool(*x == *y as f64)), + [Value::Int(x), Value::Float(y)] => Ok(Value::Bool(*x as f64 == *y)), + [Value::Float(x), Value::Float(y)] => Ok(Value::Bool(x == y)), + _ => Err(RuntimeError::NoOverloadForTypes("==".into(), args)), + } + Op::NotEqualTo => match &args[..] { + [Value::Int(x), Value::Int(y)] => Ok(Value::Bool(x != y)), + [Value::Float(x), Value::Int(y)] => Ok(Value::Bool(*x != *y as f64)), + [Value::Int(x), Value::Float(y)] => Ok(Value::Bool(*x as f64 != *y)), + [Value::Float(x), Value::Float(y)] => Ok(Value::Bool(x != y)), + _ => Err(RuntimeError::NoOverloadForTypes("!=".into(), args)), + } + Op::Not => match &args[0] { + Value::Bool(b) => Ok(Value::Bool(!b)), + _ => Err(RuntimeError::NoOverloadForTypes("!".into(), args)), + } + Op::Or => match &args[..] { + [Value::Bool(x), Value::Bool(y)] => Ok(Value::Bool(*x || *y)), + [Value::Nil, x] => Ok(x.clone()), + [x, Value::Nil] => Ok(x.clone()), + _ => Err(RuntimeError::NoOverloadForTypes("||".into(), args)), + } + Op::And => match &args[..] { + [Value::Bool(x), Value::Bool(y)] => Ok(Value::Bool(*x && *y)), + [Value::Nil, x] => Ok(x.clone()), + [x, Value::Nil] => Ok(x.clone()), + _ => Err(RuntimeError::NoOverloadForTypes("&&".into(), args)), + } + Op::Compose => match &args[..] { + [_, v] => Ok(v.clone()), + _ => Err(RuntimeError::NoOverloadForTypes("~".into(), args)), + } + Op::Head => match &args[0] { + Value::Array(_, x) => Ok(x.first().ok_or(RuntimeError::EmptyArray)?.clone()), + _ => Err(RuntimeError::NoOverloadForTypes("head".into(), args)), + } + Op::Tail => match &args[0] { + Value::Array(t, x) => Ok(Value::Array(t.clone(), if x.len() > 0 { x[1..].to_vec() } else { vec![] })), + _ => Err(RuntimeError::NoOverloadForTypes("head".into(), args)), + } + Op::Init => match &args[0] { + Value::Array(t, x) => Ok(Value::Array(t.clone(), if x.len() > 0 { x[..x.len() - 1].to_vec() } else { vec![] })), + _ => Err(RuntimeError::NoOverloadForTypes("head".into(), args)), + } + Op::Fini => match &args[0] { + Value::Array(_, x) => Ok(x.last().ok_or(RuntimeError::EmptyArray)?.clone()), + _ => Err(RuntimeError::NoOverloadForTypes("head".into(), args)), + } + Op::Id => match &args[0] { + x => Ok(x.clone()), + } + Op::IntCast => match &args[0] { + Value::Int(x) => Ok(Value::Int(*x)), + Value::Float(x) => Ok(Value::Int(*x as i64)), + Value::Bool(x) => Ok(Value::Int(if *x { 1 } else { 0 })), + Value::String(x) => { + let r: i64 = x.parse().map_err(|_| RuntimeError::ParseFail(x.clone(), Type::Int))?; + Ok(Value::Int(r)) + } + x => Err(RuntimeError::NoOverloadForTypes("int".into(), vec![x.clone()])), + } + Op::FloatCast => match &args[0] { + Value::Int(x) => Ok(Value::Float(*x as f64)), + Value::Float(x) => Ok(Value::Float(*x)), + Value::Bool(x) => Ok(Value::Float(if *x { 1.0 } else { 0.0 })), + Value::String(x) => { + let r: f64 = x.parse().map_err(|_| RuntimeError::ParseFail(x.clone(), Type::Int))?; + Ok(Value::Float(r)) + } + x => Err(RuntimeError::NoOverloadForTypes("float".into(), vec![x.clone()])), + } + Op::BoolCast => match &args[0] { + Value::Int(x) => Ok(Value::Bool(*x != 0)), + Value::Float(x) => Ok(Value::Bool(*x != 0.0)), + Value::Bool(x) => Ok(Value::Bool(*x)), + Value::String(x) => Ok(Value::Bool(!x.is_empty())), + Value::Array(_, vec) => Ok(Value::Bool(!vec.is_empty())), + x => Err(RuntimeError::NoOverloadForTypes("bool".into(), vec![x.clone()])), + } + Op::StringCast => Ok(Value::String(format!("{}", &args[0]))), + Op::Print => match &args[0] { + Value::String(s) => { + println!("{s}"); + Ok(Value::Nil) + } + x => { + println!("{x}"); + Ok(Value::Nil) + } + } + _ => unreachable!(), + } + } ParseTree::Equ(ident, body, scope) => { if self.variable_exists(&ident) { Err(RuntimeError::ImmutableError(ident.clone())) @@ -281,27 +362,46 @@ where let g = self.globals.clone(); Executor::new(self.exprs, &mut self.globals) .locals(self.locals.clone()) - .add_local(func.name().unwrap().to_string(), Arc::new(Mutex::new(Object::function(func, g, self.locals.clone())))) + .add_local(func.name().unwrap().to_string(), + Arc::new(Mutex::new(Object::function( + func + .globals(g) + .locals(self.locals.clone()), HashMap::new(), HashMap::new())))) .exec(scope) }, - ParseTree::Compose(x, y) => { - self.exec(x)?; - self.exec(y) + ParseTree::FunctionCall(ident, args) => { + let obj = self.get_object_mut(&ident)?; + let v = Self::eval(obj)?; + + match v { + Value::Function(mut f) => { + let mut args: Vec<_> = args.into_iter() + .map(|x| Arc::new(Mutex::new(Object::variable(x, self.globals.clone(), self.locals.clone())))) + .collect(); + + for arg in &mut args { + Self::eval(arg)?; + } + + f.call(args) + }, + _ => Err(RuntimeError::FunctionUndefined(ident.clone())) + } }, - ParseTree::Id(x) => self.exec(x), + ParseTree::_FunctionCallLocal(_idx, _args) => todo!(), ParseTree::If(cond, body) => if match self.exec(cond)? { - Value::Float(f) => f != 0.0, - Value::Int(i) => i != 0, - Value::Bool(b) => b, - Value::String(s) => !s.is_empty(), - Value::Array(_, vec) => !vec.is_empty(), - Value::Nil => false, - x => return Err(RuntimeError::NoOverloadForTypes("?".into(), vec![x])), - } { - self.exec(body) - } else { - Ok(Value::Nil) - }, + Value::Float(f) => f != 0.0, + Value::Int(i) => i != 0, + Value::Bool(b) => b, + Value::String(s) => !s.is_empty(), + Value::Array(_, vec) => !vec.is_empty(), + Value::Nil => false, + x => return Err(RuntimeError::NoOverloadForTypes("?".into(), vec![x])), + } { + self.exec(body) + } else { + Ok(Value::Nil) + }, ParseTree::IfElse(cond, istrue, isfalse) => if match self.exec(cond)? { Value::Float(f) => f != 0.0, Value::Int(i) => i != 0, @@ -315,23 +415,6 @@ where } else { self.exec(isfalse) }, - ParseTree::FunctionCall(ident, args) => { - let obj = self.get_object_mut(&ident)?; - let globals = Self::obj_globals(obj); - let locals = Self::obj_locals(obj); - let v = Self::eval(obj)?; - - match v { - Value::Function(mut f) => { - let args = args.into_iter() - .map(|x| Object::variable(x, self.globals.clone(), self.locals.clone())) - .collect(); - - f.call(globals, locals, args) - }, - _ => Err(RuntimeError::FunctionUndefined(ident.clone())) - } - }, ParseTree::Variable(ident) => { let obj = self.get_object_mut(&ident)?; @@ -339,70 +422,8 @@ where Ok(v) }, - ParseTree::Constant(value) => Ok(value), - ParseTree::IntCast(x) => match self.exec(x)? { - Value::Int(x) => Ok(Value::Int(x)), - Value::Float(x) => Ok(Value::Int(x as i64)), - Value::Bool(x) => Ok(Value::Int(if x { 1 } else { 0 })), - Value::String(x) => { - let r: i64 = x.parse().map_err(|_| RuntimeError::ParseFail(x.clone(), Type::Int))?; - Ok(Value::Int(r)) - } - x => Err(RuntimeError::NoOverloadForTypes("int".into(), vec![x])), - }, - ParseTree::FloatCast(x) => match self.exec(x)? { - Value::Int(x) => Ok(Value::Float(x as f64)), - Value::Float(x) => Ok(Value::Float(x)), - Value::Bool(x) => Ok(Value::Float(if x { 1.0 } else { 0.0 })), - Value::String(x) => { - let r: f64 = x.parse().map_err(|_| RuntimeError::ParseFail(x.clone(), Type::Int))?; - Ok(Value::Float(r)) - } - x => Err(RuntimeError::NoOverloadForTypes("float".into(), vec![x])), - }, - ParseTree::BoolCast(x) => match self.exec(x)? { - Value::Int(x) => Ok(Value::Bool(x != 0)), - Value::Float(x) => Ok(Value::Bool(x != 0.0)), - Value::Bool(x) => Ok(Value::Bool(x)), - Value::String(x) => Ok(Value::Bool(!x.is_empty())), - Value::Array(_, vec) => Ok(Value::Bool(!vec.is_empty())), - x => Err(RuntimeError::NoOverloadForTypes("bool".into(), vec![x])), - }, - ParseTree::StringCast(x) => Ok(Value::String(format!("{}", self.exec(x)?))), - ParseTree::Print(x) => match self.exec(x)? { - Value::String(s) => { - println!("{s}"); - Ok(Value::Nil) - } - x => { - println!("{x}"); - Ok(Value::Nil) - } - } - ParseTree::LambdaDefinition(func) => Ok(Value::Function(func)), - ParseTree::NonCall(name) => { - let obj = self.get_object_mut(&name)?; - - let v = obj.lock().unwrap().eval()?; - - Ok(v) - } - ParseTree::Head(x) => match self.exec(x)? { - Value::Array(_, x) => Ok(x.first().ok_or(RuntimeError::EmptyArray)?.clone()), - t => Err(RuntimeError::NoOverloadForTypes("head".into(), vec![t])) - }, - ParseTree::Tail(x) => match self.exec(x)? { - Value::Array(t, x) => Ok(Value::Array(t, if x.len() > 0 { x[1..].to_vec() } else { vec![] })), - t => Err(RuntimeError::NoOverloadForTypes("tail".into(), vec![t])) - }, - ParseTree::Init(x) => match self.exec(x)? { - Value::Array(t, x) => Ok(Value::Array(t, if x.len() > 0 { x[..x.len() - 1].to_vec() } else { vec![] })), - t => Err(RuntimeError::NoOverloadForTypes("init".into(), vec![t])) - }, - ParseTree::Fini(x) => match self.exec(x)? { - Value::Array(_, x) => Ok(x.last().ok_or(RuntimeError::EmptyArray)?.clone()), - t => Err(RuntimeError::NoOverloadForTypes("fini".into(), vec![t])) - }, + ParseTree::Value(value) => Ok(value), + ParseTree::LambdaDefinition(func) => Ok(Value::Function(func.globals(self.globals.clone()).locals(self.locals.clone()))), ParseTree::Nop => Ok(Value::Nil), ParseTree::Export(names) => { for name in names { @@ -412,6 +433,15 @@ where Ok(Value::Nil) } + ParseTree::NonCall(name) => { + let obj = self.get_object_mut(&name)?; + + let v = obj.lock().unwrap().eval()?; + + Ok(v) + } + ParseTree::_Local(_idx) => todo!(), + ParseTree::GeneratedFunction(function) => Ok(Value::Function(function.globals(self.globals.clone()).locals(self.locals.clone()))), } } } diff --git a/src/function.rs b/src/function.rs index 49db30a..5253091 100644 --- a/src/function.rs +++ b/src/function.rs @@ -1,4 +1,3 @@ -use std::cell::RefCell; use crate::parser::ParseTree; use crate::executor::{Executor, RuntimeError}; use crate::{Type, Object, Value}; @@ -16,11 +15,13 @@ impl Display for FunctionType { } } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug)] pub struct Function { - pub(crate) name: Option, + name: Option, t: FunctionType, - arg_names: Vec, + globals: Option>>>, + locals: Option>>>, + arg_names: Option>, body: Box, } @@ -29,7 +30,9 @@ impl Function { Self { name: None, t, - arg_names, + globals: None, + locals: None, + arg_names: Some(arg_names), body } } @@ -38,11 +41,97 @@ impl Function { Self { name: Some(name.to_string()), t, - arg_names, + globals: None, + locals: None, + arg_names: Some(arg_names), body } } + pub(crate) fn _generated(t: FunctionType, body: Box) -> Self { + Self { + name: None, + t, + globals: None, + locals: None, + arg_names: None, + body, + } + } + + pub(crate) fn locals(mut self, locals: HashMap>>) -> Self { + self.locals = Some(locals); + self + } + + pub(crate) fn globals(mut self, globals: HashMap>>) -> Self { + self.globals = Some(globals); + self + } + + fn _replace_locals(mut self) -> Self { + fn replace_locals_(body: Box, args: &Vec) -> Box { + match *body { + ParseTree::Operator(op, a) => + Box::new(ParseTree::Operator( + op, + a.into_iter().map(|x| *replace_locals_(Box::new(x), args)).collect())), + ParseTree::Equ(name, body, scope) => + Box::new(ParseTree::Equ( + name, + replace_locals_(body, args), + replace_locals_(scope, args))), + ParseTree::LazyEqu(name, body, scope) => + Box::new(ParseTree::LazyEqu( + name, + replace_locals_(body, args), + replace_locals_(scope, args))), + ParseTree::FunctionDefinition(func, scope) => + Box::new(ParseTree::FunctionDefinition(func, replace_locals_(scope, args))), + ParseTree::LambdaDefinition(_) => body, + ParseTree::FunctionCall(ref func, ref a) => + if let Some(idx) = args.into_iter().position(|r| *r == *func) { + Box::new(ParseTree::_FunctionCallLocal( + idx, + a.into_iter().map(|x| *replace_locals_(Box::new(x.clone()), args)).collect())) + } else { + Box::new(ParseTree::FunctionCall( + func.clone(), + a.into_iter().map(|x| *replace_locals_(Box::new(x.clone()), args)).collect())) + } + ParseTree::Variable(ref var) => { + if let Some(idx) = args.into_iter().position(|r| *r == *var) { + Box::new(ParseTree::_Local(idx)) + } else { + body + } + }, + ParseTree::If(cond, branch) => + Box::new(ParseTree::If(replace_locals_(cond, args), + replace_locals_(branch, args))), + ParseTree::IfElse(cond, t, f) => + Box::new(ParseTree::IfElse(replace_locals_(cond, args), + replace_locals_(t, args), + replace_locals_(f, args))), + ParseTree::_FunctionCallLocal(_, _) => body, + ParseTree::_Local(_) => body, + ParseTree::Value(_) => body, + ParseTree::Nop => body, + ParseTree::Export(_) => body, + ParseTree::NonCall(ref var) => if let Some(idx) = + args.into_iter().position(|r| *r == *var) { + Box::new(ParseTree::_Local(idx)) + } else { + body + } + ParseTree::GeneratedFunction(_) => todo!(), + } + } + + self.body = replace_locals_(self.body, &self.arg_names.take().unwrap()); + self + } + pub(crate) fn name(&self) -> Option<&str> { self.name.as_ref().map(|x| x.as_str()) } @@ -51,26 +140,25 @@ impl Function { self.t.clone() } - pub(crate) fn call(&mut self, - mut globals: HashMap>>, - locals: HashMap>>, - args: Vec) -> Result - { + pub(crate) fn call(&mut self, args: Vec>>) -> Result { let mut tree = vec![Ok(*self.body.clone())].into_iter(); - let g = globals.clone(); + let mut globals = self.globals.clone().unwrap(); + let locals = self.locals.clone().unwrap(); let mut exec = Executor::new(&mut tree, &mut globals) .locals(locals.clone()); - for (obj, name) in std::iter::zip(args.into_iter(), self.arg_names.clone().into_iter()) { - exec = exec.add_local(name.clone(), Arc::new(Mutex::new(obj))); + if let Some(names) = self.arg_names.clone() { + for (obj, name) in std::iter::zip(args.clone().into_iter(), names.into_iter()) { + exec = exec.add_local(name, obj); + } } - if let Some(name) = self.name().map(|x| x.to_string()) { - exec = exec.add_local(name, Arc::new(Mutex::new(Object::function(self.clone(), g, locals)))); + if let Some(name) = self.clone().name().map(|x| x.to_string()) { + exec = exec.add_local(name, Arc::new(Mutex::new(Object::function(self.clone(), self.globals.clone().unwrap(), locals)))); } - exec.next().unwrap() + exec.exec(self.body.clone()) } } diff --git a/src/lib.rs b/src/lib.rs index 25f7857..94f4ef8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -55,7 +55,7 @@ impl Display for Type { } /// Represents the result of executing a ParseTree with an Executor -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug)] pub enum Value { Float(f64), Int(i64), @@ -66,6 +66,20 @@ pub enum Value { Nil, } +impl PartialEq for Value { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (Self::Float(l0), Self::Float(r0)) => l0 == r0, + (Self::Int(l0), Self::Int(r0)) => l0 == r0, + (Self::Bool(l0), Self::Bool(r0)) => l0 == r0, + (Self::String(l0), Self::String(r0)) => l0 == r0, + (Self::Array(l0, l1), Self::Array(r0, r1)) => l0 == r0 && l1 == r1, + (Self::Function(_), Self::Function(_)) => false, + _ => core::mem::discriminant(self) == core::mem::discriminant(other), + } + } +} + impl Value { pub(crate) fn get_type(&self) -> Type { match self { @@ -94,7 +108,7 @@ impl Display for Value { } } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug)] enum Cache { Cached(Value), Uncached(ParseTree), @@ -107,12 +121,6 @@ struct Object { value: Cache, } -impl PartialEq for Object { - fn eq(&self, other: &Self) -> bool { - self.value == other.value - } -} - impl Object { pub fn variable(tree: ParseTree, globals: HashMap>>, locals: HashMap>>) -> Self { Self { @@ -143,12 +151,12 @@ impl Object { match self.value.clone() { Cache::Cached(v) => Ok(v), Cache::Uncached(tree) => { - let mut tree = vec![Ok(tree)].into_iter(); + let mut t = vec![Ok(tree.clone())].into_iter(); - let mut exec = Executor::new(&mut tree, &mut self.globals) + let mut exec = Executor::new(&mut t, &mut self.globals) .locals(self.locals.clone()); - let v = exec.next().unwrap()?; + let v = exec.exec(Box::new(tree))?; self.value = Cache::Cached(v.clone()); @@ -157,11 +165,11 @@ impl Object { } } - pub fn locals(&self) -> HashMap>> { + pub fn _locals(&self) -> HashMap>> { self.locals.clone() } - pub fn globals(&self) -> HashMap>> { + pub fn _globals(&self) -> HashMap>> { self.globals.clone() } } diff --git a/src/parser.rs b/src/parser.rs index a577859..575cca7 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -20,6 +20,7 @@ pub enum ParseError { UnwantedToken(Token), TokenizeError(TokenizeError), ImmutableError(String), + RuntimeError, } impl Display for ParseError { @@ -31,6 +32,7 @@ impl Display for ParseError { ParseError::NoInput => write!(f, "No input given"), ParseError::UnmatchedArrayClose => write!(f, "there was an unmatched array closing operator `]`"), ParseError::TokenizeError(e) => write!(f, "Tokenizer Error: {e}"), + ParseError::RuntimeError => write!(f, "Runtime Error"), ParseError::ImmutableError(i) => write!(f, "attempt to redeclare {i} met with force"), ParseError::UnwantedToken(t) => write!(f, "unexpected token {t:?}"), } @@ -39,26 +41,9 @@ impl Display for ParseError { impl error::Error for ParseError {} -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug)] pub(crate) enum ParseTree { - // Mathematical Operators - Add(Box, Box), - Sub(Box, Box), - Mul(Box, Box), - Div(Box, Box), - Exp(Box, Box), - Mod(Box, Box), - - // Boolean Operations - EqualTo(Box, Box), - NotEqualTo(Box, Box), - GreaterThan(Box, Box), - GreaterThanOrEqualTo(Box, Box), - LessThan(Box, Box), - LessThanOrEqualTo(Box, Box), - Not(Box), - And(Box, Box), - Or(Box, Box), + Operator(Op, Vec), // Defining Objects Equ(String, Box, Box), @@ -66,33 +51,20 @@ pub(crate) enum ParseTree { FunctionDefinition(Function, Box), LambdaDefinition(Function), - // Functional Operations - Compose(Box, Box), - Id(Box), - Head(Box), - Tail(Box), - Init(Box), - Fini(Box), - - // Branching + // Control Flow If(Box, Box), IfElse(Box, Box, Box), // Evaluations FunctionCall(String, Vec), + _FunctionCallLocal(usize, Vec), Variable(String), - Constant(Value), - NonCall(String), + _Local(usize), + Value(Value), + GeneratedFunction(Function), - // Type Casts - IntCast(Box), - FloatCast(Box), - BoolCast(Box), - StringCast(Box), - - // Misc - Print(Box), Nop, + NonCall(String), Export(Vec), } @@ -113,12 +85,12 @@ impl<'a, I: Iterator>> Parser<'a, I> { } - pub fn add_global(self, k: String, v: Type) -> Self { + pub fn _add_global(self, k: String, v: Type) -> Self { self.globals.insert(k, v); self } - pub fn add_globals>(self, items: Items) -> Self { + pub fn _add_globals>(self, items: Items) -> Self { items.for_each(|(name, t)| { self.globals.insert(name, t); }); @@ -135,7 +107,7 @@ impl<'a, I: Iterator>> Parser<'a, I> { self } - pub fn add_locals>(mut self, items: Items) -> Self { + pub fn _add_locals>(mut self, items: Items) -> Self { items.for_each(|(name, t)| { self.locals.insert(name, t); }); @@ -147,203 +119,283 @@ impl<'a, I: Iterator>> Parser<'a, I> { .ok_or(ParseError::IdentifierUndefined(ident.clone())) } - fn get_object_types>(&self, items: Names) -> impl Iterator> { + fn _get_object_types>(&self, items: Names) -> impl Iterator> { items.map(|x| self.get_object_type(&x)) } + // get at most count arguments + fn get_args(&mut self, count: usize) -> Result, ParseError> { + (0..count).map_while(|_| match self.parse() { + Ok(r) => Some(Ok(r)), + Err(ParseError::NoInput) => None, + Err(e) => Some(Err(e)), + }).collect() + } + + fn parse_operator(&mut self, op: Op) -> Result { + let operators: HashMap = HashMap::from([ + (Op::Add, FunctionType(Box::new(Type::Any), vec![Type::Any, Type::Any])), + (Op::Sub, FunctionType(Box::new(Type::Any), vec![Type::Any, Type::Any])), + (Op::Mul, FunctionType(Box::new(Type::Any), vec![Type::Any, Type::Any])), + (Op::Div, FunctionType(Box::new(Type::Any), vec![Type::Any, Type::Any])), + (Op::Exp, FunctionType(Box::new(Type::Any), vec![Type::Any, Type::Any])), + (Op::Mod, FunctionType(Box::new(Type::Any), vec![Type::Any, Type::Any])), + (Op::Id, FunctionType(Box::new(Type::Any), vec![Type::Any])), + (Op::GreaterThan, FunctionType(Box::new(Type::Bool), vec![Type::Any, Type::Any])), + (Op::LessThan, FunctionType(Box::new(Type::Bool), vec![Type::Any, Type::Any])), + (Op::EqualTo, FunctionType(Box::new(Type::Bool), vec![Type::Any, Type::Any])), + (Op::NotEqualTo, FunctionType(Box::new(Type::Bool), vec![Type::Any, Type::Any])), + (Op::GreaterThanOrEqualTo, FunctionType(Box::new(Type::Bool), vec![Type::Any, Type::Any])), + (Op::LessThanOrEqualTo, FunctionType(Box::new(Type::Bool), vec![Type::Any, Type::Any])), + (Op::Not, FunctionType(Box::new(Type::Bool), vec![Type::Bool])), + (Op::And, FunctionType(Box::new(Type::Bool), vec![Type::Bool, Type::Bool])), + (Op::Or, FunctionType(Box::new(Type::Bool), vec![Type::Bool, Type::Bool])), + (Op::Head, FunctionType(Box::new(Type::Any), vec![Type::Array(Box::new(Type::Any))])), + (Op::Tail, FunctionType(Box::new(Type::Array(Box::new(Type::Any))), vec![Type::Array(Box::new(Type::Any))])), + (Op::Init, FunctionType(Box::new(Type::Array(Box::new(Type::Any))), vec![Type::Array(Box::new(Type::Any))])), + (Op::Fini, FunctionType(Box::new(Type::Any), vec![Type::Array(Box::new(Type::Any))])), + (Op::Print, FunctionType(Box::new(Type::Nil), vec![Type::Any])), + (Op::IntCast, FunctionType(Box::new(Type::Int), vec![Type::Any])), + (Op::FloatCast, FunctionType(Box::new(Type::Float), vec![Type::Any])), + (Op::BoolCast, FunctionType(Box::new(Type::Bool), vec![Type::Any])), + (Op::StringCast, FunctionType(Box::new(Type::String), vec![Type::Any])), + ]); + + let operator = operators.get(&op).expect("All operators should be accounted for"); + let args = self.get_args(operator.1.len())?; + + if args.len() == operator.1.len() { + Ok(ParseTree::Operator(op, args)) + } else { + let mut counter = 0; + let func_args: Vec = operator.1.iter().skip(args.len()).cloned().collect(); + let (names, types): (Vec, Vec) = func_args + .into_iter() + .map(|t| { + counter += 1; + (format!("{counter}"), t) + }).unzip(); + let function_type = FunctionType(operator.0.clone(), types); + + Ok(ParseTree::GeneratedFunction(Function::lambda( + function_type, + names.clone(), + Box::new(ParseTree::Operator(op, + vec![ + args, + names.into_iter().map(|x| ParseTree::Variable(x)).collect() + ].concat()))))) + } + } + fn parse(&mut self) -> Result { - match self.tokens.next().ok_or(ParseError::NoInput)?.map_err(|e| ParseError::TokenizeError(e))? { - Token::Constant(c) => Ok(ParseTree::Constant(c)), + let token = self.tokens.next() + .ok_or(ParseError::NoInput)? + .map_err(|e| ParseError::TokenizeError(e))?; + + match token { + Token::Constant(c) => Ok(ParseTree::Value(c)), Token::Identifier(ident) => { match self.get_object_type(&ident)? { Type::Function(f) => { - let args = f.1.clone().iter() - .map(|_| self.parse()).collect::, ParseError>>()?; + let f = f.clone(); + let args = self.get_args(f.1.len())?; - Ok(ParseTree::FunctionCall(ident, args)) + if args.len() < f.1.len() { + let mut counter = 0; + let func_args: Vec = f.1.iter().skip(args.len()).cloned().collect(); + let (names, types): (Vec, Vec) = func_args + .into_iter() + .map(|t| { + counter += 1; + (format!("{counter}"), t) + }).unzip(); + let function_type = FunctionType(f.0.clone(), types); + + Ok(ParseTree::Value(Value::Function(Function::lambda( + function_type, + names.clone(), + Box::new(ParseTree::FunctionCall(ident, + vec![ + args, + names.into_iter().map(|x| ParseTree::Variable(x)).collect() + ].concat())))))) + } else { + Ok(ParseTree::FunctionCall(ident, args)) + } } _ => Ok(ParseTree::Variable(ident)), } - } - Token::Operator(op) => { - match op { - Op::Add => Ok(ParseTree::Add(Box::new(self.parse()?), Box::new(self.parse()?))), - Op::Sub => Ok(ParseTree::Sub(Box::new(self.parse()?), Box::new(self.parse()?))), - Op::Mul => Ok(ParseTree::Mul(Box::new(self.parse()?), Box::new(self.parse()?))), - Op::Div => Ok(ParseTree::Div(Box::new(self.parse()?), Box::new(self.parse()?))), - Op::Exp => Ok(ParseTree::Exp(Box::new(self.parse()?), Box::new(self.parse()?))), - Op::Mod => Ok(ParseTree::Mod(Box::new(self.parse()?), Box::new(self.parse()?))), - Op::Equ | Op::LazyEqu => { - let token = self.tokens.next() - .ok_or(ParseError::UnexpectedEndInput)? - .map_err(|e| ParseError::TokenizeError(e))?; + }, + Token::Operator(op) => match op { + Op::OpenArray => { + let mut depth = 1; - let body = Box::new(self.parse()?); - - if let Token::Identifier(ident) = token { - match op { - Op::Equ => Ok(ParseTree::Equ(ident.clone(), - body, - Box::new(Parser::new(self.tokens.by_ref(), self.globals.borrow_mut()) - .locals(self.locals.clone()) - .add_local(ident, Type::Any) - .parse()?)) - ), - Op::LazyEqu => Ok(ParseTree::LazyEqu(ident.clone(), - body, - Box::new(Parser::new(self.tokens.by_ref(), self.globals.borrow_mut()) - .locals(self.locals.clone()) - .add_local(ident, Type::Any) - .parse()?)) - ), - _ => unreachable!(), - } - } else { - Err(ParseError::InvalidIdentifier(token)) + // take tokens until we reach the end of this array + // if we don't collect them here it causes rust to overflow computing the types + let array_tokens = self.tokens.by_ref().take_while(|t| match t { + Ok(Token::Operator(Op::OpenArray)) => { + depth += 1; + true + }, + Ok(Token::Operator(Op::CloseArray)) => { + depth -= 1; + depth > 0 } - } - Op::FunctionDefine(arg_count) => { - let f = self.parse_function(arg_count)?; + _ => true, + }).collect::, TokenizeError>>().map_err(|e| ParseError::TokenizeError(e))?; - Ok(ParseTree::FunctionDefinition(f.clone(), - Box::new( - Parser::new(self.tokens, self.globals.borrow_mut()) + let mut array_tokens = array_tokens + .into_iter() + .map(|t| Ok(t)) + .collect::>>() + .into_iter() + .peekable(); + + let trees: Vec = Parser::new(&mut array_tokens, self.globals.borrow_mut()) + .locals(self.locals.to_owned()) + .collect::>()?; + + let tree = trees.into_iter().fold( + ParseTree::Value(Value::Array(Type::Any, vec![])), + |acc, x| ParseTree::Operator(Op::Add, vec![acc, x.clone()]), + ); + + Ok(tree) + }, + Op::OpenStatement => { + let mut depth = 1; + + // take tokens until we reach the end of this array + // if we don't collect them here it causes rust to overflow computing the types + let array_tokens = self.tokens.by_ref().take_while(|t| match t { + Ok(Token::Operator(Op::OpenStatement)) => { + depth += 1; + true + }, + Ok(Token::Operator(Op::CloseStatement)) => { + depth -= 1; + depth > 0 + } + _ => true, + }).collect::, TokenizeError>>().map_err(|e| ParseError::TokenizeError(e))?; + + let mut array_tokens = array_tokens + .into_iter() + .map(|t| Ok(t)) + .collect::>>() + .into_iter() + .peekable(); + + let trees: Vec = Parser::new(&mut array_tokens, self.globals.borrow_mut()) + .locals(self.locals.to_owned()) + .collect::>()?; + + let tree = trees.into_iter().fold( + ParseTree::Nop, + |acc, x| ParseTree::Operator(Op::Compose, vec![acc, x.clone()]), + ); + + Ok(tree) + }, + Op::Equ | Op::LazyEqu => { + let token = self.tokens.next().ok_or(ParseError::UnexpectedEndInput)?.map_err(|e| ParseError::TokenizeError(e))?; + + let body = Box::new(self.parse()?); + + if let Token::Identifier(ident) = token { + match op { + Op::Equ => Ok(ParseTree::Equ( + ident.clone(), + body, + Box::new(Parser::new(self.tokens.by_ref(), self.globals.borrow_mut()) + .locals(self.locals.clone()) + .add_local(ident, Type::Any) + .parse()?)) + ), + Op::LazyEqu => Ok(ParseTree::LazyEqu( + ident.clone(), + body, + Box::new(Parser::new(self.tokens.by_ref(), self.globals.borrow_mut()) + .locals(self.locals.clone()) + .add_local(ident, Type::Any) + .parse()?)) + ), + _ => unreachable!(), + } + } else { + Err(ParseError::InvalidIdentifier(token)) + } + }, + Op::FunctionDefine(arg_count) => { + let f = self.parse_function_definition(arg_count)?; + + Ok(ParseTree::FunctionDefinition( + f.clone(), + Box::new( + Parser::new(self.tokens, self.globals.borrow_mut()) .locals(self.locals.clone()) .add_local(f.name().unwrap().to_string(), Type::Function(f.get_type())) .parse()? - ))) - }, - Op::Compose => Ok(ParseTree::Compose(Box::new(self.parse()?), Box::new(self.parse()?))), - Op::Id => Ok(ParseTree::Id(Box::new(self.parse()?))), - Op::IfElse => Ok(ParseTree::IfElse(Box::new(self.parse()?), Box::new(self.parse()?), Box::new(self.parse()?))), - Op::If => Ok(ParseTree::If(Box::new(self.parse()?), Box::new(self.parse()?))), - Op::EqualTo => Ok(ParseTree::EqualTo(Box::new(self.parse()?), Box::new(self.parse()?))), - Op::GreaterThan => Ok(ParseTree::GreaterThan(Box::new(self.parse()?), Box::new(self.parse()?))), - Op::LessThan => Ok(ParseTree::LessThan(Box::new(self.parse()?), Box::new(self.parse()?))), - Op::GreaterThanOrEqualTo => Ok(ParseTree::GreaterThanOrEqualTo(Box::new(self.parse()?), Box::new(self.parse()?))), - Op::LessThanOrEqualTo => Ok(ParseTree::LessThanOrEqualTo(Box::new(self.parse()?), Box::new(self.parse()?))), - Op::Not => Ok(ParseTree::Not(Box::new(self.parse()?))), - Op::IntCast => Ok(ParseTree::IntCast(Box::new(self.parse()?))), - Op::FloatCast => Ok(ParseTree::FloatCast(Box::new(self.parse()?))), - Op::BoolCast => Ok(ParseTree::BoolCast(Box::new(self.parse()?))), - Op::StringCast => Ok(ParseTree::StringCast(Box::new(self.parse()?))), - Op::Print => Ok(ParseTree::Print(Box::new(self.parse()?))), - Op::OpenArray => { - let mut depth = 1; + ))) + }, + Op::LambdaDefine(arg_count) => { + let f = self.parse_lambda_definition(arg_count)?; - // take tokens until we reach the end of this array - // if we don't collect them here it causes rust to overflow computing the types - let array_tokens = self.tokens.by_ref().take_while(|t| match t { - Ok(Token::Operator(Op::OpenArray)) => { - depth += 1; - true - }, - Ok(Token::Operator(Op::CloseArray)) => { - depth -= 1; - depth > 0 - } - _ => true, - }).collect::, TokenizeError>>().map_err(|e| ParseError::TokenizeError(e))?; + Ok(ParseTree::LambdaDefinition(f)) + }, + Op::Export => { + let list = self.parse()?; - let mut array_tokens = array_tokens - .into_iter() - .map(|t| Ok(t)) - .collect::>>() - .into_iter() - .peekable(); + let mut g = HashMap::new(); + let list = Executor::new(&mut vec![Ok(list)].into_iter(), &mut g) + .next().unwrap().map_err(|_| ParseError::RuntimeError)?; - let trees: Vec = Parser::new(&mut array_tokens, self.globals.borrow_mut()) - .locals(self.locals.to_owned()) - .collect::>()?; + if let Value::Array(Type::String, items) = list { + let names = items.into_iter().map(|x| match x { + Value::String(s) => s, + _ => unreachable!(), + }); - let tree = trees.into_iter().fold( - ParseTree::Constant(Value::Array(Type::Any, vec![])), - |acc, x| ParseTree::Add(Box::new(acc), Box::new(x.clone())), - ); - - Ok(tree) - } - Op::OpenStatement => { - let mut depth = 1; - - // take tokens until we reach the end of this array - // if we don't collect them here it causes rust to overflow computing the types - let tokens = self.tokens.by_ref().take_while(|t| match t { - Ok(Token::Operator(Op::OpenStatement)) => { - depth += 1; - true - }, - Ok(Token::Operator(Op::CloseStatement)) => { - depth -= 1; - depth > 0 - } - _ => true, - }).collect::, TokenizeError>>().map_err(|e| ParseError::TokenizeError(e))?; - - let mut tokens = tokens - .into_iter() - .map(|t| Ok(t)) - .collect::>>() - .into_iter() - .peekable(); - - let trees: Vec = Parser::new(&mut tokens, self.globals.borrow_mut()) - .locals(self.locals.to_owned()) - .collect::>()?; - - let tree = trees.into_iter().fold( - ParseTree::Nop, - |acc, x| ParseTree::Compose(Box::new(acc), Box::new(x.clone())), - ); - - Ok(tree) - } - Op::Empty => Ok(ParseTree::Constant(Value::Array(Type::Any, vec![]))), - Op::CloseArray => Err(ParseError::UnmatchedArrayClose), - Op::NotEqualTo => Ok(ParseTree::NotEqualTo(Box::new(self.parse()?), Box::new(self.parse()?))), - Op::And => Ok(ParseTree::And(Box::new(self.parse()?), Box::new(self.parse()?))), - Op::Or => Ok(ParseTree::Or(Box::new(self.parse()?), Box::new(self.parse()?))), - Op::LambdaDefine(arg_count) => { - let f = self.parse_lambda(arg_count)?; - Ok(ParseTree::LambdaDefinition(f)) - } - Op::NonCall => { - let name = Self::get_identifier(self.tokens.next())?; - Ok(ParseTree::NonCall(name)) - }, - Op::Head => Ok(ParseTree::Head(Box::new(self.parse()?))), - Op::Tail => Ok(ParseTree::Tail(Box::new(self.parse()?))), - Op::Init => Ok(ParseTree::Init(Box::new(self.parse()?))), - Op::Fini => Ok(ParseTree::Fini(Box::new(self.parse()?))), - Op::Export => { - let list = self.parse()?; - let mut g = HashMap::new(); - let list = Executor::new(&mut vec![Ok(list)].into_iter(), &mut g).next().unwrap().map_err(|_| ParseError::NoInput)?; - - if let Value::Array(Type::String, items) = list { - let names = items.into_iter().map(|x| match x { - Value::String(s) => s, - _ => unreachable!(), - }); - - for name in names.clone() { - let t = self.locals.remove(&name).ok_or(ParseError::IdentifierUndefined(name.clone()))?; - self.globals.insert(name, t); - } - - Ok(ParseTree::Export(names.collect())) - } else { - Err(ParseError::NoInput) + for name in names.clone() { + let t = match self.locals.remove(&name).ok_or(ParseError::IdentifierUndefined(name.clone())) { + Ok(t) => t, + Err(e) => return Err(e), + }; + self.globals.insert(name, t); } + + Ok(ParseTree::Export(names.collect())) + } else { + Err(ParseError::NoInput) } - op => Err(ParseError::UnwantedToken(Token::Operator(op))), } - } + Op::Empty => Ok(ParseTree::Value(Value::Array(Type::Any, vec![]))), + Op::NonCall => { + let name = Self::get_identifier(self.tokens.next())?; + Ok(ParseTree::NonCall(name)) + }, + Op::If => { + let cond = self.parse()?; + let truebranch = self.parse()?; + + Ok(ParseTree::If(Box::new(cond), Box::new(truebranch))) + }, + Op::IfElse => { + let cond = self.parse()?; + let truebranch = self.parse()?; + let falsebranch = self.parse()?; + + Ok(ParseTree::IfElse( + Box::new(cond), Box::new(truebranch), Box::new(falsebranch))) + }, + op => self.parse_operator(op), + }, t => Err(ParseError::UnwantedToken(t)), } } - fn parse_lambda(&mut self, arg_count: usize) -> Result { + fn parse_lambda_definition(&mut self, arg_count: usize) -> Result { let (t, args) = Self::parse_function_declaration(self.tokens, arg_count)?; let mut locals = self.locals.clone(); @@ -357,7 +409,7 @@ impl<'a, I: Iterator>> Parser<'a, I> { .locals(locals).parse()?))) } - fn parse_function(&mut self, arg_count: usize) -> Result { + fn parse_function_definition(&mut self, arg_count: usize) -> Result { let name = Self::get_identifier(self.tokens.next())?; let (t, args) = Self::parse_function_declaration(self.tokens, arg_count)?; diff --git a/src/tokenizer.rs b/src/tokenizer.rs index 34df5da..0227a79 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -41,7 +41,7 @@ impl Display for TokenizeError { impl error::Error for TokenizeError {} -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum Op { Add, Sub, @@ -79,12 +79,12 @@ pub enum Op { Empty, And, Or, - NonCall, Head, Tail, Init, Fini, Export, + NonCall, } #[derive(Debug, Clone, PartialEq)] @@ -119,6 +119,7 @@ impl Token { // Match keywords first "true" => Ok(Token::Constant(Value::Bool(true))), "false" => Ok(Token::Constant(Value::Bool(false))), + "nil" => Ok(Token::Constant(Value::Nil)), "int" => Ok(Token::Operator(Op::IntCast)), "float" => Ok(Token::Operator(Op::FloatCast)), "bool" => Ok(Token::Operator(Op::BoolCast)), @@ -205,7 +206,7 @@ impl Tokenizer { ("!", Op::Not), ("&&", Op::And), ("||", Op::Or), - ("'", Op::NonCall), + ("\\", Op::NonCall), ]); let c = if let Some(c) = iter.next() {