Improve expression implementation
This commit is contained in:
parent
d043f334db
commit
65bb2c9d84
@ -18,27 +18,30 @@ impl AbstractTree for Expression {
|
||||
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
|
||||
debug_assert_eq!("expression", node.kind());
|
||||
|
||||
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)?),
|
||||
"math" => Expression::Math(Box::new(Math::from_syntax_node(source, child)?)),
|
||||
"logic" => Expression::Logic(Box::new(Logic::from_syntax_node(source, child)?)),
|
||||
"function_call" => {
|
||||
Expression::FunctionCall(FunctionCall::from_syntax_node(source, child)?)
|
||||
}
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
return Ok(expression);
|
||||
}
|
||||
|
||||
let child = node.child(0).unwrap();
|
||||
|
||||
let expression = match child.kind() {
|
||||
"value" => Expression::Value(ValueNode::from_syntax_node(source, child)?),
|
||||
"identifier" => Self::Identifier(Identifier::from_syntax_node(source, child)?),
|
||||
"math" => Expression::Math(Box::new(Math::from_syntax_node(source, child)?)),
|
||||
"logic" => Expression::Logic(Box::new(Logic::from_syntax_node(source, child)?)),
|
||||
"function_call" => {
|
||||
Expression::FunctionCall(FunctionCall::from_syntax_node(source, child)?)
|
||||
}
|
||||
_ => {
|
||||
return 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)
|
||||
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(),
|
||||
})
|
||||
}
|
||||
|
||||
fn run(&self, source: &str, context: &mut VariableMap) -> Result<Value> {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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!(),
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user