1
0
dust/src/abstract_tree/math.rs

104 lines
3.1 KiB
Rust
Raw Normal View History

2024-01-06 10:00:36 +00:00
use std::fmt::{self, Display, Formatter};
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 math operation.
///
/// Dust currently supports the four basic operations and the modulo (or
/// remainder) operator.
2023-10-06 17:32:58 +00:00
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Math {
left: Expression,
operator: MathOperator,
right: Expression,
}
impl AbstractTree for Math {
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, "math", node)?;
2023-10-06 17:32:58 +00:00
let left_node = node.child(0).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_node = node.child(1).unwrap().child(0).unwrap();
let operator = match operator_node.kind() {
"+" => MathOperator::Add,
"-" => MathOperator::Subtract,
"*" => MathOperator::Multiply,
"/" => MathOperator::Divide,
"%" => MathOperator::Modulo,
_ => {
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(),
})
}
};
let right_node = node.child(2).unwrap();
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(Math {
left,
operator,
right,
})
}
2023-11-30 00:23:42 +00:00
fn run(&self, source: &str, context: &Map) -> Result<Value> {
2023-10-13 23:56:57 +00:00
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,
}?;
2023-10-06 17:32:58 +00:00
2023-10-13 23:56:57 +00:00
Ok(value)
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> {
2023-11-30 03:02:55 +00:00
self.left.expected_type(context)
2023-11-30 00:23:42 +00:00
}
2023-10-06 17:32:58 +00:00
}
2024-01-06 10:00:36 +00:00
impl Display for Math {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let Math {
left,
operator,
right,
} = self;
write!(f, "{left} {operator} {right}")
}
}
2023-10-06 17:32:58 +00:00
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub enum MathOperator {
Add,
Subtract,
Multiply,
Divide,
Modulo,
}
2024-01-06 10:00:36 +00:00
impl Display for MathOperator {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
MathOperator::Add => write!(f, "+"),
MathOperator::Subtract => write!(f, "-"),
MathOperator::Multiply => write!(f, "*"),
MathOperator::Divide => write!(f, "\\"),
MathOperator::Modulo => write!(f, "%"),
}
}
}