Improve expression implementation
This commit is contained in:
parent
d043f334db
commit
65bb2c9d84
@ -18,8 +18,8 @@ impl AbstractTree for Expression {
|
|||||||
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
|
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
|
||||||
debug_assert_eq!("expression", node.kind());
|
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() {
|
let expression = match child.kind() {
|
||||||
"value" => Expression::Value(ValueNode::from_syntax_node(source, child)?),
|
"value" => Expression::Value(ValueNode::from_syntax_node(source, child)?),
|
||||||
"identifier" => Self::Identifier(Identifier::from_syntax_node(source, child)?),
|
"identifier" => Self::Identifier(Identifier::from_syntax_node(source, child)?),
|
||||||
@ -28,18 +28,21 @@ impl AbstractTree for Expression {
|
|||||||
"function_call" => {
|
"function_call" => {
|
||||||
Expression::FunctionCall(FunctionCall::from_syntax_node(source, child)?)
|
Expression::FunctionCall(FunctionCall::from_syntax_node(source, child)?)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => continue,
|
||||||
return Err(Error::UnexpectedSyntaxNode {
|
};
|
||||||
|
|
||||||
|
return Ok(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
let child = node.child(0).unwrap();
|
||||||
|
|
||||||
|
Err(Error::UnexpectedSyntaxNode {
|
||||||
expected: "value, identifier, math or function_call",
|
expected: "value, identifier, math or function_call",
|
||||||
actual: child.kind(),
|
actual: child.kind(),
|
||||||
location: child.start_position(),
|
location: child.start_position(),
|
||||||
relevant_source: source[child.byte_range()].to_string(),
|
relevant_source: source[child.byte_range()].to_string(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
Ok(expression)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run(&self, source: &str, context: &mut VariableMap) -> Result<Value> {
|
fn run(&self, source: &str, context: &mut VariableMap) -> Result<Value> {
|
||||||
match self {
|
match self {
|
||||||
|
@ -43,31 +43,17 @@ impl AbstractTree for Math {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, source: &str, context: &mut VariableMap) -> Result<Value> {
|
fn run(&self, source: &str, context: &mut VariableMap) -> Result<Value> {
|
||||||
match self.operator {
|
let left = self.left.run(source, context)?;
|
||||||
MathOperator::Add | MathOperator::Subtract | MathOperator::Multiply => {
|
let right = self.right.run(source, context)?;
|
||||||
let left_value = self.left.run(source, context)?.as_int()?;
|
let value = match self.operator {
|
||||||
let right_value = self.right.run(source, context)?.as_int()?;
|
MathOperator::Add => left + right,
|
||||||
let outcome = match &self.operator {
|
MathOperator::Subtract => left - right,
|
||||||
MathOperator::Add => left_value + right_value,
|
MathOperator::Multiply => left * right,
|
||||||
MathOperator::Subtract => left_value - right_value,
|
MathOperator::Divide => left / right,
|
||||||
MathOperator::Multiply => left_value * right_value,
|
MathOperator::Modulo => left % right,
|
||||||
_ => panic!("Unreachable"),
|
}?;
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Value::Integer(outcome))
|
Ok(value)
|
||||||
}
|
|
||||||
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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,7 +277,10 @@ impl fmt::Display for Error {
|
|||||||
actual,
|
actual,
|
||||||
location,
|
location,
|
||||||
relevant_source,
|
relevant_source,
|
||||||
} => todo!(),
|
} => write!(
|
||||||
|
f,
|
||||||
|
"Expected syntax node {expected}, but got {actual} at {location}. Code: {relevant_source} ",
|
||||||
|
),
|
||||||
ExpectedChildNode { empty_node_sexp } => todo!(),
|
ExpectedChildNode { empty_node_sexp } => todo!(),
|
||||||
WrongColumnAmount { expected, actual } => todo!(),
|
WrongColumnAmount { expected, actual } => todo!(),
|
||||||
ToolFailure(_) => todo!(),
|
ToolFailure(_) => todo!(),
|
||||||
|
@ -16,7 +16,7 @@ use std::{
|
|||||||
convert::TryFrom,
|
convert::TryFrom,
|
||||||
fmt::{self, Display, Formatter},
|
fmt::{self, Display, Formatter},
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
ops::{Add, AddAssign, Sub, SubAssign},
|
ops::{Add, AddAssign, Div, Mul, Rem, Sub, SubAssign},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod function;
|
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 {
|
impl AddAssign for Value {
|
||||||
fn add_assign(&mut self, other: Self) {
|
fn add_assign(&mut self, other: Self) {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
|
Loading…
Reference in New Issue
Block a user