support code generation through () blocks

This commit is contained in:
2024-10-25 20:55:07 -04:00
parent d29fa2b9b0
commit a28dedb1ea
5 changed files with 654 additions and 475 deletions

View File

@@ -1,12 +1,12 @@
use super::{Value, Type, Object}; use super::{Value, Type, Object};
use super::parser::{ParseTree, ParseError}; use super::parser::{ParseTree, ParseError};
use super::tokenizer::Op;
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt::Display; use std::fmt::Display;
use std::error::Error; use std::error::Error;
use std::io; use std::io;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::cell::RefCell;
#[derive(Debug)] #[derive(Debug)]
pub enum RuntimeError { pub enum RuntimeError {
@@ -104,155 +104,236 @@ where
Ok(v) Ok(v)
} }
fn obj_locals(obj: &Arc<Mutex<Object>>) -> HashMap<String, Arc<Mutex<Object>>> { fn _obj_locals(obj: &Arc<Mutex<Object>>) -> HashMap<String, Arc<Mutex<Object>>> {
let guard = obj.lock().unwrap(); let guard = obj.lock().unwrap();
let locals = guard.locals(); let locals = guard._locals();
locals locals
} }
fn obj_globals(obj: &Arc<Mutex<Object>>) -> HashMap<String, Arc<Mutex<Object>>> { fn _obj_globals(obj: &Arc<Mutex<Object>>) -> HashMap<String, Arc<Mutex<Object>>> {
let guard = obj.lock().unwrap(); let guard = obj.lock().unwrap();
let locals = guard.globals(); let locals = guard._globals();
locals locals
} }
pub fn exec(&mut self, tree: Box<ParseTree>) -> Result<Value, RuntimeError> { pub fn exec(&mut self, tree: Box<ParseTree>) -> Result<Value, RuntimeError> {
match *tree { match *tree {
ParseTree::Add(x, y) => match (self.exec(x)?, self.exec(y)?) { ParseTree::Operator(op, args) => {
(Value::Int(x), Value::Int(y)) => Ok(Value::Int(x + y)), let args: Vec<Value> = args.into_iter()
(Value::Float(x), Value::Int(y)) => Ok(Value::Float(x + y as f64)), .map(|x| self.exec(Box::new(x))).collect::<Result<_, _>>()?;
(Value::Int(x), Value::Float(y)) => Ok(Value::Float(x as f64 + y)),
(Value::Float(x), Value::Float(y)) => Ok(Value::Float(x + y)), match op {
(Value::String(x), Value::String(y)) => Ok(Value::String(format!("{x}{y}"))), Op::Add => match &args[..] {
(Value::Array(xtype, x), Value::Array(ytype, 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 { if xtype != ytype {
return Err(RuntimeError::TypeError(xtype, ytype)); return Err(RuntimeError::TypeError(xtype.clone(), ytype.clone()));
} }
Ok(Value::Array(xtype, [x, y].concat())) Ok(Value::Array(xtype.clone(), [x.clone(), y.clone()].concat()))
}, },
(Value::Array(t, x), y) => { [Value::Nil, x] => Ok(x.clone()),
[x, Value::Nil] => Ok(x.clone()),
[Value::Array(t, x), y] => {
let ytype = y.get_type(); let ytype = y.get_type();
if t != ytype { if *t != ytype {
return Err(RuntimeError::TypeError(t, ytype)); return Err(RuntimeError::TypeError(t.clone(), ytype));
} }
// NOTE: use y's type instead of the arrays type. // NOTE: use y's type instead of the arrays type.
// an `empty` array has Any type, but any value will have a fixed type. // an `empty` array has Any type, but any value will have a fixed type.
// this converts the empty array into a typed array. // this converts the empty array into a typed array.
Ok(Value::Array(ytype, [x, vec![y]].concat())) Ok(Value::Array(ytype, [x.clone(), vec![y.clone()]].concat()))
}, },
(x, Value::Array(t, y)) => { [x, Value::Array(t, y)] => {
let xtype = x.get_type(); let xtype = x.get_type();
if t != xtype { if *t != xtype {
return Err(RuntimeError::TypeError(t, xtype)); return Err(RuntimeError::TypeError(t.clone(), xtype));
} }
// NOTE: read above // NOTE: read above
Ok(Value::Array(xtype, [vec![x], y].concat())) Ok(Value::Array(xtype, [vec![x.clone()], y.clone()].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]))
}, },
_ => Err(RuntimeError::NoOverloadForTypes("+".into(), args)),
}
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)),
}
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)),
}
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) => { ParseTree::Equ(ident, body, scope) => {
if self.variable_exists(&ident) { if self.variable_exists(&ident) {
Err(RuntimeError::ImmutableError(ident.clone())) Err(RuntimeError::ImmutableError(ident.clone()))
@@ -281,14 +362,33 @@ where
let g = self.globals.clone(); let g = self.globals.clone();
Executor::new(self.exprs, &mut self.globals) Executor::new(self.exprs, &mut self.globals)
.locals(self.locals.clone()) .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) .exec(scope)
}, },
ParseTree::Compose(x, y) => { ParseTree::FunctionCall(ident, args) => {
self.exec(x)?; let obj = self.get_object_mut(&ident)?;
self.exec(y) 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)
}, },
ParseTree::Id(x) => self.exec(x), _ => Err(RuntimeError::FunctionUndefined(ident.clone()))
}
},
ParseTree::_FunctionCallLocal(_idx, _args) => todo!(),
ParseTree::If(cond, body) => if match self.exec(cond)? { ParseTree::If(cond, body) => if match self.exec(cond)? {
Value::Float(f) => f != 0.0, Value::Float(f) => f != 0.0,
Value::Int(i) => i != 0, Value::Int(i) => i != 0,
@@ -315,23 +415,6 @@ where
} else { } else {
self.exec(isfalse) 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) => { ParseTree::Variable(ident) => {
let obj = self.get_object_mut(&ident)?; let obj = self.get_object_mut(&ident)?;
@@ -339,70 +422,8 @@ where
Ok(v) Ok(v)
}, },
ParseTree::Constant(value) => Ok(value), ParseTree::Value(value) => Ok(value),
ParseTree::IntCast(x) => match self.exec(x)? { ParseTree::LambdaDefinition(func) => Ok(Value::Function(func.globals(self.globals.clone()).locals(self.locals.clone()))),
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::Nop => Ok(Value::Nil), ParseTree::Nop => Ok(Value::Nil),
ParseTree::Export(names) => { ParseTree::Export(names) => {
for name in names { for name in names {
@@ -412,6 +433,15 @@ where
Ok(Value::Nil) 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()))),
} }
} }
} }

View File

@@ -1,4 +1,3 @@
use std::cell::RefCell;
use crate::parser::ParseTree; use crate::parser::ParseTree;
use crate::executor::{Executor, RuntimeError}; use crate::executor::{Executor, RuntimeError};
use crate::{Type, Object, Value}; use crate::{Type, Object, Value};
@@ -16,11 +15,13 @@ impl Display for FunctionType {
} }
} }
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug)]
pub struct Function { pub struct Function {
pub(crate) name: Option<String>, name: Option<String>,
t: FunctionType, t: FunctionType,
arg_names: Vec<String>, globals: Option<HashMap<String, Arc<Mutex<Object>>>>,
locals: Option<HashMap<String, Arc<Mutex<Object>>>>,
arg_names: Option<Vec<String>>,
body: Box<ParseTree>, body: Box<ParseTree>,
} }
@@ -29,7 +30,9 @@ impl Function {
Self { Self {
name: None, name: None,
t, t,
arg_names, globals: None,
locals: None,
arg_names: Some(arg_names),
body body
} }
} }
@@ -38,11 +41,97 @@ impl Function {
Self { Self {
name: Some(name.to_string()), name: Some(name.to_string()),
t, t,
arg_names, globals: None,
locals: None,
arg_names: Some(arg_names),
body body
} }
} }
pub(crate) fn _generated(t: FunctionType, body: Box<ParseTree>) -> Self {
Self {
name: None,
t,
globals: None,
locals: None,
arg_names: None,
body,
}
}
pub(crate) fn locals(mut self, locals: HashMap<String, Arc<Mutex<Object>>>) -> Self {
self.locals = Some(locals);
self
}
pub(crate) fn globals(mut self, globals: HashMap<String, Arc<Mutex<Object>>>) -> Self {
self.globals = Some(globals);
self
}
fn _replace_locals(mut self) -> Self {
fn replace_locals_(body: Box<ParseTree>, args: &Vec<String>) -> Box<ParseTree> {
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> { pub(crate) fn name(&self) -> Option<&str> {
self.name.as_ref().map(|x| x.as_str()) self.name.as_ref().map(|x| x.as_str())
} }
@@ -51,26 +140,25 @@ impl Function {
self.t.clone() self.t.clone()
} }
pub(crate) fn call(&mut self, pub(crate) fn call(&mut self, args: Vec<Arc<Mutex<Object>>>) -> Result<Value, RuntimeError> {
mut globals: HashMap<String, Arc<Mutex<Object>>>,
locals: HashMap<String, Arc<Mutex<Object>>>,
args: Vec<Object>) -> Result<Value, RuntimeError>
{
let mut tree = vec![Ok(*self.body.clone())].into_iter(); 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) let mut exec = Executor::new(&mut tree, &mut globals)
.locals(locals.clone()); .locals(locals.clone());
for (obj, name) in std::iter::zip(args.into_iter(), self.arg_names.clone().into_iter()) { if let Some(names) = self.arg_names.clone() {
exec = exec.add_local(name.clone(), Arc::new(Mutex::new(obj))); 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()) { 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(), g, locals)))); 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())
} }
} }

View File

@@ -55,7 +55,7 @@ impl Display for Type {
} }
/// Represents the result of executing a ParseTree with an Executor /// Represents the result of executing a ParseTree with an Executor
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug)]
pub enum Value { pub enum Value {
Float(f64), Float(f64),
Int(i64), Int(i64),
@@ -66,6 +66,20 @@ pub enum Value {
Nil, 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 { impl Value {
pub(crate) fn get_type(&self) -> Type { pub(crate) fn get_type(&self) -> Type {
match self { match self {
@@ -94,7 +108,7 @@ impl Display for Value {
} }
} }
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug)]
enum Cache { enum Cache {
Cached(Value), Cached(Value),
Uncached(ParseTree), Uncached(ParseTree),
@@ -107,12 +121,6 @@ struct Object {
value: Cache, value: Cache,
} }
impl PartialEq for Object {
fn eq(&self, other: &Self) -> bool {
self.value == other.value
}
}
impl Object { impl Object {
pub fn variable(tree: ParseTree, globals: HashMap<String, Arc<Mutex<Object>>>, locals: HashMap<String, Arc<Mutex<Object>>>) -> Self { pub fn variable(tree: ParseTree, globals: HashMap<String, Arc<Mutex<Object>>>, locals: HashMap<String, Arc<Mutex<Object>>>) -> Self {
Self { Self {
@@ -143,12 +151,12 @@ impl Object {
match self.value.clone() { match self.value.clone() {
Cache::Cached(v) => Ok(v), Cache::Cached(v) => Ok(v),
Cache::Uncached(tree) => { 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()); .locals(self.locals.clone());
let v = exec.next().unwrap()?; let v = exec.exec(Box::new(tree))?;
self.value = Cache::Cached(v.clone()); self.value = Cache::Cached(v.clone());
@@ -157,11 +165,11 @@ impl Object {
} }
} }
pub fn locals(&self) -> HashMap<String, Arc<Mutex<Object>>> { pub fn _locals(&self) -> HashMap<String, Arc<Mutex<Object>>> {
self.locals.clone() self.locals.clone()
} }
pub fn globals(&self) -> HashMap<String, Arc<Mutex<Object>>> { pub fn _globals(&self) -> HashMap<String, Arc<Mutex<Object>>> {
self.globals.clone() self.globals.clone()
} }
} }

View File

@@ -20,6 +20,7 @@ pub enum ParseError {
UnwantedToken(Token), UnwantedToken(Token),
TokenizeError(TokenizeError), TokenizeError(TokenizeError),
ImmutableError(String), ImmutableError(String),
RuntimeError,
} }
impl Display for ParseError { impl Display for ParseError {
@@ -31,6 +32,7 @@ impl Display for ParseError {
ParseError::NoInput => write!(f, "No input given"), ParseError::NoInput => write!(f, "No input given"),
ParseError::UnmatchedArrayClose => write!(f, "there was an unmatched array closing operator `]`"), ParseError::UnmatchedArrayClose => write!(f, "there was an unmatched array closing operator `]`"),
ParseError::TokenizeError(e) => write!(f, "Tokenizer Error: {e}"), 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::ImmutableError(i) => write!(f, "attempt to redeclare {i} met with force"),
ParseError::UnwantedToken(t) => write!(f, "unexpected token {t:?}"), ParseError::UnwantedToken(t) => write!(f, "unexpected token {t:?}"),
} }
@@ -39,26 +41,9 @@ impl Display for ParseError {
impl error::Error for ParseError {} impl error::Error for ParseError {}
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug)]
pub(crate) enum ParseTree { pub(crate) enum ParseTree {
// Mathematical Operators Operator(Op, Vec<ParseTree>),
Add(Box<ParseTree>, Box<ParseTree>),
Sub(Box<ParseTree>, Box<ParseTree>),
Mul(Box<ParseTree>, Box<ParseTree>),
Div(Box<ParseTree>, Box<ParseTree>),
Exp(Box<ParseTree>, Box<ParseTree>),
Mod(Box<ParseTree>, Box<ParseTree>),
// Boolean Operations
EqualTo(Box<ParseTree>, Box<ParseTree>),
NotEqualTo(Box<ParseTree>, Box<ParseTree>),
GreaterThan(Box<ParseTree>, Box<ParseTree>),
GreaterThanOrEqualTo(Box<ParseTree>, Box<ParseTree>),
LessThan(Box<ParseTree>, Box<ParseTree>),
LessThanOrEqualTo(Box<ParseTree>, Box<ParseTree>),
Not(Box<ParseTree>),
And(Box<ParseTree>, Box<ParseTree>),
Or(Box<ParseTree>, Box<ParseTree>),
// Defining Objects // Defining Objects
Equ(String, Box<ParseTree>, Box<ParseTree>), Equ(String, Box<ParseTree>, Box<ParseTree>),
@@ -66,33 +51,20 @@ pub(crate) enum ParseTree {
FunctionDefinition(Function, Box<ParseTree>), FunctionDefinition(Function, Box<ParseTree>),
LambdaDefinition(Function), LambdaDefinition(Function),
// Functional Operations // Control Flow
Compose(Box<ParseTree>, Box<ParseTree>),
Id(Box<ParseTree>),
Head(Box<ParseTree>),
Tail(Box<ParseTree>),
Init(Box<ParseTree>),
Fini(Box<ParseTree>),
// Branching
If(Box<ParseTree>, Box<ParseTree>), If(Box<ParseTree>, Box<ParseTree>),
IfElse(Box<ParseTree>, Box<ParseTree>, Box<ParseTree>), IfElse(Box<ParseTree>, Box<ParseTree>, Box<ParseTree>),
// Evaluations // Evaluations
FunctionCall(String, Vec<ParseTree>), FunctionCall(String, Vec<ParseTree>),
_FunctionCallLocal(usize, Vec<ParseTree>),
Variable(String), Variable(String),
Constant(Value), _Local(usize),
NonCall(String), Value(Value),
GeneratedFunction(Function),
// Type Casts
IntCast(Box<ParseTree>),
FloatCast(Box<ParseTree>),
BoolCast(Box<ParseTree>),
StringCast(Box<ParseTree>),
// Misc
Print(Box<ParseTree>),
Nop, Nop,
NonCall(String),
Export(Vec<String>), Export(Vec<String>),
} }
@@ -113,12 +85,12 @@ impl<'a, I: Iterator<Item = Result<Token, TokenizeError>>> 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.globals.insert(k, v);
self self
} }
pub fn add_globals<Items: Iterator<Item = (String, Type)>>(self, items: Items) -> Self { pub fn _add_globals<Items: Iterator<Item = (String, Type)>>(self, items: Items) -> Self {
items.for_each(|(name, t)| { items.for_each(|(name, t)| {
self.globals.insert(name, t); self.globals.insert(name, t);
}); });
@@ -135,7 +107,7 @@ impl<'a, I: Iterator<Item = Result<Token, TokenizeError>>> Parser<'a, I> {
self self
} }
pub fn add_locals<Items: Iterator<Item = (String, Type)>>(mut self, items: Items) -> Self { pub fn _add_locals<Items: Iterator<Item = (String, Type)>>(mut self, items: Items) -> Self {
items.for_each(|(name, t)| { items.for_each(|(name, t)| {
self.locals.insert(name, t); self.locals.insert(name, t);
}); });
@@ -147,87 +119,115 @@ impl<'a, I: Iterator<Item = Result<Token, TokenizeError>>> Parser<'a, I> {
.ok_or(ParseError::IdentifierUndefined(ident.clone())) .ok_or(ParseError::IdentifierUndefined(ident.clone()))
} }
fn get_object_types<Names: Iterator<Item = String>>(&self, items: Names) -> impl Iterator<Item = Result<&Type, ParseError>> { fn _get_object_types<Names: Iterator<Item = String>>(&self, items: Names) -> impl Iterator<Item = Result<&Type, ParseError>> {
items.map(|x| self.get_object_type(&x)) items.map(|x| self.get_object_type(&x))
} }
// get at most count arguments
fn get_args(&mut self, count: usize) -> Result<Vec<ParseTree>, 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<ParseTree, ParseError> {
let operators: HashMap<Op, FunctionType> = 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<Type> = operator.1.iter().skip(args.len()).cloned().collect();
let (names, types): (Vec<String>, Vec<Type>) = 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<ParseTree, ParseError> { fn parse(&mut self) -> Result<ParseTree, ParseError> {
match self.tokens.next().ok_or(ParseError::NoInput)?.map_err(|e| ParseError::TokenizeError(e))? { let token = self.tokens.next()
Token::Constant(c) => Ok(ParseTree::Constant(c)), .ok_or(ParseError::NoInput)?
.map_err(|e| ParseError::TokenizeError(e))?;
match token {
Token::Constant(c) => Ok(ParseTree::Value(c)),
Token::Identifier(ident) => { Token::Identifier(ident) => {
match self.get_object_type(&ident)? { match self.get_object_type(&ident)? {
Type::Function(f) => { Type::Function(f) => {
let args = f.1.clone().iter() let f = f.clone();
.map(|_| self.parse()).collect::<Result<Vec<_>, ParseError>>()?; let args = self.get_args(f.1.len())?;
if args.len() < f.1.len() {
let mut counter = 0;
let func_args: Vec<Type> = f.1.iter().skip(args.len()).cloned().collect();
let (names, types): (Vec<String>, Vec<Type>) = 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::FunctionCall(ident, args))
} }
}
_ => Ok(ParseTree::Variable(ident)), _ => 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))?;
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(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()?))), Token::Operator(op) => match op {
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 => { Op::OpenArray => {
let mut depth = 1; let mut depth = 1;
@@ -257,18 +257,18 @@ impl<'a, I: Iterator<Item = Result<Token, TokenizeError>>> Parser<'a, I> {
.collect::<Result<_, ParseError>>()?; .collect::<Result<_, ParseError>>()?;
let tree = trees.into_iter().fold( let tree = trees.into_iter().fold(
ParseTree::Constant(Value::Array(Type::Any, vec![])), ParseTree::Value(Value::Array(Type::Any, vec![])),
|acc, x| ParseTree::Add(Box::new(acc), Box::new(x.clone())), |acc, x| ParseTree::Operator(Op::Add, vec![acc, x.clone()]),
); );
Ok(tree) Ok(tree)
} },
Op::OpenStatement => { Op::OpenStatement => {
let mut depth = 1; let mut depth = 1;
// take tokens until we reach the end of this array // 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 // 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 { let array_tokens = self.tokens.by_ref().take_while(|t| match t {
Ok(Token::Operator(Op::OpenStatement)) => { Ok(Token::Operator(Op::OpenStatement)) => {
depth += 1; depth += 1;
true true
@@ -280,45 +280,76 @@ impl<'a, I: Iterator<Item = Result<Token, TokenizeError>>> Parser<'a, I> {
_ => true, _ => true,
}).collect::<Result<Vec<_>, TokenizeError>>().map_err(|e| ParseError::TokenizeError(e))?; }).collect::<Result<Vec<_>, TokenizeError>>().map_err(|e| ParseError::TokenizeError(e))?;
let mut tokens = tokens let mut array_tokens = array_tokens
.into_iter() .into_iter()
.map(|t| Ok(t)) .map(|t| Ok(t))
.collect::<Vec<Result<Token, TokenizeError>>>() .collect::<Vec<Result<Token, TokenizeError>>>()
.into_iter() .into_iter()
.peekable(); .peekable();
let trees: Vec<ParseTree> = Parser::new(&mut tokens, self.globals.borrow_mut()) let trees: Vec<ParseTree> = Parser::new(&mut array_tokens, self.globals.borrow_mut())
.locals(self.locals.to_owned()) .locals(self.locals.to_owned())
.collect::<Result<_, ParseError>>()?; .collect::<Result<_, ParseError>>()?;
let tree = trees.into_iter().fold( let tree = trees.into_iter().fold(
ParseTree::Nop, ParseTree::Nop,
|acc, x| ParseTree::Compose(Box::new(acc), Box::new(x.clone())), |acc, x| ParseTree::Operator(Op::Compose, vec![acc, x.clone()]),
); );
Ok(tree) 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::Equ | Op::LazyEqu => {
Op::Tail => Ok(ParseTree::Tail(Box::new(self.parse()?))), let token = self.tokens.next().ok_or(ParseError::UnexpectedEndInput)?.map_err(|e| ParseError::TokenizeError(e))?;
Op::Init => Ok(ParseTree::Init(Box::new(self.parse()?))),
Op::Fini => Ok(ParseTree::Fini(Box::new(self.parse()?))), 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::LambdaDefine(arg_count) => {
let f = self.parse_lambda_definition(arg_count)?;
Ok(ParseTree::LambdaDefinition(f))
},
Op::Export => { Op::Export => {
let list = self.parse()?; let list = self.parse()?;
let mut g = HashMap::new(); let mut g = HashMap::new();
let list = Executor::new(&mut vec![Ok(list)].into_iter(), &mut g).next().unwrap().map_err(|_| ParseError::NoInput)?; let list = Executor::new(&mut vec![Ok(list)].into_iter(), &mut g)
.next().unwrap().map_err(|_| ParseError::RuntimeError)?;
if let Value::Array(Type::String, items) = list { if let Value::Array(Type::String, items) = list {
let names = items.into_iter().map(|x| match x { let names = items.into_iter().map(|x| match x {
@@ -327,7 +358,10 @@ impl<'a, I: Iterator<Item = Result<Token, TokenizeError>>> Parser<'a, I> {
}); });
for name in names.clone() { for name in names.clone() {
let t = self.locals.remove(&name).ok_or(ParseError::IdentifierUndefined(name.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); self.globals.insert(name, t);
} }
@@ -336,14 +370,32 @@ impl<'a, I: Iterator<Item = Result<Token, TokenizeError>>> Parser<'a, I> {
Err(ParseError::NoInput) 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)), t => Err(ParseError::UnwantedToken(t)),
} }
} }
fn parse_lambda(&mut self, arg_count: usize) -> Result<Function, ParseError> { fn parse_lambda_definition(&mut self, arg_count: usize) -> Result<Function, ParseError> {
let (t, args) = Self::parse_function_declaration(self.tokens, arg_count)?; let (t, args) = Self::parse_function_declaration(self.tokens, arg_count)?;
let mut locals = self.locals.clone(); let mut locals = self.locals.clone();
@@ -357,7 +409,7 @@ impl<'a, I: Iterator<Item = Result<Token, TokenizeError>>> Parser<'a, I> {
.locals(locals).parse()?))) .locals(locals).parse()?)))
} }
fn parse_function(&mut self, arg_count: usize) -> Result<Function, ParseError> { fn parse_function_definition(&mut self, arg_count: usize) -> Result<Function, ParseError> {
let name = Self::get_identifier(self.tokens.next())?; let name = Self::get_identifier(self.tokens.next())?;
let (t, args) = Self::parse_function_declaration(self.tokens, arg_count)?; let (t, args) = Self::parse_function_declaration(self.tokens, arg_count)?;

View File

@@ -41,7 +41,7 @@ impl Display for TokenizeError {
impl error::Error for TokenizeError {} impl error::Error for TokenizeError {}
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Op { pub enum Op {
Add, Add,
Sub, Sub,
@@ -79,12 +79,12 @@ pub enum Op {
Empty, Empty,
And, And,
Or, Or,
NonCall,
Head, Head,
Tail, Tail,
Init, Init,
Fini, Fini,
Export, Export,
NonCall,
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@@ -119,6 +119,7 @@ impl Token {
// Match keywords first // Match keywords first
"true" => Ok(Token::Constant(Value::Bool(true))), "true" => Ok(Token::Constant(Value::Bool(true))),
"false" => Ok(Token::Constant(Value::Bool(false))), "false" => Ok(Token::Constant(Value::Bool(false))),
"nil" => Ok(Token::Constant(Value::Nil)),
"int" => Ok(Token::Operator(Op::IntCast)), "int" => Ok(Token::Operator(Op::IntCast)),
"float" => Ok(Token::Operator(Op::FloatCast)), "float" => Ok(Token::Operator(Op::FloatCast)),
"bool" => Ok(Token::Operator(Op::BoolCast)), "bool" => Ok(Token::Operator(Op::BoolCast)),
@@ -205,7 +206,7 @@ impl<R: BufRead> Tokenizer<R> {
("!", Op::Not), ("!", Op::Not),
("&&", Op::And), ("&&", Op::And),
("||", Op::Or), ("||", Op::Or),
("'", Op::NonCall), ("\\", Op::NonCall),
]); ]);
let c = if let Some(c) = iter.next() { let c = if let Some(c) = iter.next() {