1
0

Refactor the abstract syntax tree

This commit is contained in:
Jeff 2024-08-09 04:23:02 -04:00
parent b9081f8653
commit 8c8fde94ce
6 changed files with 380 additions and 430 deletions

View File

@ -35,12 +35,17 @@ impl<T: Display> Display for Node<T> {
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum Statement { pub enum Statement {
// Top-level statements // Top-level statements
Assign(Box<Node<Statement>>, Box<Node<Statement>>), Assignment {
identifier: Identifier,
value_node: Box<Node<Statement>>,
},
// Math expressions // Logic, math and comparison expressions
Add(Box<Node<Statement>>, Box<Node<Statement>>), BinaryOperation {
Subtract(Box<Node<Statement>>, Box<Node<Statement>>), left: Box<Node<Statement>>,
Multiply(Box<Node<Statement>>, Box<Node<Statement>>), operator: Node<BinaryOperator>,
right: Box<Node<Statement>>,
},
// Function calls // Function calls
BuiltInFunctionCall { BuiltInFunctionCall {
@ -54,31 +59,25 @@ pub enum Statement {
value_arguments: Option<Vec<Node<Statement>>>, value_arguments: Option<Vec<Node<Statement>>>,
}, },
// Comparison expressions // Property access expression
Comparison(
Box<Node<Statement>>,
Node<ComparisonOperator>,
Box<Node<Statement>>,
),
// Property access
PropertyAccess(Box<Node<Statement>>, Box<Node<Statement>>), PropertyAccess(Box<Node<Statement>>, Box<Node<Statement>>),
// Value collections // Identifier expression
Identifier(Identifier),
// Value collection expressions
List(Vec<Node<Statement>>), List(Vec<Node<Statement>>),
// Hard-coded values // Hard-coded values
Constant(Value), Constant(Value),
Identifier(Identifier),
} }
impl Statement { impl Statement {
pub fn expected_type(&self, variables: &HashMap<Identifier, Value>) -> Option<Type> { pub fn expected_type(&self, variables: &HashMap<Identifier, Value>) -> Option<Type> {
match self { match self {
Statement::Add(left, _) => left.inner.expected_type(variables), Statement::Assignment { .. } => None,
Statement::Assign(_, _) => None, Statement::BinaryOperation { left, .. } => left.inner.expected_type(variables),
Statement::BuiltInFunctionCall { function, .. } => function.expected_type(), Statement::BuiltInFunctionCall { function, .. } => function.expected_return_type(),
Statement::Comparison(_, _, _) => Some(Type::Boolean),
Statement::Constant(value) => Some(value.r#type(variables)), Statement::Constant(value) => Some(value.r#type(variables)),
Statement::FunctionCall { function, .. } => function.inner.expected_type(variables), Statement::FunctionCall { function, .. } => function.inner.expected_type(variables),
Statement::Identifier(identifier) => variables Statement::Identifier(identifier) => variables
@ -88,9 +87,7 @@ impl Statement {
.first() .first()
.map(|node| node.inner.expected_type(variables)) .map(|node| node.inner.expected_type(variables))
.flatten(), .flatten(),
Statement::Multiply(left, _) => left.inner.expected_type(variables),
Statement::PropertyAccess(_, _) => None, Statement::PropertyAccess(_, _) => None,
Statement::Subtract(left, _) => left.inner.expected_type(variables),
} }
} }
} }
@ -98,8 +95,19 @@ impl Statement {
impl Display for Statement { impl Display for Statement {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
Statement::Assign(left, right) => write!(f, "{left} = {right}"), Statement::Assignment {
Statement::Add(left, right) => write!(f, "{left} + {right}"), identifier,
value_node: value,
} => {
write!(f, "{identifier} = {value}")
}
Statement::BinaryOperation {
left,
operator,
right,
} => {
write!(f, "{left} {operator} {right}")
}
Statement::BuiltInFunctionCall { Statement::BuiltInFunctionCall {
function, function,
type_arguments: type_parameters, type_arguments: type_parameters,
@ -135,7 +143,6 @@ impl Display for Statement {
write!(f, ")") write!(f, ")")
} }
Statement::Comparison(left, operator, right) => write!(f, "{left} {operator} {right}"),
Statement::Constant(value) => write!(f, "{value}"), Statement::Constant(value) => write!(f, "{value}"),
Statement::FunctionCall { Statement::FunctionCall {
function, function,
@ -183,28 +190,34 @@ impl Display for Statement {
} }
write!(f, "]") write!(f, "]")
} }
Statement::Multiply(left, right) => write!(f, "{left} * {right}"),
Statement::PropertyAccess(left, right) => write!(f, "{left}.{right}"), Statement::PropertyAccess(left, right) => write!(f, "{left}.{right}"),
Statement::Subtract(left, right) => write!(f, "{left} - {right}"),
} }
} }
} }
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum ComparisonOperator { pub enum BinaryOperator {
GreaterThan, Add,
GreaterThanOrEqual, Divide,
LessThan, Greater,
LessThanOrEqual, GreaterOrEqual,
Less,
LessOrEqual,
Multiply,
Subtract,
} }
impl Display for ComparisonOperator { impl Display for BinaryOperator {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self { match self {
ComparisonOperator::GreaterThan => write!(f, ">"), BinaryOperator::Add => write!(f, "+"),
ComparisonOperator::GreaterThanOrEqual => write!(f, ">="), BinaryOperator::Divide => write!(f, "/"),
ComparisonOperator::LessThan => write!(f, "<"), BinaryOperator::Greater => write!(f, ">"),
ComparisonOperator::LessThanOrEqual => write!(f, "<="), BinaryOperator::GreaterOrEqual => write!(f, ">="),
BinaryOperator::Less => write!(f, "<"),
BinaryOperator::LessOrEqual => write!(f, "<="),
BinaryOperator::Multiply => write!(f, "*"),
BinaryOperator::Subtract => write!(f, "-"),
} }
} }
} }

View File

@ -11,7 +11,10 @@ use std::{
fmt::{self, Display, Formatter}, fmt::{self, Display, Formatter},
}; };
use crate::{AbstractSyntaxTree, BuiltInFunction, Identifier, Node, Span, Statement, Type, Value}; use crate::{
abstract_tree::BinaryOperator, AbstractSyntaxTree, BuiltInFunction, Identifier, Node, Span,
Statement, Type, Value,
};
/// Analyzes the abstract syntax tree for errors. /// Analyzes the abstract syntax tree for errors.
/// ///
@ -74,68 +77,26 @@ impl<'a> Analyzer<'a> {
fn analyze_node(&self, node: &Node<Statement>) -> Result<(), AnalyzerError> { fn analyze_node(&self, node: &Node<Statement>) -> Result<(), AnalyzerError> {
match &node.inner { match &node.inner {
Statement::Add(left, right) => { Statement::Assignment {
self.analyze_node(left)?; identifier,
self.analyze_node(right)?; value_node: value,
} => {
let left_type = left.inner.expected_type(self.variables); if let None = value.inner.expected_type(self.variables) {
let right_type = right.inner.expected_type(self.variables); return Err(AnalyzerError::ExpectedValue {
actual: value.as_ref().clone(),
match (left_type, right_type) { position: value.position,
(Some(Type::Integer), Some(Type::Integer)) => {}
(Some(Type::Float), Some(Type::Float)) => {}
(Some(Type::String), Some(Type::String)) => {}
(Some(Type::Integer), _) | (Some(Type::Float), _) | (Some(Type::String), _) => {
return Err(AnalyzerError::ExpectedIntegerFloatOrString {
actual: right.as_ref().clone(),
position: right.position,
});
}
_ => {
return Err(AnalyzerError::ExpectedIntegerFloatOrString {
actual: left.as_ref().clone(),
position: left.position,
});
}
}
}
Statement::Assign(left, right) => {
if let Statement::Identifier(_) = &left.inner {
// Identifier is in the correct position
} else {
return Err(AnalyzerError::ExpectedIdentifier {
actual: left.as_ref().clone(),
position: left.position,
}); });
} }
}
Statement::BinaryOperation {
left,
operator,
right,
} => {
self.analyze_node(left)?;
self.analyze_node(right)?; self.analyze_node(right)?;
} }
Statement::BuiltInFunctionCall { .. } => {} Statement::BuiltInFunctionCall { .. } => {}
Statement::Comparison(left, _, right) => {
self.analyze_node(left)?;
self.analyze_node(right)?;
if let Some(Type::Integer) | Some(Type::Float) =
left.inner.expected_type(self.variables)
{
} else {
return Err(AnalyzerError::ExpectedIntegerOrFloat {
actual: left.as_ref().clone(),
position: left.position,
});
}
if let Some(Type::Integer) | Some(Type::Float) =
right.inner.expected_type(self.variables)
{
} else {
return Err(AnalyzerError::ExpectedIntegerOrFloat {
actual: right.as_ref().clone(),
position: right.position,
});
}
}
Statement::Constant(_) => {} Statement::Constant(_) => {}
Statement::FunctionCall { function, .. } => { Statement::FunctionCall { function, .. } => {
if let Statement::Identifier(_) = &function.inner { if let Statement::Identifier(_) = &function.inner {
@ -158,37 +119,13 @@ impl<'a> Analyzer<'a> {
self.analyze_node(statement)?; self.analyze_node(statement)?;
} }
} }
Statement::Multiply(left, right) => {
self.analyze_node(left)?;
self.analyze_node(right)?;
if let Some(Type::Integer) | Some(Type::Float) =
left.inner.expected_type(self.variables)
{
} else {
return Err(AnalyzerError::ExpectedIntegerOrFloat {
actual: left.as_ref().clone(),
position: left.position,
});
}
if let Some(Type::Integer) | Some(Type::Float) =
right.inner.expected_type(self.variables)
{
} else {
return Err(AnalyzerError::ExpectedIntegerOrFloat {
actual: right.as_ref().clone(),
position: right.position,
});
}
}
Statement::PropertyAccess(left, right) => { Statement::PropertyAccess(left, right) => {
if let Statement::Identifier(_) | Statement::Constant(_) | Statement::List(_) = if let Statement::Identifier(_) | Statement::Constant(_) | Statement::List(_) =
&left.inner &left.inner
{ {
// Left side is valid // Left side is valid
} else { } else {
return Err(AnalyzerError::ExpectedIdentifierOrValue { return Err(AnalyzerError::ExpectedValue {
actual: left.as_ref().clone(), actual: left.as_ref().clone(),
position: left.position, position: left.position,
}); });
@ -208,30 +145,6 @@ impl<'a> Analyzer<'a> {
self.analyze_node(right)?; self.analyze_node(right)?;
} }
Statement::Subtract(left, right) => {
self.analyze_node(left)?;
self.analyze_node(right)?;
let left_type = left.inner.expected_type(self.variables);
let right_type = right.inner.expected_type(self.variables);
match (left_type, right_type) {
(Some(Type::Integer), Some(Type::Integer)) => {}
(Some(Type::Float), Some(Type::Float)) => {}
(Some(Type::Integer), _) | (Some(Type::Float), _) => {
return Err(AnalyzerError::ExpectedIntegerOrFloat {
actual: right.as_ref().clone(),
position: right.position,
});
}
_ => {
return Err(AnalyzerError::ExpectedIntegerOrFloat {
actual: left.as_ref().clone(),
position: left.position,
});
}
}
}
} }
Ok(()) Ok(())
@ -244,6 +157,10 @@ pub enum AnalyzerError {
actual: Node<Statement>, actual: Node<Statement>,
position: Span, position: Span,
}, },
ExpectedFloat {
actual: Node<Statement>,
position: (usize, usize),
},
ExpectedFunction { ExpectedFunction {
actual: Node<Statement>, actual: Node<Statement>,
position: Span, position: Span,
@ -252,7 +169,7 @@ pub enum AnalyzerError {
actual: Node<Statement>, actual: Node<Statement>,
position: Span, position: Span,
}, },
ExpectedIdentifierOrValue { ExpectedInteger {
actual: Node<Statement>, actual: Node<Statement>,
position: Span, position: Span,
}, },
@ -264,22 +181,38 @@ pub enum AnalyzerError {
actual: Node<Statement>, actual: Node<Statement>,
position: Span, position: Span,
}, },
ExpectedString {
actual: Node<Statement>,
position: (usize, usize),
},
ExpectedValue {
actual: Node<Statement>,
position: Span,
},
UnexpectedIdentifier { UnexpectedIdentifier {
identifier: Node<Statement>, identifier: Node<Statement>,
position: Span, position: Span,
}, },
UnexectedString {
actual: Node<Statement>,
position: (usize, usize),
},
} }
impl AnalyzerError { impl AnalyzerError {
pub fn position(&self) -> Span { pub fn position(&self) -> Span {
match self { match self {
AnalyzerError::ExpectedBoolean { position, .. } => *position, AnalyzerError::ExpectedBoolean { position, .. } => *position,
AnalyzerError::ExpectedFloat { position, .. } => *position,
AnalyzerError::ExpectedFunction { position, .. } => *position, AnalyzerError::ExpectedFunction { position, .. } => *position,
AnalyzerError::ExpectedIdentifier { position, .. } => *position, AnalyzerError::ExpectedIdentifier { position, .. } => *position,
AnalyzerError::ExpectedIdentifierOrValue { position, .. } => *position, AnalyzerError::ExpectedValue { position, .. } => *position,
AnalyzerError::ExpectedInteger { position, .. } => *position,
AnalyzerError::ExpectedIntegerOrFloat { position, .. } => *position, AnalyzerError::ExpectedIntegerOrFloat { position, .. } => *position,
AnalyzerError::ExpectedIntegerFloatOrString { position, .. } => *position, AnalyzerError::ExpectedIntegerFloatOrString { position, .. } => *position,
AnalyzerError::ExpectedString { position, .. } => *position,
AnalyzerError::UnexpectedIdentifier { position, .. } => *position, AnalyzerError::UnexpectedIdentifier { position, .. } => *position,
AnalyzerError::UnexectedString { position, .. } => *position,
} }
} }
} }
@ -295,11 +228,14 @@ impl Display for AnalyzerError {
AnalyzerError::ExpectedFunction { actual, .. } => { AnalyzerError::ExpectedFunction { actual, .. } => {
write!(f, "Expected function, found {}", actual) write!(f, "Expected function, found {}", actual)
} }
AnalyzerError::ExpectedFloat { actual, .. } => {
write!(f, "Expected float, found {}", actual)
}
AnalyzerError::ExpectedIdentifier { actual, .. } => { AnalyzerError::ExpectedIdentifier { actual, .. } => {
write!(f, "Expected identifier, found {}", actual) write!(f, "Expected identifier, found {}", actual)
} }
AnalyzerError::ExpectedIdentifierOrValue { actual, .. } => { AnalyzerError::ExpectedInteger { actual, .. } => {
write!(f, "Expected identifier or value, found {}", actual) write!(f, "Expected integer, found {}", actual)
} }
AnalyzerError::ExpectedIntegerOrFloat { actual, .. } => { AnalyzerError::ExpectedIntegerOrFloat { actual, .. } => {
write!(f, "Expected integer or float, found {}", actual) write!(f, "Expected integer or float, found {}", actual)
@ -307,9 +243,18 @@ impl Display for AnalyzerError {
AnalyzerError::ExpectedIntegerFloatOrString { actual, .. } => { AnalyzerError::ExpectedIntegerFloatOrString { actual, .. } => {
write!(f, "Expected integer, float, or string, found {}", actual) write!(f, "Expected integer, float, or string, found {}", actual)
} }
AnalyzerError::ExpectedString { actual, .. } => {
write!(f, "Expected string, found {}", actual)
}
AnalyzerError::ExpectedValue { actual, .. } => {
write!(f, "Expected value, found {}", actual)
}
AnalyzerError::UnexpectedIdentifier { identifier, .. } => { AnalyzerError::UnexpectedIdentifier { identifier, .. } => {
write!(f, "Unexpected identifier {}", identifier) write!(f, "Unexpected identifier {}", identifier)
} }
AnalyzerError::UnexectedString { actual, .. } => {
write!(f, "Unexpected string {}", actual)
}
} }
} }
} }
@ -324,11 +269,12 @@ mod tests {
fn add_expects_same_types() { fn add_expects_same_types() {
let abstract_tree = AbstractSyntaxTree { let abstract_tree = AbstractSyntaxTree {
nodes: [Node::new( nodes: [Node::new(
Statement::Add( Statement::BinaryOperation {
Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), left: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))),
Box::new(Node::new(Statement::Constant(Value::float(1.0)), (1, 2))), operator: Node::new(BinaryOperator::Add, (1, 2)),
), right: Box::new(Node::new(Statement::Constant(Value::float(1.0)), (3, 4))),
(0, 2), },
(0, 4),
)] )]
.into(), .into(),
}; };
@ -348,10 +294,11 @@ mod tests {
fn add_expects_integer_float_or_string() { fn add_expects_integer_float_or_string() {
let abstract_tree = AbstractSyntaxTree { let abstract_tree = AbstractSyntaxTree {
nodes: [Node::new( nodes: [Node::new(
Statement::Add( Statement::BinaryOperation {
Box::new(Node::new(Statement::Constant(Value::boolean(true)), (0, 1))), left: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))),
Box::new(Node::new(Statement::Constant(Value::integer(1)), (1, 2))), operator: Node::new(BinaryOperator::Add, (1, 2)),
), right: Box::new(Node::new(Statement::Constant(Value::boolean(true)), (3, 4))),
},
(0, 2), (0, 2),
)] )]
.into(), .into(),
@ -433,13 +380,14 @@ mod tests {
fn multiply_expect_integer_or_float() { fn multiply_expect_integer_or_float() {
let abstract_tree = AbstractSyntaxTree { let abstract_tree = AbstractSyntaxTree {
nodes: [Node::new( nodes: [Node::new(
Statement::Multiply( Statement::BinaryOperation {
Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), left: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))),
Box::new(Node::new( operator: Node::new(BinaryOperator::Multiply, (1, 2)),
right: Box::new(Node::new(
Statement::Constant(Value::boolean(false)), Statement::Constant(Value::boolean(false)),
(1, 2), (3, 4),
)), )),
), },
(0, 2), (0, 2),
)] )]
.into(), .into(),
@ -460,10 +408,10 @@ mod tests {
fn assignment_expect_identifier() { fn assignment_expect_identifier() {
let abstract_tree = AbstractSyntaxTree { let abstract_tree = AbstractSyntaxTree {
nodes: [Node::new( nodes: [Node::new(
Statement::Assign( Statement::Assignment {
Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), identifier: Identifier::new("x"),
Box::new(Node::new(Statement::Constant(Value::integer(2)), (1, 2))), value_node: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))),
), },
(0, 2), (0, 2),
)] )]
.into(), .into(),

View File

@ -113,7 +113,7 @@ impl BuiltInFunction {
} }
} }
pub fn expected_type(&self) -> Option<Type> { pub fn expected_return_type(&self) -> Option<Type> {
match self { match self {
BuiltInFunction::IsEven => Some(Type::Boolean), BuiltInFunction::IsEven => Some(Type::Boolean),
BuiltInFunction::IsOdd => Some(Type::Boolean), BuiltInFunction::IsOdd => Some(Type::Boolean),

View File

@ -20,15 +20,17 @@ pub struct Identifier(Arc<String>);
impl Identifier { impl Identifier {
pub fn new<T: ToString>(text: T) -> Self { pub fn new<T: ToString>(text: T) -> Self {
let cache = identifier_cache(); let cache = identifier_cache().read().unwrap();
let new = Identifier(Arc::new(text.to_string())); let new = Identifier(Arc::new(text.to_string()));
if let Some(identifier) = cache.read().unwrap().get(&new).cloned() { if cache.contains(&new) {
return identifier; return new;
} }
cache.write().unwrap().insert(new.clone()); drop(cache);
identifier_cache().write().unwrap().insert(new.clone());
new new
} }

View File

@ -10,7 +10,7 @@ use std::{
}; };
use crate::{ use crate::{
abstract_tree::ComparisonOperator, built_in_function::BuiltInFunction, token::TokenOwned, abstract_tree::BinaryOperator, built_in_function::BuiltInFunction, token::TokenOwned,
AbstractSyntaxTree, Identifier, LexError, Lexer, Node, Span, Statement, Token, Value, AbstractSyntaxTree, Identifier, LexError, Lexer, Node, Span, Statement, Token, Value,
}; };
@ -169,16 +169,27 @@ impl<'src> Parser<'src> {
(Token::Equal, _) => { (Token::Equal, _) => {
self.next_token()?; self.next_token()?;
let identifier = if let Statement::Identifier(identifier) = left_node.inner {
identifier
} else {
return Err(ParseError::ExpectedIdentifier {
actual: left_node.inner,
position: left_node.position,
});
};
let right_node = self.parse_node(self.current_precedence())?; let right_node = self.parse_node(self.current_precedence())?;
let right_end = right_node.position.1; let right_end = right_node.position.1;
return Ok(Node::new( return Ok(Node::new(
Statement::Assign(Box::new(left_node), Box::new(right_node)), Statement::Assignment {
identifier,
value_node: Box::new(right_node),
},
(left_start, right_end), (left_start, right_end),
)); ));
} }
(Token::Greater, _) => { (Token::Greater, _) => {
let operator_position = self.current.1; let operator = Node::new(BinaryOperator::Greater, self.current.1);
self.next_token()?; self.next_token()?;
@ -186,16 +197,16 @@ impl<'src> Parser<'src> {
let right_end = right_node.position.1; let right_end = right_node.position.1;
return Ok(Node::new( return Ok(Node::new(
Statement::Comparison( Statement::BinaryOperation {
Box::new(left_node), left: Box::new(left_node),
Node::new(ComparisonOperator::GreaterThan, operator_position), operator,
Box::new(right_node), right: Box::new(right_node),
), },
(left_start, right_end), (left_start, right_end),
)); ));
} }
(Token::GreaterEqual, _) => { (Token::GreaterEqual, _) => {
let operator_position = self.current.1; let operator = Node::new(BinaryOperator::GreaterOrEqual, self.current.1);
self.next_token()?; self.next_token()?;
@ -203,16 +214,16 @@ impl<'src> Parser<'src> {
let right_end = right_node.position.1; let right_end = right_node.position.1;
return Ok(Node::new( return Ok(Node::new(
Statement::Comparison( Statement::BinaryOperation {
Box::new(left_node), left: Box::new(left_node),
Node::new(ComparisonOperator::GreaterThanOrEqual, operator_position), operator,
Box::new(right_node), right: Box::new(right_node),
), },
(left_start, right_end), (left_start, right_end),
)); ));
} }
(Token::Less, _) => { (Token::Less, _) => {
let operator_position = self.current.1; let operator = Node::new(BinaryOperator::Less, self.current.1);
self.next_token()?; self.next_token()?;
@ -220,16 +231,16 @@ impl<'src> Parser<'src> {
let right_end = right_node.position.1; let right_end = right_node.position.1;
return Ok(Node::new( return Ok(Node::new(
Statement::Comparison( Statement::BinaryOperation {
Box::new(left_node), left: Box::new(left_node),
Node::new(ComparisonOperator::LessThan, operator_position), operator,
Box::new(right_node), right: Box::new(right_node),
), },
(left_start, right_end), (left_start, right_end),
)); ));
} }
(Token::LessEqual, _) => { (Token::LessEqual, _) => {
let operator_position = self.current.1; let operator = Node::new(BinaryOperator::LessOrEqual, self.current.1);
self.next_token()?; self.next_token()?;
@ -237,44 +248,62 @@ impl<'src> Parser<'src> {
let right_end = right_node.position.1; let right_end = right_node.position.1;
return Ok(Node::new( return Ok(Node::new(
Statement::Comparison( Statement::BinaryOperation {
Box::new(left_node), left: Box::new(left_node),
Node::new(ComparisonOperator::LessThanOrEqual, operator_position), operator,
Box::new(right_node), right: Box::new(right_node),
), },
(left_start, right_end), (left_start, right_end),
)); ));
} }
(Token::Minus, _) => { (Token::Minus, _) => {
let operator = Node::new(BinaryOperator::Subtract, self.current.1);
self.next_token()?; self.next_token()?;
let right_node = self.parse_node(self.current_precedence())?; let right_node = self.parse_node(self.current_precedence())?;
let right_end = right_node.position.1; let right_end = right_node.position.1;
return Ok(Node::new( return Ok(Node::new(
Statement::Subtract(Box::new(left_node), Box::new(right_node)), Statement::BinaryOperation {
left: Box::new(left_node),
operator,
right: Box::new(right_node),
},
(left_start, right_end), (left_start, right_end),
)); ));
} }
(Token::Plus, _) => { (Token::Plus, _) => {
let operator = Node::new(BinaryOperator::Add, self.current.1);
self.next_token()?; self.next_token()?;
let right_node = self.parse_node(self.current_precedence())?; let right_node = self.parse_node(self.current_precedence())?;
let right_end = right_node.position.1; let right_end = right_node.position.1;
return Ok(Node::new( return Ok(Node::new(
Statement::Add(Box::new(left_node), Box::new(right_node)), Statement::BinaryOperation {
left: Box::new(left_node),
operator,
right: Box::new(right_node),
},
(left_start, right_end), (left_start, right_end),
)); ));
} }
(Token::Star, _) => { (Token::Star, _) => {
let operator = Node::new(BinaryOperator::Multiply, self.current.1);
self.next_token()?; self.next_token()?;
let right_node = self.parse_node(self.current_precedence())?; let right_node = self.parse_node(self.current_precedence())?;
let right_end = right_node.position.1; let right_end = right_node.position.1;
return Ok(Node::new( return Ok(Node::new(
Statement::Multiply(Box::new(left_node), Box::new(right_node)), Statement::BinaryOperation {
left: Box::new(left_node),
operator,
right: Box::new(right_node),
},
(left_start, right_end), (left_start, right_end),
)); ));
} }
@ -447,12 +476,31 @@ impl<'src> Parser<'src> {
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum ParseError { pub enum ParseError {
LexError { error: LexError, position: Span }, LexError {
error: LexError,
position: Span,
},
ExpectedClosingParenthesis { actual: TokenOwned, position: Span }, ExpectedClosingParenthesis {
ExpectedClosingSquareBrace { actual: TokenOwned, position: Span }, actual: TokenOwned,
ExpectedOpeningParenthesis { actual: TokenOwned, position: Span }, position: Span,
UnexpectedToken { actual: TokenOwned, position: Span }, },
ExpectedClosingSquareBrace {
actual: TokenOwned,
position: Span,
},
ExpectedIdentifier {
actual: Statement,
position: (usize, usize),
},
ExpectedOpeningParenthesis {
actual: TokenOwned,
position: Span,
},
UnexpectedToken {
actual: TokenOwned,
position: Span,
},
} }
impl ParseError { impl ParseError {
@ -461,6 +509,7 @@ impl ParseError {
Self::LexError { position, .. } => *position, Self::LexError { position, .. } => *position,
Self::ExpectedClosingParenthesis { position, .. } => *position, Self::ExpectedClosingParenthesis { position, .. } => *position,
Self::ExpectedClosingSquareBrace { position, .. } => *position, Self::ExpectedClosingSquareBrace { position, .. } => *position,
Self::ExpectedIdentifier { position, .. } => *position,
Self::ExpectedOpeningParenthesis { position, .. } => *position, Self::ExpectedOpeningParenthesis { position, .. } => *position,
Self::UnexpectedToken { position, .. } => *position, Self::UnexpectedToken { position, .. } => *position,
} }
@ -486,6 +535,9 @@ impl Display for ParseError {
Self::ExpectedClosingSquareBrace { actual, .. } => { Self::ExpectedClosingSquareBrace { actual, .. } => {
write!(f, "Expected closing square brace, found {actual}",) write!(f, "Expected closing square brace, found {actual}",)
} }
Self::ExpectedIdentifier { actual, .. } => {
write!(f, "Expected identifier, found {actual}")
}
Self::ExpectedOpeningParenthesis { actual, .. } => { Self::ExpectedOpeningParenthesis { actual, .. } => {
write!(f, "Expected opening parenthesis, found {actual}",) write!(f, "Expected opening parenthesis, found {actual}",)
} }
@ -496,7 +548,7 @@ impl Display for ParseError {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{abstract_tree::ComparisonOperator, Identifier}; use crate::{abstract_tree::BinaryOperator, Identifier};
use super::*; use super::*;
@ -508,11 +560,11 @@ mod tests {
parse(input), parse(input),
Ok(AbstractSyntaxTree { Ok(AbstractSyntaxTree {
nodes: [Node::new( nodes: [Node::new(
Statement::Comparison( Statement::BinaryOperation {
Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), left: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))),
Node::new(ComparisonOperator::LessThan, (2, 3)), operator: Node::new(BinaryOperator::Less, (2, 3)),
Box::new(Node::new(Statement::Constant(Value::integer(2)), (4, 5))) right: Box::new(Node::new(Statement::Constant(Value::integer(2)), (4, 5))),
), },
(0, 5) (0, 5)
)] )]
.into() .into()
@ -528,11 +580,11 @@ mod tests {
parse(input), parse(input),
Ok(AbstractSyntaxTree { Ok(AbstractSyntaxTree {
nodes: [Node::new( nodes: [Node::new(
Statement::Comparison( Statement::BinaryOperation {
Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), left: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))),
Node::new(ComparisonOperator::LessThanOrEqual, (2, 4)), operator: Node::new(BinaryOperator::Less, (2, 4)),
Box::new(Node::new(Statement::Constant(Value::integer(2)), (5, 6))) right: Box::new(Node::new(Statement::Constant(Value::integer(2)), (5, 6))),
), },
(0, 6) (0, 6)
)] )]
.into() .into()
@ -548,11 +600,11 @@ mod tests {
parse(input), parse(input),
Ok(AbstractSyntaxTree { Ok(AbstractSyntaxTree {
nodes: [Node::new( nodes: [Node::new(
Statement::Comparison( Statement::BinaryOperation {
Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), left: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))),
Node::new(ComparisonOperator::GreaterThanOrEqual, (2, 4)), operator: Node::new(BinaryOperator::Greater, (2, 4)),
Box::new(Node::new(Statement::Constant(Value::integer(2)), (5, 6))) right: Box::new(Node::new(Statement::Constant(Value::integer(2)), (5, 6))),
), },
(0, 6) (0, 6)
)] )]
.into() .into()
@ -568,11 +620,11 @@ mod tests {
parse(input), parse(input),
Ok(AbstractSyntaxTree { Ok(AbstractSyntaxTree {
nodes: [Node::new( nodes: [Node::new(
Statement::Comparison( Statement::BinaryOperation {
Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), left: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))),
Node::new(ComparisonOperator::GreaterThan, (2, 3)), operator: Node::new(BinaryOperator::Greater, (2, 3)),
Box::new(Node::new(Statement::Constant(Value::integer(2)), (4, 5))) right: Box::new(Node::new(Statement::Constant(Value::integer(2)), (4, 5))),
), },
(0, 5) (0, 5)
)] )]
.into() .into()
@ -588,10 +640,11 @@ mod tests {
parse(input), parse(input),
Ok(AbstractSyntaxTree { Ok(AbstractSyntaxTree {
nodes: [Node::new( nodes: [Node::new(
Statement::Subtract( Statement::BinaryOperation {
Box::new(Node::new(Statement::Constant(Value::integer(-1)), (0, 2))), left: Node::new(Statement::Constant(Value::integer(1)), (1, 2)).into(),
Box::new(Node::new(Statement::Constant(Value::integer(-2)), (5, 7))) operator: Node::new(BinaryOperator::Subtract, (3, 4)),
), right: Node::new(Statement::Constant(Value::integer(2)), (6, 7)).into()
},
(0, 7) (0, 7)
)] )]
.into() .into()
@ -607,17 +660,18 @@ mod tests {
parse(input), parse(input),
Ok(AbstractSyntaxTree { Ok(AbstractSyntaxTree {
nodes: [Node::new( nodes: [Node::new(
Statement::Add( Statement::BinaryOperation {
Box::new(Node::new( left: Box::new(Node::new(
Statement::Constant(Value::string("Hello, ")), Statement::Constant(Value::string("Hello, ")),
(0, 9) (0, 8)
)), )),
Box::new(Node::new( operator: Node::new(BinaryOperator::Add, (9, 10)),
right: Box::new(Node::new(
Statement::Constant(Value::string("World!")), Statement::Constant(Value::string("World!")),
(12, 20) (11, 19)
)) ))
), },
(0, 20) (0, 19)
)] )]
.into() .into()
}) })
@ -740,33 +794,42 @@ mod tests {
Statement::List(vec![ Statement::List(vec![
Node::new(Statement::Constant(Value::integer(1)), (1, 2)), Node::new(Statement::Constant(Value::integer(1)), (1, 2)),
Node::new( Node::new(
Statement::Add( Statement::BinaryOperation {
Box::new(Node::new(Statement::Constant(Value::integer(1)), (4, 5))), left: Box::new(Node::new(
Box::new(Node::new(Statement::Constant(Value::integer(1)), (8, 9))), Statement::Constant(Value::integer(1)),
), (4, 5)
(4, 9), )),
operator: Node::new(BinaryOperator::Add, (6, 7)),
right: Box::new(Node::new(
Statement::Constant(Value::integer(1)),
(8, 9)
))
},
(4, 9)
), ),
Node::new( Node::new(
Statement::Add( Statement::BinaryOperation {
Box::new(Node::new( left: Box::new(Node::new(
Statement::Constant(Value::integer(2)), Statement::Constant(Value::integer(2)),
(11, 12) (11, 12)
)), )),
Box::new(Node::new( operator: Node::new(BinaryOperator::Add, (13, 14)),
Statement::Multiply( right: Box::new(Node::new(
Box::new(Node::new( Statement::BinaryOperation {
left: Box::new(Node::new(
Statement::Constant(Value::integer(4)), Statement::Constant(Value::integer(4)),
(16, 17) (16, 17)
)), )),
Box::new(Node::new( operator: Node::new(BinaryOperator::Multiply, (18, 19)),
right: Box::new(Node::new(
Statement::Constant(Value::integer(10)), Statement::Constant(Value::integer(10)),
(20, 22) (20, 22)
)), ))
), },
(15, 23), (15, 23)
),), ))
), },
(11, 23), (11, 23)
), ),
]), ]),
(0, 24), (0, 24),
@ -827,10 +890,11 @@ mod tests {
parse(input), parse(input),
Ok(AbstractSyntaxTree { Ok(AbstractSyntaxTree {
nodes: [Node::new( nodes: [Node::new(
Statement::Add( Statement::BinaryOperation {
Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), left: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))),
Box::new(Node::new(Statement::Constant(Value::integer(2)), (4, 5))), operator: Node::new(BinaryOperator::Add, (2, 3)),
), right: Box::new(Node::new(Statement::Constant(Value::integer(2)), (4, 5)),)
},
(0, 5), (0, 5),
)] )]
.into() .into()
@ -846,10 +910,11 @@ mod tests {
parse(input), parse(input),
Ok(AbstractSyntaxTree { Ok(AbstractSyntaxTree {
nodes: [Node::new( nodes: [Node::new(
Statement::Multiply( Statement::BinaryOperation {
Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), left: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))),
Box::new(Node::new(Statement::Constant(Value::integer(2)), (4, 5))), operator: Node::new(BinaryOperator::Multiply, (2, 3)),
), right: Box::new(Node::new(Statement::Constant(Value::integer(2)), (4, 5)),)
},
(0, 5), (0, 5),
)] )]
.into() .into()
@ -865,16 +930,24 @@ mod tests {
parse(input), parse(input),
Ok(AbstractSyntaxTree { Ok(AbstractSyntaxTree {
nodes: [Node::new( nodes: [Node::new(
Statement::Add( Statement::BinaryOperation {
Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), left: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))),
Box::new(Node::new( operator: Node::new(BinaryOperator::Add, (2, 3)),
Statement::Multiply( right: Box::new(Node::new(
Box::new(Node::new(Statement::Constant(Value::integer(2)), (4, 5))), Statement::BinaryOperation {
Box::new(Node::new(Statement::Constant(Value::integer(3)), (8, 9))), left: Box::new(Node::new(
), Statement::Constant(Value::integer(2)),
(4, 9), (4, 5)
)), )),
), operator: Node::new(BinaryOperator::Multiply, (6, 7)),
right: Box::new(Node::new(
Statement::Constant(Value::integer(3)),
(8, 9)
),)
},
(4, 9)
),)
},
(0, 9), (0, 9),
)] )]
.into() .into()
@ -890,31 +963,33 @@ mod tests {
parse(input), parse(input),
Ok(AbstractSyntaxTree { Ok(AbstractSyntaxTree {
nodes: [Node::new( nodes: [Node::new(
Statement::Assign( Statement::Assignment {
Box::new(Node::new( identifier: Identifier::new("a"),
Statement::Identifier(Identifier::new("a")), value_node: Box::new(Node::new(
(0, 1) Statement::BinaryOperation {
)), left: Box::new(Node::new(
Box::new(Node::new( Statement::Constant(Value::integer(1)),
Statement::Add( (4, 5)
Box::new(Node::new(Statement::Constant(Value::integer(1)), (4, 5))), )),
Box::new(Node::new( operator: Node::new(BinaryOperator::Add, (6, 7)),
Statement::Multiply( right: Box::new(Node::new(
Box::new(Node::new( Statement::BinaryOperation {
left: Box::new(Node::new(
Statement::Constant(Value::integer(2)), Statement::Constant(Value::integer(2)),
(8, 9) (8, 9)
)), )),
Box::new(Node::new( operator: Node::new(BinaryOperator::Multiply, (10, 11)),
right: Box::new(Node::new(
Statement::Constant(Value::integer(3)), Statement::Constant(Value::integer(3)),
(12, 13) (12, 13)
)), ),)
), },
(8, 13), (8, 13)
)), ),)
), },
(4, 13), (4, 13)
)), ),)
), },
(0, 13), (0, 13),
)] )]
.into() .into()

View File

@ -6,7 +6,7 @@ use std::{
}; };
use crate::{ use crate::{
abstract_tree::ComparisonOperator, parse, AbstractSyntaxTree, Analyzer, AnalyzerError, abstract_tree::BinaryOperator, parse, AbstractSyntaxTree, Analyzer, AnalyzerError,
BuiltInFunctionError, Identifier, Node, ParseError, Span, Statement, Value, ValueError, BuiltInFunctionError, Identifier, Node, ParseError, Span, Statement, Value, ValueError,
}; };
@ -52,53 +52,65 @@ impl Vm {
variables: &mut HashMap<Identifier, Value>, variables: &mut HashMap<Identifier, Value>,
) -> Result<Option<Value>, VmError> { ) -> Result<Option<Value>, VmError> {
match node.inner { match node.inner {
Statement::Add(left, right) => { Statement::Assignment {
let left_span = left.position; identifier,
let left = if let Some(value) = self.run_node(*left, variables)? { value_node,
} => {
let value_node_position = value_node.position;
let value = if let Some(value) = self.run_node(*value_node, variables)? {
value value
} else { } else {
return Err(VmError::ExpectedValue { return Err(VmError::ExpectedValue {
position: left_span, position: value_node_position,
});
};
let right_span = right.position;
let right = if let Some(value) = self.run_node(*right, variables)? {
value
} else {
return Err(VmError::ExpectedValue {
position: right_span,
});
};
let sum = left
.add(&right)
.map_err(|value_error| VmError::ValueError {
error: value_error,
position: (left_span.0, right_span.1),
})?;
Ok(Some(sum))
}
Statement::Assign(left, right) => {
let identifier = if let Statement::Identifier(identifier) = &left.inner {
identifier
} else {
return Err(VmError::ExpectedIdentifier {
position: left.position,
});
};
let right_span = right.position;
let value = if let Some(value) = self.run_node(*right, variables)? {
value
} else {
return Err(VmError::ExpectedValue {
position: right_span,
}); });
}; };
variables.insert(identifier.clone(), value); variables.insert(identifier, value);
Ok(None) Ok(None)
} }
Statement::BinaryOperation {
left,
operator,
right,
} => {
let left_position = left.position;
let left_value = if let Some(value) = self.run_node(*left, variables)? {
value
} else {
return Err(VmError::ExpectedValue {
position: left_position,
});
};
let right_position = right.position;
let right_value = if let Some(value) = self.run_node(*right, variables)? {
value
} else {
return Err(VmError::ExpectedValue {
position: right_position,
});
};
let result = match operator.inner {
BinaryOperator::Add => left_value.add(&right_value),
BinaryOperator::Divide => todo!(),
BinaryOperator::Greater => left_value.greater_than(&right_value),
BinaryOperator::GreaterOrEqual => {
left_value.greater_than_or_equal(&right_value)
}
BinaryOperator::Less => left_value.less_than(&right_value),
BinaryOperator::LessOrEqual => left_value.less_than_or_equal(&right_value),
BinaryOperator::Multiply => left_value.multiply(&right_value),
BinaryOperator::Subtract => left_value.subtract(&right_value),
}
.map_err(|value_error| VmError::ValueError {
error: value_error,
position: node.position,
})?;
Ok(Some(result))
}
Statement::BuiltInFunctionCall { Statement::BuiltInFunctionCall {
function, function,
type_arguments: _, type_arguments: _,
@ -132,54 +144,6 @@ impl Vm {
Ok(function_call_return) Ok(function_call_return)
} }
Statement::Comparison(left, operator, right) => {
let left_span = left.position;
let left = if let Some(value) = self.run_node(*left, variables)? {
value
} else {
return Err(VmError::ExpectedValue {
position: left_span,
});
};
let right_span = right.position;
let right = if let Some(value) = self.run_node(*right, variables)? {
value
} else {
return Err(VmError::ExpectedValue {
position: right_span,
});
};
let comparison = match operator.inner {
ComparisonOperator::GreaterThan => {
left.greater_than(&right)
.map_err(|value_error| VmError::ValueError {
error: value_error,
position: (left_span.0, right_span.1),
})?
}
ComparisonOperator::GreaterThanOrEqual => left
.greater_than_or_equal(&right)
.map_err(|value_error| VmError::ValueError {
error: value_error,
position: (left_span.0, right_span.1),
})?,
ComparisonOperator::LessThan => {
left.less_than(&right)
.map_err(|value_error| VmError::ValueError {
error: value_error,
position: (left_span.0, right_span.1),
})?
}
ComparisonOperator::LessThanOrEqual => left
.less_than_or_equal(&right)
.map_err(|value_error| VmError::ValueError {
error: value_error,
position: (left_span.0, right_span.1),
})?,
};
Ok(Some(comparison))
}
Statement::Constant(value) => Ok(Some(value.clone())), Statement::Constant(value) => Ok(Some(value.clone())),
Statement::FunctionCall { Statement::FunctionCall {
function: function_node, function: function_node,
@ -250,32 +214,6 @@ impl Vm {
Ok(Some(Value::list(values))) Ok(Some(Value::list(values)))
} }
Statement::Multiply(left, right) => {
let left_span = left.position;
let left = if let Some(value) = self.run_node(*left, variables)? {
value
} else {
return Err(VmError::ExpectedValue {
position: left_span,
});
};
let right_span = right.position;
let right = if let Some(value) = self.run_node(*right, variables)? {
value
} else {
return Err(VmError::ExpectedValue {
position: right_span,
});
};
let product = left
.multiply(&right)
.map_err(|value_error| VmError::ValueError {
error: value_error,
position: (left_span.0, right_span.1),
})?;
Ok(Some(product))
}
Statement::PropertyAccess(left, right) => { Statement::PropertyAccess(left, right) => {
let left_span = left.position; let left_span = left.position;
let left_value = if let Some(value) = self.run_node(*left, variables)? { let left_value = if let Some(value) = self.run_node(*left, variables)? {
@ -337,32 +275,6 @@ impl Vm {
position: right_span, position: right_span,
}) })
} }
Statement::Subtract(left, right) => {
let left_span = left.position;
let left = if let Some(value) = self.run_node(*left, variables)? {
value
} else {
return Err(VmError::ExpectedValue {
position: left_span,
});
};
let right_span = right.position;
let right = if let Some(value) = self.run_node(*right, variables)? {
value
} else {
return Err(VmError::ExpectedValue {
position: right_span,
});
};
let difference =
left.subtract(&right)
.map_err(|value_error| VmError::ValueError {
error: value_error,
position: (left_span.0, right_span.1),
})?;
Ok(Some(difference))
}
} }
} }
} }