1
0

Improve expression implementation

This commit is contained in:
Jeff 2023-10-13 19:56:57 -04:00
parent d043f334db
commit 65bb2c9d84
4 changed files with 87 additions and 45 deletions

View File

@ -18,8 +18,8 @@ impl AbstractTree for Expression {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
debug_assert_eq!("expression", node.kind());
let child = node.child(0).unwrap();
for index in 0..node.child_count() {
let child = node.child(index).unwrap();
let expression = match child.kind() {
"value" => Expression::Value(ValueNode::from_syntax_node(source, child)?),
"identifier" => Self::Identifier(Identifier::from_syntax_node(source, child)?),
@ -28,18 +28,21 @@ impl AbstractTree for Expression {
"function_call" => {
Expression::FunctionCall(FunctionCall::from_syntax_node(source, child)?)
}
_ => {
return Err(Error::UnexpectedSyntaxNode {
_ => continue,
};
return Ok(expression);
}
let child = node.child(0).unwrap();
Err(Error::UnexpectedSyntaxNode {
expected: "value, identifier, math or function_call",
actual: child.kind(),
location: child.start_position(),
relevant_source: source[child.byte_range()].to_string(),
})
}
};
Ok(expression)
}
fn run(&self, source: &str, context: &mut VariableMap) -> Result<Value> {
match self {

View File

@ -43,31 +43,17 @@ impl AbstractTree for Math {
}
fn run(&self, source: &str, context: &mut VariableMap) -> Result<Value> {
match self.operator {
MathOperator::Add | MathOperator::Subtract | MathOperator::Multiply => {
let left_value = self.left.run(source, context)?.as_int()?;
let right_value = self.right.run(source, context)?.as_int()?;
let outcome = match &self.operator {
MathOperator::Add => left_value + right_value,
MathOperator::Subtract => left_value - right_value,
MathOperator::Multiply => left_value * right_value,
_ => panic!("Unreachable"),
};
let left = self.left.run(source, context)?;
let right = self.right.run(source, context)?;
let value = match self.operator {
MathOperator::Add => left + right,
MathOperator::Subtract => left - right,
MathOperator::Multiply => left * right,
MathOperator::Divide => left / right,
MathOperator::Modulo => left % right,
}?;
Ok(Value::Integer(outcome))
}
MathOperator::Divide | MathOperator::Modulo => {
let left_value = self.left.run(source, context)?.as_number()?;
let right_value = self.right.run(source, context)?.as_number()?;
let outcome = match self.operator {
MathOperator::Divide => left_value / right_value,
MathOperator::Modulo => left_value % right_value,
_ => panic!("Unreachable"),
};
Ok(Value::Float(outcome))
}
}
Ok(value)
}
}

View File

@ -277,7 +277,10 @@ impl fmt::Display for Error {
actual,
location,
relevant_source,
} => todo!(),
} => write!(
f,
"Expected syntax node {expected}, but got {actual} at {location}. Code: {relevant_source} ",
),
ExpectedChildNode { empty_node_sexp } => todo!(),
WrongColumnAmount { expected, actual } => todo!(),
ToolFailure(_) => todo!(),

View File

@ -16,7 +16,7 @@ use std::{
convert::TryFrom,
fmt::{self, Display, Formatter},
marker::PhantomData,
ops::{Add, AddAssign, Sub, SubAssign},
ops::{Add, AddAssign, Div, Mul, Rem, Sub, SubAssign},
};
pub mod function;
@ -260,6 +260,56 @@ impl Sub for Value {
}
}
impl Mul for Value {
type Output = Result<Self>;
fn mul(self, other: Self) -> Self::Output {
if self.is_integer() && other.is_integer() {
let left = self.as_int().unwrap();
let right = other.as_int().unwrap();
let value = Value::Integer(left.saturating_mul(right));
Ok(value)
} else {
let left = self.as_number()?;
let right = other.as_number()?;
let value = Value::Float(left * right);
Ok(value)
}
}
}
impl Div for Value {
type Output = Result<Self>;
fn div(self, other: Self) -> Self::Output {
let left = self.as_number()?;
let right = other.as_number()?;
let result = left / right;
let value = if result % 2.0 == 0.0 {
Value::Integer(result as i64)
} else {
Value::Float(result)
};
Ok(value)
}
}
impl Rem for Value {
type Output = Result<Self>;
fn rem(self, other: Self) -> Self::Output {
let left = self.as_int()?;
let right = other.as_int()?;
let result = left % right;
Ok(Value::Integer(result))
}
}
impl AddAssign for Value {
fn add_assign(&mut self, other: Self) {
match (self, other) {