This commit is contained in:
2024-10-29 00:57:07 -04:00
parent 4c4c69d40b
commit fbd95ecafb
3 changed files with 240 additions and 212 deletions

View File

@@ -89,253 +89,217 @@ impl Executor {
locals locals
} }
fn op_error(op: &Op, args: &[Value]) -> Error {
Error::new(format!("no overload of {op} matches the arguments {}",
args.iter().map(|x| format!("{x}")).collect::<Vec<_>>().join(", ")))
}
pub(crate) fn exec(&mut self, tree: ParseTree) -> Result<Value, Error> { pub(crate) fn exec(&mut self, tree: ParseTree) -> Result<Value, Error> {
match tree { match tree {
ParseTree::Operator(op, args) => { ParseTree::Operator(op, args) => {
let args: Vec<Value> = args.into_iter() let args: Vec<Value> = args.into_iter()
.map(|x| self.exec(x)).collect::<Result<_, _>>()?; .map(|x| self.exec(x)).collect::<Result<_, _>>()?;
match op { match (&op, &args[..]) {
Op::Add => match &args[..] { (Op::Add, [x, y]) => match (x, y) {
[Value::Int(x), Value::Int(y)] => Ok(Value::Int(x + 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::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::Int(x), Value::Float(y)) => Ok(Value::Float(*x as f64 + y)),
[Value::Float(x), Value::Float(y)] => Ok(Value::Float(x + 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::String(x), Value::String(y)) => Ok(Value::String(format!("{x}{y}"))),
[Value::Nil, x] => Ok(x.clone()), _ => Err(Self::op_error(&op, &args)),
[x, Value::Nil] => Ok(x.clone()), },
[x, y] => Err(Error::new(format!("no overload of + exists for types {} and {}", x.get_type(), y.get_type()))), (Op::Neg, [x]) => match x {
_ => unreachable!(), Value::Int(x) => Ok(Value::Int(-x)),
} Value::Float(x) => Ok(Value::Float(-x)),
Op::Concat => match &args[..] { _ => Err(Self::op_error(&op, &args)),
[Value::Array(xtype, x), Value::Array(ytype, y)] => { },
(Op::Concat, [x, y]) => match (x, y) {
(Value::Array(xtype, x), Value::Nil) => Ok(Value::Array(xtype.clone(), x.clone())),
(Value::Nil, Value::Array(xtype, x)) => Ok(Value::Array(xtype.clone(), x.clone())),
(Value::Array(xtype, x), Value::Array(ytype, y)) =>
if xtype != ytype { if xtype != ytype {
return Err(Error::new(format!("expected type {} but found {}", xtype, ytype))); Err(Error::new(format!("expected type {} but found {}", xtype, ytype)))
} } else {
Ok(Value::Array(xtype.clone(), [x.clone(), y.clone()].concat()))
Ok(Value::Array(xtype.clone(), [x.clone(), y.clone()].concat())) },
}, _ => Err(Self::op_error(&op, &args)),
_ => Err(Error::new("++".into())), },
} (Op::Prepend, [x, y]) => match (x, y) {
Op::Prepend => match &args[..] { (Value::Nil, Value::Array(xtype, x)) => Ok(Value::Array(xtype.clone(), x.clone())),
[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(Error::new(format!("expected type {} but found {}", t, xtype))); Err(Error::new(format!("expected type {} but found {}", t, xtype)))
} else {
Ok(Value::Array(xtype, [vec![x.clone()], y.clone()].concat()))
} }
Ok(Value::Array(xtype, [vec![x.clone()], y.clone()].concat()))
}, },
[x, y] => Err(Error::new(format!("no overload of [+ exists for types {} and {}", x.get_type(), y.get_type()))), _ => Err(Self::op_error(&op, &args)),
_ => unreachable!(), },
} (Op::Append, [x, y]) => match (x, y) {
Op::Append => match &args[..] { (Value::Array(xtype, x), Value::Nil) => Ok(Value::Array(xtype.clone(), x.clone())),
[Value::Array(t, y), x] => { (Value::Array(t, y), x) => {
let xtype = x.get_type(); let xtype = x.get_type();
if *t != xtype { if *t != xtype {
return Err(Error::new(format!("expected type {} but found {}", t, xtype))); Err(Error::new(format!("expected type {} but found {}", t, xtype)))
} else {
Ok(Value::Array(xtype, [y.clone(), vec![x.clone()]].concat()))
} }
Ok(Value::Array(xtype, [y.clone(), vec![x.clone()]].concat()))
}, },
_ => Err(Error::new("+]".into())), _ => Err(Self::op_error(&op, &args)),
} },
Op::Insert => match &args[..] { (Op::Insert, [Value::Int(idx), x, Value::Array(t, y)]) => {
[Value::Int(idx), x, Value::Array(t, y)] => { let mut y = y.clone();
let mut y = y.clone(); let xtype = x.get_type();
let xtype = x.get_type(); if *t != xtype {
Err(Error::new(format!("expected type {} but found {}", t, xtype)))
if *t != xtype { } else if *idx as usize > y.len() {
return Err(Error::new(format!("expected type {} but found {}", t, xtype))); Err(Error::new("attempt to insert out of array len".into()))
} } else {
if *idx as usize > y.len() {
return Err(Error::new("attempt to insert out of array len".into()));
}
y.insert(*idx as usize, x.clone()); y.insert(*idx as usize, x.clone());
Ok(Value::Array(t.clone(), y)) Ok(Value::Array(t.clone(), y))
}, }
_ => Err(Error::new("[+]".into())), },
} (Op::Sub, [x, y]) => match (x, y) {
Op::Sub => match &args[..] { (Value::Int(x), Value::Int(y)) => Ok(Value::Int(x - y)),
[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::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::Int(y)] => Ok(Value::Float(x - *y as f64)), (Value::Float(x), Value::Float(y)) => Ok(Value::Float(x - y)),
[Value::Float(x), Value::Float(y)] => Ok(Value::Float(x - y)), _ => Err(Self::op_error(&op, &args)),
[Value::Nil, x] => Ok(x.clone()), },
[x, Value::Nil] => Ok(x.clone()), (Op::Mul, [x, y]) => match (x, y) {
_ => Err(Error::new("todo: actual error output".into())), (Value::Int(x), Value::Int(y)) => Ok(Value::Int(x * y)),
} (Value::Int(x), Value::Float(y)) => Ok(Value::Float(*x as f64 * y)),
Op::Mul => match &args[..] { (Value::Float(x), Value::Int(y)) => Ok(Value::Float(x * *y as f64)),
[Value::Int(x), Value::Int(y)] => Ok(Value::Int(x * y)), (Value::Float(x), Value::Float(y)) => Ok(Value::Float(x * y)),
[Value::Int(x), Value::Float(y)] => Ok(Value::Float(*x as f64 * y)), _ => Err(Self::op_error(&op, &args)),
[Value::Float(x), Value::Int(y)] => Ok(Value::Float(x * *y as f64)), },
[Value::Float(x), Value::Float(y)] => Ok(Value::Float(x * y)), (Op::Div, [x, y]) => match (x, y) {
[Value::Nil, x] => Ok(x.clone()), (Value::Int(x), Value::Int(y)) => Ok(Value::Float(*x as f64 / *y as f64)),
[x, Value::Nil] => Ok(x.clone()), (Value::Float(x), Value::Int(y)) => Ok(Value::Float(x / *y as f64)),
_ => Err(Error::new("todo: actual error output".into())), (Value::Int(x), Value::Float(y)) => Ok(Value::Float(*x as f64 / y)),
} (Value::Float(x), Value::Float(y)) => Ok(Value::Float(x / y)),
Op::Div => match &args[..] { _ => Err(Self::op_error(&op, &args)),
[Value::Int(x), Value::Int(y)] => Ok(Value::Float(*x as f64 / *y as f64)), },
[Value::Float(x), Value::Int(y)] => Ok(Value::Float(x / *y as f64)), (Op::FloorDiv, [x, y]) => match (x, y) {
[Value::Int(x), Value::Float(y)] => Ok(Value::Float(*x as f64 / y)), (Value::Int(x), Value::Int(y)) => Ok(Value::Int(x / y)),
[Value::Float(x), Value::Float(y)] => Ok(Value::Float(x / y)), (Value::Float(x), Value::Int(y)) => Ok(Value::Int(*x as i64 / y)),
[Value::Nil, x] => Ok(x.clone()), (Value::Int(x), Value::Float(y)) => Ok(Value::Int(x / *y as i64)),
[x, Value::Nil] => Ok(x.clone()), (Value::Float(x), Value::Float(y)) => Ok(Value::Int(*x as i64 / *y as i64)),
_ => Err(Error::new("todo: actual error output".into())), _ => Err(Self::op_error(&op, &args)),
} },
Op::FloorDiv => match &args[..] { (Op::Exp, [x, y]) => match (x, y) {
[Value::Int(x), Value::Int(y)] => Ok(Value::Int(x / y)), (Value::Int(x), Value::Int(y)) => Ok(Value::Float((*x as f64).powf(*y as f64))),
[Value::Float(x), Value::Int(y)] => Ok(Value::Int(*x as i64 / y)), (Value::Float(x), Value::Int(y)) => Ok(Value::Float(x.powf(*y as f64))),
[Value::Int(x), Value::Float(y)] => Ok(Value::Int(x / *y as i64)), (Value::Int(x), Value::Float(y)) => Ok(Value::Float((*x as f64).powf(*y))),
[Value::Float(x), Value::Float(y)] => Ok(Value::Int(*x as i64 / *y as i64)), (Value::Float(x), Value::Float(y)) => Ok(Value::Float(x.powf(*y))),
[Value::Nil, x] => Ok(x.clone()), _ => Err(Self::op_error(&op, &args)),
[x, Value::Nil] => Ok(x.clone()), },
_ => Err(Error::new("todo: actual error output".into())), (Op::Mod, [x, y]) => match (x, y) {
} (Value::Int(x), Value::Int(y)) => Ok(Value::Int(x % y)),
Op::Exp => match &args[..] { (Value::Float(x), Value::Int(y)) => Ok(Value::Float(x % *y as f64)),
[Value::Int(x), Value::Int(y)] => Ok(Value::Float((*x as f64).powf(*y as f64))), (Value::Int(x), Value::Float(y)) => Ok(Value::Float(*x as f64 % 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 % y)),
[Value::Int(x), Value::Float(y)] => Ok(Value::Float((*x as f64).powf(*y))), _ => Err(Self::op_error(&op, &args)),
[Value::Float(x), Value::Float(y)] => Ok(Value::Float(x.powf(*y))), },
[Value::Nil, x] => Ok(x.clone()), (Op::GreaterThan, [x, y]) => match (x, y) {
[x, Value::Nil] => Ok(x.clone()), (Value::Int(x), Value::Int(y)) => Ok(Value::Bool(x > y)),
_ => Err(Error::new("todo: fsadfdsf".into())), (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)),
Op::Mod => match &args[..] { (Value::Float(x), Value::Float(y)) => Ok(Value::Bool(x > y)),
[Value::Int(x), Value::Int(y)] => Ok(Value::Int(x % y)), _ => Err(Self::op_error(&op, &args)),
[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)), (Op::GreaterThanOrEqualTo, [x, y]) => match (x, y) {
[Value::Float(x), Value::Float(y)] => Ok(Value::Float(x % y)), (Value::Int(x), Value::Int(y)) => Ok(Value::Bool(x >= y)),
[Value::Nil, x] => Ok(x.clone()), (Value::Float(x), Value::Int(y)) => Ok(Value::Bool(*x >= *y as f64)),
[x, Value::Nil] => Ok(x.clone()), (Value::Int(x), Value::Float(y)) => Ok(Value::Bool(*x as f64 >= *y)),
_ => Err(Error::new("todo: actual error output".into())), (Value::Float(x), Value::Float(y)) => Ok(Value::Bool(x >= y)),
} _ => Err(Self::op_error(&op, &args)),
Op::GreaterThan => match &args[..] { },
[Value::Int(x), Value::Int(y)] => Ok(Value::Bool(x > y)), (Op::LessThan, [x, y]) => match (x, y) {
[Value::Float(x), Value::Int(y)] => Ok(Value::Bool(*x > *y as f64)), (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::Int(x), Value::Float(y)) => Ok(Value::Bool((*x as f64) < *y)),
_ => Err(Error::new("todo: actual error output".into())), (Value::Float(x), Value::Float(y)) => Ok(Value::Bool(x < y)),
} _ => Err(Self::op_error(&op, &args)),
Op::GreaterThanOrEqualTo => match &args[..] { },
[Value::Int(x), Value::Int(y)] => Ok(Value::Bool(x >= y)), (Op::LessThanOrEqualTo, [x, y]) => match (x, y) {
[Value::Float(x), Value::Int(y)] => Ok(Value::Bool(*x >= *y as f64)), (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::Int(x), Value::Float(y)) => Ok(Value::Bool(*x as f64 <= *y)),
_ => Err(Error::new("todo: actual error output".into())), (Value::Float(x), Value::Float(y)) => Ok(Value::Bool(x <= y)),
} _ => Err(Self::op_error(&op, &args)),
Op::LessThan => match &args[..] { },
[Value::Int(x), Value::Int(y)] => Ok(Value::Bool(x < y)), (Op::EqualTo, [x, y]) => match (x, y) {
[Value::Float(x), Value::Int(y)] => Ok(Value::Bool(*x < *y as f64)), (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::Int(x), Value::Float(y)) => Ok(Value::Bool(*x as f64 == *y)),
_ => Err(Error::new("todo: actual error output".into())), (Value::Float(x), Value::Float(y)) => Ok(Value::Bool(x == y)),
} _ => Err(Self::op_error(&op, &args)),
Op::LessThanOrEqualTo => match &args[..] { },
[Value::Int(x), Value::Int(y)] => Ok(Value::Bool(x <= y)), (Op::NotEqualTo, [x, y]) => match (x, y) {
[Value::Float(x), Value::Int(y)] => Ok(Value::Bool(*x <= *y as f64)), (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::Int(x), Value::Float(y)) => Ok(Value::Bool(*x as f64 != *y)),
_ => Err(Error::new("todo: actual error output".into())), (Value::Float(x), Value::Float(y)) => Ok(Value::Bool(x != y)),
} _ => Err(Self::op_error(&op, &args)),
Op::EqualTo => match &args[..] { },
[Value::Int(x), Value::Int(y)] => Ok(Value::Bool(x == y)), (Op::Not, [Value::Bool(b)]) => Ok(Value::Bool(!b)),
[Value::Float(x), Value::Int(y)] => Ok(Value::Bool(*x == *y as f64)), (Op::Or, [x, y]) => match (x, y) {
[Value::Int(x), Value::Float(y)] => Ok(Value::Bool(*x as f64 == *y)), (Value::Bool(x), Value::Bool(y)) => Ok(Value::Bool(*x || *y)),
[Value::Float(x), Value::Float(y)] => Ok(Value::Bool(x == y)), _ => Err(Self::op_error(&op, &args)),
_ => Err(Error::new("todo: actual error output".into())), },
} (Op::And, [x, y]) => match (x, y) {
Op::NotEqualTo => match &args[..] { (Value::Bool(x), Value::Bool(y)) => Ok(Value::Bool(*x && *y)),
[Value::Int(x), Value::Int(y)] => Ok(Value::Bool(x != y)), _ => Err(Self::op_error(&op, &args)),
[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)), (Op::Compose, [_, v]) => Ok(v.clone()),
[Value::Float(x), Value::Float(y)] => Ok(Value::Bool(x != y)), (Op::Head, [Value::Array(_, x)]) => Ok(x.first().ok_or(Error::new("passed an empty array to head".into()))?.clone()),
_ => Err(Error::new("todo: actual error output".into())), (Op::Tail, [Value::Array(t, x)]) => Ok(Value::Array(t.clone(), if x.len() > 0 { x[1..].to_vec() } else { vec![] })),
} (Op::Init, [Value::Array(t, x)]) => Ok(Value::Array(t.clone(), if x.len() > 0 { x[..x.len() - 1].to_vec() } else { vec![] })),
Op::Not => match &args[0] { (Op::Fini, [Value::Array(_, x)]) => Ok(x.last().ok_or(Error::new("passed an empty array to fini".into()))?.clone()),
Value::Bool(b) => Ok(Value::Bool(!b)), (Op::Id, [x]) => Ok(x.clone()),
_ => Err(Error::new("todo: actual error output".into())), (Op::IntCast, [x]) => match x {
}
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(Error::new("todo: actual error output".into())),
}
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(Error::new("todo: actual error output".into())),
}
Op::Compose => match &args[..] {
[_, v] => Ok(v.clone()),
_ => Err(Error::new("todo: actual error output".into())),
}
Op::Head => match &args[0] {
Value::Array(_, x) => Ok(x.first().ok_or(Error::new(format!("passed an empty array to head")))?.clone()),
_ => Err(Error::new("head".into())),
}
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(Error::new("tail".into())),
}
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(Error::new("init".into())),
}
Op::Fini => match &args[0] {
Value::Array(_, x) => Ok(x.last().ok_or(Error::new(format!("passed an empty array to fini")))?.clone()),
_ => Err(Error::new("fini".into())),
}
Op::Id => match &args[0] {
x => Ok(x.clone()),
}
Op::IntCast => match &args[0] {
Value::Int(x) => Ok(Value::Int(*x)), Value::Int(x) => Ok(Value::Int(*x)),
Value::Float(x) => Ok(Value::Int(*x as i64)), Value::Float(x) => Ok(Value::Int(*x as i64)),
Value::Bool(x) => Ok(Value::Int(if *x { 1 } else { 0 })), Value::Bool(x) => Ok(Value::Int(if *x { 1 } else { 0 })),
Value::String(x) => { Value::String(x) => {
let r: i64 = x.parse().map_err(|_| Error::new(format!("failed to parse {} into {}", x, Type::Int)))?; let r: i64 = x.parse().map_err(|_| Error::new(format!("failed to parse {} into {}", x, Type::Int)))?;
Ok(Value::Int(r)) Ok(Value::Int(r))
} },
x => Err(Error::new(format!("no possible conversion from {} into {}", x, Type::Int))), _ => Err(Error::new(format!("no possible conversion from {} into {}", x, Type::Int))),
} },
Op::FloatCast => match &args[0] { (Op::FloatCast, [x]) => match x {
Value::Int(x) => Ok(Value::Float(*x as f64)), Value::Int(x) => Ok(Value::Float(*x as f64)),
Value::Float(x) => Ok(Value::Float(*x)), Value::Float(x) => Ok(Value::Float(*x)),
Value::Bool(x) => Ok(Value::Float(if *x { 1.0 } else { 0.0 })), Value::Bool(x) => Ok(Value::Float(if *x { 1.0 } else { 0.0 })),
Value::String(x) => { Value::String(x) => {
let r: f64 = x.parse().map_err(|_| Error::new(format!("failed to parse {} into {}", x, Type::Float)))?; let r: f64 = x.parse().map_err(|_| Error::new(format!("failed to parse {} into {}", x, Type::Float)))?;
Ok(Value::Float(r)) Ok(Value::Float(r))
} },
x => Err(Error::new(format!("no possible conversion from {} into {}", x, Type::Float))), _ => Err(Error::new(format!("no possible conversion from {} into {}", x, Type::Float))),
} },
Op::BoolCast => match &args[0] { (Op::BoolCast, [x]) => match x {
Value::Int(x) => Ok(Value::Bool(*x != 0)), Value::Int(x) => Ok(Value::Bool(*x != 0)),
Value::Float(x) => Ok(Value::Bool(*x != 0.0)), Value::Float(x) => Ok(Value::Bool(*x != 0.0)),
Value::Bool(x) => Ok(Value::Bool(*x)), Value::Bool(x) => Ok(Value::Bool(*x)),
Value::String(x) => Ok(Value::Bool(!x.is_empty())), Value::String(x) => Ok(Value::Bool(!x.is_empty())),
Value::Array(_, vec) => Ok(Value::Bool(!vec.is_empty())), Value::Array(_, vec) => Ok(Value::Bool(!vec.is_empty())),
x => Err(Error::new(format!("no possible conversion from {} into {}", x, Type::Bool))), _ => Err(Error::new(format!("no possible conversion from {} into {}", x, Type::Bool))),
} },
Op::StringCast => Ok(Value::String(format!("{}", &args[0]))), (Op::StringCast, [x]) => Ok(Value::String(format!("{}", x))),
Op::Print => match &args[0] { (Op::Print, [x]) => match x {
Value::String(s) => { Value::String(s) => {
println!("{s}"); println!("{s}");
Ok(Value::Nil) Ok(Value::Nil)
} }
x => { _ => {
println!("{x}"); println!("{x}");
Ok(Value::Nil) Ok(Value::Nil)
} }
} },
_ => unreachable!(), _ => Err(Self::op_error(&op, &args)),
} }
} }
ParseTree::Equ(ident, body, scope) => { ParseTree::Equ(ident, body, scope) => {
@@ -345,7 +309,9 @@ impl Executor {
let value = self.exec(*body)?; let value = self.exec(*body)?;
let g = self.globals.clone(); let g = self.globals.clone();
let r = self.add_local_mut(ident.clone(), Arc::new(Mutex::new(Object::value(value, g, self.locals.to_owned())))) let r = self.add_local_mut(
ident.clone(),
Arc::new(Mutex::new(Object::value(value, g, self.locals.to_owned()))))
.exec(*scope); .exec(*scope);
self.locals.remove(&ident); self.locals.remove(&ident);

View File

@@ -109,6 +109,7 @@ impl Parser {
let operators: HashMap<Op, FunctionType> = HashMap::from([ let operators: HashMap<Op, FunctionType> = HashMap::from([
(Op::Add, FunctionType(Box::new(Type::Any), vec![Type::Any, Type::Any])), (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::Sub, FunctionType(Box::new(Type::Any), vec![Type::Any, Type::Any])),
(Op::Neg, FunctionType(Box::new(Type::Any), vec![Type::Any])),
(Op::Mul, 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::Float), vec![Type::Any, Type::Any])), (Op::Div, FunctionType(Box::new(Type::Float), vec![Type::Any, Type::Any])),
(Op::FloorDiv, FunctionType(Box::new(Type::Int), vec![Type::Any, Type::Any])), (Op::FloorDiv, FunctionType(Box::new(Type::Int), vec![Type::Any, Type::Any])),

View File

@@ -7,6 +7,8 @@ use crate::error::Error;
use super::Value; use super::Value;
use std::io::BufRead; use std::io::BufRead;
use std::ops::Range; use std::ops::Range;
use std::fmt;
use std::fmt::Formatter;
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Op { pub enum Op {
@@ -17,6 +19,7 @@ pub enum Op {
FloorDiv, FloorDiv,
Exp, Exp,
Equ, Equ,
Neg,
Mod, Mod,
LazyEqu, LazyEqu,
TypeDeclaration, TypeDeclaration,
@@ -59,6 +62,63 @@ pub enum Op {
NonCall, NonCall,
} }
impl fmt::Display for Op {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let s = match self {
Op::Add => "+",
Op::Sub => "-",
Op::Mul => "*",
Op::Div => "/",
Op::FloorDiv => "//",
Op::Exp => "**",
Op::Equ => "=",
Op::Neg => "_",
Op::Mod => "%",
Op::LazyEqu => ".",
Op::TypeDeclaration => "?.",
Op::FunctionDefine(_n) => ":",
Op::FunctionDeclare(_n) => "?:",
Op::LambdaDefine(_n) => ";",
Op::Arrow => "->",
Op::Compose => "~",
Op::Id => ",",
Op::If => "?",
Op::IfElse => "??",
Op::GreaterThan => ">",
Op::LessThan => "<",
Op::EqualTo => "==",
Op::NotEqualTo => "!=",
Op::GreaterThanOrEqualTo => ">=",
Op::LessThanOrEqualTo => ">=",
Op::Not => "!",
Op::IntCast => "int",
Op::FloatCast => "float",
Op::BoolCast => "bool",
Op::StringCast => "string",
Op::Print => "print",
Op::OpenArray => "[",
Op::CloseArray => "]",
Op::Concat => "++",
Op::Prepend => "[+",
Op::Append => "+]",
Op::Insert => "[+]",
Op::OpenStatement => "(",
Op::CloseStatement => ")",
Op::Empty => "empty",
Op::And => "&&",
Op::Or => "||",
Op::Head => "head",
Op::Tail => "tail",
Op::Init => "init",
Op::Fini => "fini",
Op::Export => "export",
Op::NonCall => "\\",
};
write!(f, "{s}")
}
}
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum TokenType { pub enum TokenType {
Identifier(String), Identifier(String),
@@ -75,9 +135,9 @@ impl TokenType {
"true" => TokenType::Constant(Value::Bool(true)), "true" => TokenType::Constant(Value::Bool(true)),
"false" => TokenType::Constant(Value::Bool(false)), "false" => TokenType::Constant(Value::Bool(false)),
"nil" => TokenType::Constant(Value::Nil), "nil" => TokenType::Constant(Value::Nil),
"int" => TokenType::Operator(Op::IntCast), "int" => TokenType::Operator(Op::IntCast),
"float" => TokenType::Operator(Op::FloatCast), "float" => TokenType::Operator(Op::FloatCast),
"bool" => TokenType::Operator(Op::BoolCast), "bool" => TokenType::Operator(Op::BoolCast),
"string" => TokenType::Operator(Op::StringCast), "string" => TokenType::Operator(Op::StringCast),
"print" => TokenType::Operator(Op::Print), "print" => TokenType::Operator(Op::Print),
"empty" => TokenType::Operator(Op::Empty), "empty" => TokenType::Operator(Op::Empty),
@@ -87,7 +147,7 @@ impl TokenType {
"fini" => TokenType::Operator(Op::Fini), "fini" => TokenType::Operator(Op::Fini),
"export" => TokenType::Operator(Op::Export), "export" => TokenType::Operator(Op::Export),
// Types // Built-in Types
"Any" => TokenType::Type(Type::Any), "Any" => TokenType::Type(Type::Any),
"Int" => TokenType::Type(Type::Int), "Int" => TokenType::Type(Type::Int),
"Float" => TokenType::Type(Type::Float), "Float" => TokenType::Type(Type::Float),
@@ -193,6 +253,7 @@ impl<R: BufRead> Tokenizer<R> {
("**", Op::Exp), ("**", Op::Exp),
("%", Op::Mod), ("%", Op::Mod),
("=", Op::Equ), ("=", Op::Equ),
("_", Op::Neg),
(".", Op::LazyEqu), (".", Op::LazyEqu),
("?.", Op::TypeDeclaration), ("?.", Op::TypeDeclaration),
(":", Op::FunctionDefine(1)), (":", Op::FunctionDefine(1)),
@@ -232,7 +293,7 @@ impl<R: BufRead> Tokenizer<R> {
if c.is_alphanumeric() { if c.is_alphanumeric() {
let mut token = String::from(c); let mut token = String::from(c);
while let Some(c) = self.next_char_if(|&c| c.is_alphanumeric() || c == '.' || c == '\'') { while let Some(c) = self.next_char_if(|&c| c.is_alphanumeric() || c == '.' || c == '\'' || c == '_') {
token.push(c); token.push(c);
} }