2023-10-06 17:32:58 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use tree_sitter::Node;
|
|
|
|
|
2023-12-05 22:08:22 +00:00
|
|
|
use crate::{AbstractTree, Error, Expression, Map, Result, Type, Value};
|
2023-10-06 17:32:58 +00:00
|
|
|
|
2023-12-06 19:13:22 +00:00
|
|
|
/// Abstract representation of a logic expression.
|
2023-10-06 17:32:58 +00:00
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
|
|
|
pub struct Logic {
|
|
|
|
left: Expression,
|
|
|
|
operator: LogicOperator,
|
|
|
|
right: Expression,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl AbstractTree for Logic {
|
2023-11-30 03:54:46 +00:00
|
|
|
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
|
2023-12-30 02:15:03 +00:00
|
|
|
Error::expect_syntax_node(source, "logic", node)?;
|
|
|
|
|
2023-12-02 03:16:50 +00:00
|
|
|
let first_node = node.child(0).unwrap();
|
|
|
|
let (left_node, operator_node, right_node) = {
|
|
|
|
if first_node.is_named() {
|
|
|
|
(
|
|
|
|
first_node,
|
|
|
|
node.child(1).unwrap().child(0).unwrap(),
|
|
|
|
node.child(2).unwrap(),
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
(
|
|
|
|
node.child(1).unwrap(),
|
|
|
|
node.child(2).unwrap().child(0).unwrap(),
|
|
|
|
node.child(3).unwrap(),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
};
|
2023-11-30 03:54:46 +00:00
|
|
|
let left = Expression::from_syntax_node(source, left_node, context)?;
|
2023-10-06 17:32:58 +00:00
|
|
|
let operator = match operator_node.kind() {
|
|
|
|
"==" => LogicOperator::Equal,
|
2023-10-28 14:28:43 +00:00
|
|
|
"!=" => LogicOperator::NotEqual,
|
2023-10-06 17:32:58 +00:00
|
|
|
"&&" => LogicOperator::And,
|
|
|
|
"||" => LogicOperator::Or,
|
2023-10-09 19:54:47 +00:00
|
|
|
">" => LogicOperator::Greater,
|
|
|
|
"<" => LogicOperator::Less,
|
|
|
|
">=" => LogicOperator::GreaterOrEqual,
|
|
|
|
"<=" => LogicOperator::LessOrEqaul,
|
2023-10-06 17:32:58 +00:00
|
|
|
_ => {
|
2023-10-10 17:29:11 +00:00
|
|
|
return Err(Error::UnexpectedSyntaxNode {
|
2023-12-30 07:04:39 +00:00
|
|
|
expected: "==, !=, &&, ||, >, <, >= or <=".to_string(),
|
|
|
|
actual: operator_node.kind().to_string(),
|
2023-10-06 17:32:58 +00:00
|
|
|
location: operator_node.start_position(),
|
|
|
|
relevant_source: source[operator_node.byte_range()].to_string(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
};
|
2023-11-30 03:54:46 +00:00
|
|
|
let right = Expression::from_syntax_node(source, right_node, context)?;
|
2023-10-06 17:32:58 +00:00
|
|
|
|
|
|
|
Ok(Logic {
|
|
|
|
left,
|
|
|
|
operator,
|
|
|
|
right,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-11-30 00:23:42 +00:00
|
|
|
fn run(&self, source: &str, context: &Map) -> Result<Value> {
|
2023-10-10 17:29:11 +00:00
|
|
|
let left = self.left.run(source, context)?;
|
|
|
|
let right = self.right.run(source, context)?;
|
2023-10-09 19:54:47 +00:00
|
|
|
let result = match self.operator {
|
|
|
|
LogicOperator::Equal => {
|
|
|
|
if let (Ok(left_num), Ok(right_num)) = (left.as_number(), right.as_number()) {
|
|
|
|
left_num == right_num
|
|
|
|
} else {
|
|
|
|
left == right
|
|
|
|
}
|
|
|
|
}
|
2023-10-28 14:28:43 +00:00
|
|
|
LogicOperator::NotEqual => {
|
|
|
|
if let (Ok(left_num), Ok(right_num)) = (left.as_number(), right.as_number()) {
|
|
|
|
left_num != right_num
|
|
|
|
} else {
|
|
|
|
left != right
|
|
|
|
}
|
|
|
|
}
|
2023-10-09 19:54:47 +00:00
|
|
|
LogicOperator::And => left.as_boolean()? && right.as_boolean()?,
|
|
|
|
LogicOperator::Or => left.as_boolean()? || right.as_boolean()?,
|
|
|
|
LogicOperator::Greater => left > right,
|
|
|
|
LogicOperator::Less => left < right,
|
|
|
|
LogicOperator::GreaterOrEqual => left >= right,
|
|
|
|
LogicOperator::LessOrEqaul => left <= right,
|
2023-10-06 17:32:58 +00:00
|
|
|
};
|
|
|
|
|
2023-10-09 19:54:47 +00:00
|
|
|
Ok(Value::Boolean(result))
|
2023-10-06 17:32:58 +00:00
|
|
|
}
|
2023-11-30 00:23:42 +00:00
|
|
|
|
2023-12-05 22:08:22 +00:00
|
|
|
fn expected_type(&self, _context: &Map) -> Result<Type> {
|
|
|
|
Ok(Type::Boolean)
|
2023-11-30 00:23:42 +00:00
|
|
|
}
|
2023-10-06 17:32:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
|
|
|
pub enum LogicOperator {
|
|
|
|
Equal,
|
2023-10-28 14:28:43 +00:00
|
|
|
NotEqual,
|
2023-10-06 17:32:58 +00:00
|
|
|
And,
|
|
|
|
Or,
|
2023-10-09 19:54:47 +00:00
|
|
|
Greater,
|
|
|
|
Less,
|
|
|
|
GreaterOrEqual,
|
|
|
|
LessOrEqaul,
|
2023-10-06 17:32:58 +00:00
|
|
|
}
|