From 8c8fde94ce36cd46a0bc4a5ae14450439fd501f9 Mon Sep 17 00:00:00 2001 From: Jeff Date: Fri, 9 Aug 2024 04:23:02 -0400 Subject: [PATCH] Refactor the abstract syntax tree --- dust-lang/src/abstract_tree.rs | 85 ++++---- dust-lang/src/analyzer.rs | 206 +++++++------------ dust-lang/src/built_in_function.rs | 2 +- dust-lang/src/identifier.rs | 10 +- dust-lang/src/parse.rs | 317 ++++++++++++++++++----------- dust-lang/src/vm.rs | 190 +++++------------ 6 files changed, 380 insertions(+), 430 deletions(-) diff --git a/dust-lang/src/abstract_tree.rs b/dust-lang/src/abstract_tree.rs index a910896..269d9ab 100644 --- a/dust-lang/src/abstract_tree.rs +++ b/dust-lang/src/abstract_tree.rs @@ -35,12 +35,17 @@ impl Display for Node { #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub enum Statement { // Top-level statements - Assign(Box>, Box>), + Assignment { + identifier: Identifier, + value_node: Box>, + }, - // Math expressions - Add(Box>, Box>), - Subtract(Box>, Box>), - Multiply(Box>, Box>), + // Logic, math and comparison expressions + BinaryOperation { + left: Box>, + operator: Node, + right: Box>, + }, // Function calls BuiltInFunctionCall { @@ -54,31 +59,25 @@ pub enum Statement { value_arguments: Option>>, }, - // Comparison expressions - Comparison( - Box>, - Node, - Box>, - ), - - // Property access + // Property access expression PropertyAccess(Box>, Box>), - // Value collections + // Identifier expression + Identifier(Identifier), + + // Value collection expressions List(Vec>), // Hard-coded values Constant(Value), - Identifier(Identifier), } impl Statement { pub fn expected_type(&self, variables: &HashMap) -> Option { match self { - Statement::Add(left, _) => left.inner.expected_type(variables), - Statement::Assign(_, _) => None, - Statement::BuiltInFunctionCall { function, .. } => function.expected_type(), - Statement::Comparison(_, _, _) => Some(Type::Boolean), + Statement::Assignment { .. } => None, + Statement::BinaryOperation { left, .. } => left.inner.expected_type(variables), + Statement::BuiltInFunctionCall { function, .. } => function.expected_return_type(), Statement::Constant(value) => Some(value.r#type(variables)), Statement::FunctionCall { function, .. } => function.inner.expected_type(variables), Statement::Identifier(identifier) => variables @@ -88,9 +87,7 @@ impl Statement { .first() .map(|node| node.inner.expected_type(variables)) .flatten(), - Statement::Multiply(left, _) => left.inner.expected_type(variables), Statement::PropertyAccess(_, _) => None, - Statement::Subtract(left, _) => left.inner.expected_type(variables), } } } @@ -98,8 +95,19 @@ impl Statement { impl Display for Statement { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Statement::Assign(left, right) => write!(f, "{left} = {right}"), - Statement::Add(left, right) => write!(f, "{left} + {right}"), + Statement::Assignment { + identifier, + value_node: value, + } => { + write!(f, "{identifier} = {value}") + } + Statement::BinaryOperation { + left, + operator, + right, + } => { + write!(f, "{left} {operator} {right}") + } Statement::BuiltInFunctionCall { function, type_arguments: type_parameters, @@ -135,7 +143,6 @@ impl Display for Statement { write!(f, ")") } - Statement::Comparison(left, operator, right) => write!(f, "{left} {operator} {right}"), Statement::Constant(value) => write!(f, "{value}"), Statement::FunctionCall { function, @@ -183,28 +190,34 @@ impl Display for Statement { } write!(f, "]") } - Statement::Multiply(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)] -pub enum ComparisonOperator { - GreaterThan, - GreaterThanOrEqual, - LessThan, - LessThanOrEqual, +pub enum BinaryOperator { + Add, + Divide, + Greater, + GreaterOrEqual, + Less, + LessOrEqual, + Multiply, + Subtract, } -impl Display for ComparisonOperator { +impl Display for BinaryOperator { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { - ComparisonOperator::GreaterThan => write!(f, ">"), - ComparisonOperator::GreaterThanOrEqual => write!(f, ">="), - ComparisonOperator::LessThan => write!(f, "<"), - ComparisonOperator::LessThanOrEqual => write!(f, "<="), + BinaryOperator::Add => write!(f, "+"), + BinaryOperator::Divide => write!(f, "/"), + BinaryOperator::Greater => write!(f, ">"), + BinaryOperator::GreaterOrEqual => write!(f, ">="), + BinaryOperator::Less => write!(f, "<"), + BinaryOperator::LessOrEqual => write!(f, "<="), + BinaryOperator::Multiply => write!(f, "*"), + BinaryOperator::Subtract => write!(f, "-"), } } } diff --git a/dust-lang/src/analyzer.rs b/dust-lang/src/analyzer.rs index a9d05f0..4ec723f 100644 --- a/dust-lang/src/analyzer.rs +++ b/dust-lang/src/analyzer.rs @@ -11,7 +11,10 @@ use std::{ 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. /// @@ -74,68 +77,26 @@ impl<'a> Analyzer<'a> { fn analyze_node(&self, node: &Node) -> Result<(), AnalyzerError> { match &node.inner { - Statement::Add(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::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::Assignment { + identifier, + value_node: value, + } => { + if let None = value.inner.expected_type(self.variables) { + return Err(AnalyzerError::ExpectedValue { + actual: value.as_ref().clone(), + position: value.position, }); } - + } + Statement::BinaryOperation { + left, + operator, + right, + } => { + self.analyze_node(left)?; self.analyze_node(right)?; } 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::FunctionCall { function, .. } => { if let Statement::Identifier(_) = &function.inner { @@ -158,37 +119,13 @@ impl<'a> Analyzer<'a> { 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) => { if let Statement::Identifier(_) | Statement::Constant(_) | Statement::List(_) = &left.inner { // Left side is valid } else { - return Err(AnalyzerError::ExpectedIdentifierOrValue { + return Err(AnalyzerError::ExpectedValue { actual: left.as_ref().clone(), position: left.position, }); @@ -208,30 +145,6 @@ impl<'a> Analyzer<'a> { 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(()) @@ -244,6 +157,10 @@ pub enum AnalyzerError { actual: Node, position: Span, }, + ExpectedFloat { + actual: Node, + position: (usize, usize), + }, ExpectedFunction { actual: Node, position: Span, @@ -252,7 +169,7 @@ pub enum AnalyzerError { actual: Node, position: Span, }, - ExpectedIdentifierOrValue { + ExpectedInteger { actual: Node, position: Span, }, @@ -264,22 +181,38 @@ pub enum AnalyzerError { actual: Node, position: Span, }, + ExpectedString { + actual: Node, + position: (usize, usize), + }, + ExpectedValue { + actual: Node, + position: Span, + }, UnexpectedIdentifier { identifier: Node, position: Span, }, + UnexectedString { + actual: Node, + position: (usize, usize), + }, } impl AnalyzerError { pub fn position(&self) -> Span { match self { AnalyzerError::ExpectedBoolean { position, .. } => *position, + AnalyzerError::ExpectedFloat { position, .. } => *position, AnalyzerError::ExpectedFunction { position, .. } => *position, AnalyzerError::ExpectedIdentifier { position, .. } => *position, - AnalyzerError::ExpectedIdentifierOrValue { position, .. } => *position, + AnalyzerError::ExpectedValue { position, .. } => *position, + AnalyzerError::ExpectedInteger { position, .. } => *position, AnalyzerError::ExpectedIntegerOrFloat { position, .. } => *position, AnalyzerError::ExpectedIntegerFloatOrString { position, .. } => *position, + AnalyzerError::ExpectedString { position, .. } => *position, AnalyzerError::UnexpectedIdentifier { position, .. } => *position, + AnalyzerError::UnexectedString { position, .. } => *position, } } } @@ -295,11 +228,14 @@ impl Display for AnalyzerError { AnalyzerError::ExpectedFunction { actual, .. } => { write!(f, "Expected function, found {}", actual) } + AnalyzerError::ExpectedFloat { actual, .. } => { + write!(f, "Expected float, found {}", actual) + } AnalyzerError::ExpectedIdentifier { actual, .. } => { write!(f, "Expected identifier, found {}", actual) } - AnalyzerError::ExpectedIdentifierOrValue { actual, .. } => { - write!(f, "Expected identifier or value, found {}", actual) + AnalyzerError::ExpectedInteger { actual, .. } => { + write!(f, "Expected integer, found {}", actual) } AnalyzerError::ExpectedIntegerOrFloat { actual, .. } => { write!(f, "Expected integer or float, found {}", actual) @@ -307,9 +243,18 @@ impl Display for AnalyzerError { AnalyzerError::ExpectedIntegerFloatOrString { 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, .. } => { write!(f, "Unexpected identifier {}", identifier) } + AnalyzerError::UnexectedString { actual, .. } => { + write!(f, "Unexpected string {}", actual) + } } } } @@ -324,11 +269,12 @@ mod tests { fn add_expects_same_types() { let abstract_tree = AbstractSyntaxTree { nodes: [Node::new( - Statement::Add( - Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), - Box::new(Node::new(Statement::Constant(Value::float(1.0)), (1, 2))), - ), - (0, 2), + Statement::BinaryOperation { + left: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), + operator: Node::new(BinaryOperator::Add, (1, 2)), + right: Box::new(Node::new(Statement::Constant(Value::float(1.0)), (3, 4))), + }, + (0, 4), )] .into(), }; @@ -348,10 +294,11 @@ mod tests { fn add_expects_integer_float_or_string() { let abstract_tree = AbstractSyntaxTree { nodes: [Node::new( - Statement::Add( - Box::new(Node::new(Statement::Constant(Value::boolean(true)), (0, 1))), - Box::new(Node::new(Statement::Constant(Value::integer(1)), (1, 2))), - ), + Statement::BinaryOperation { + left: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), + operator: Node::new(BinaryOperator::Add, (1, 2)), + right: Box::new(Node::new(Statement::Constant(Value::boolean(true)), (3, 4))), + }, (0, 2), )] .into(), @@ -433,13 +380,14 @@ mod tests { fn multiply_expect_integer_or_float() { let abstract_tree = AbstractSyntaxTree { nodes: [Node::new( - Statement::Multiply( - Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), - Box::new(Node::new( + Statement::BinaryOperation { + left: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), + operator: Node::new(BinaryOperator::Multiply, (1, 2)), + right: Box::new(Node::new( Statement::Constant(Value::boolean(false)), - (1, 2), + (3, 4), )), - ), + }, (0, 2), )] .into(), @@ -460,10 +408,10 @@ mod tests { fn assignment_expect_identifier() { let abstract_tree = AbstractSyntaxTree { nodes: [Node::new( - Statement::Assign( - Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), - Box::new(Node::new(Statement::Constant(Value::integer(2)), (1, 2))), - ), + Statement::Assignment { + identifier: Identifier::new("x"), + value_node: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), + }, (0, 2), )] .into(), diff --git a/dust-lang/src/built_in_function.rs b/dust-lang/src/built_in_function.rs index 6673b51..39b5a72 100644 --- a/dust-lang/src/built_in_function.rs +++ b/dust-lang/src/built_in_function.rs @@ -113,7 +113,7 @@ impl BuiltInFunction { } } - pub fn expected_type(&self) -> Option { + pub fn expected_return_type(&self) -> Option { match self { BuiltInFunction::IsEven => Some(Type::Boolean), BuiltInFunction::IsOdd => Some(Type::Boolean), diff --git a/dust-lang/src/identifier.rs b/dust-lang/src/identifier.rs index 42f874b..ec4abed 100644 --- a/dust-lang/src/identifier.rs +++ b/dust-lang/src/identifier.rs @@ -20,15 +20,17 @@ pub struct Identifier(Arc); impl Identifier { pub fn new(text: T) -> Self { - let cache = identifier_cache(); + let cache = identifier_cache().read().unwrap(); let new = Identifier(Arc::new(text.to_string())); - if let Some(identifier) = cache.read().unwrap().get(&new).cloned() { - return identifier; + if cache.contains(&new) { + return new; } - cache.write().unwrap().insert(new.clone()); + drop(cache); + + identifier_cache().write().unwrap().insert(new.clone()); new } diff --git a/dust-lang/src/parse.rs b/dust-lang/src/parse.rs index e2c1b6f..73de1b2 100644 --- a/dust-lang/src/parse.rs +++ b/dust-lang/src/parse.rs @@ -10,7 +10,7 @@ use std::{ }; 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, }; @@ -169,16 +169,27 @@ impl<'src> Parser<'src> { (Token::Equal, _) => { 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_end = right_node.position.1; 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), )); } (Token::Greater, _) => { - let operator_position = self.current.1; + let operator = Node::new(BinaryOperator::Greater, self.current.1); self.next_token()?; @@ -186,16 +197,16 @@ impl<'src> Parser<'src> { let right_end = right_node.position.1; return Ok(Node::new( - Statement::Comparison( - Box::new(left_node), - Node::new(ComparisonOperator::GreaterThan, operator_position), - Box::new(right_node), - ), + Statement::BinaryOperation { + left: Box::new(left_node), + operator, + right: Box::new(right_node), + }, (left_start, right_end), )); } (Token::GreaterEqual, _) => { - let operator_position = self.current.1; + let operator = Node::new(BinaryOperator::GreaterOrEqual, self.current.1); self.next_token()?; @@ -203,16 +214,16 @@ impl<'src> Parser<'src> { let right_end = right_node.position.1; return Ok(Node::new( - Statement::Comparison( - Box::new(left_node), - Node::new(ComparisonOperator::GreaterThanOrEqual, operator_position), - Box::new(right_node), - ), + Statement::BinaryOperation { + left: Box::new(left_node), + operator, + right: Box::new(right_node), + }, (left_start, right_end), )); } (Token::Less, _) => { - let operator_position = self.current.1; + let operator = Node::new(BinaryOperator::Less, self.current.1); self.next_token()?; @@ -220,16 +231,16 @@ impl<'src> Parser<'src> { let right_end = right_node.position.1; return Ok(Node::new( - Statement::Comparison( - Box::new(left_node), - Node::new(ComparisonOperator::LessThan, operator_position), - Box::new(right_node), - ), + Statement::BinaryOperation { + left: Box::new(left_node), + operator, + right: Box::new(right_node), + }, (left_start, right_end), )); } (Token::LessEqual, _) => { - let operator_position = self.current.1; + let operator = Node::new(BinaryOperator::LessOrEqual, self.current.1); self.next_token()?; @@ -237,44 +248,62 @@ impl<'src> Parser<'src> { let right_end = right_node.position.1; return Ok(Node::new( - Statement::Comparison( - Box::new(left_node), - Node::new(ComparisonOperator::LessThanOrEqual, operator_position), - Box::new(right_node), - ), + Statement::BinaryOperation { + left: Box::new(left_node), + operator, + right: Box::new(right_node), + }, (left_start, right_end), )); } (Token::Minus, _) => { + let operator = Node::new(BinaryOperator::Subtract, self.current.1); + self.next_token()?; let right_node = self.parse_node(self.current_precedence())?; let right_end = right_node.position.1; 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), )); } (Token::Plus, _) => { + let operator = Node::new(BinaryOperator::Add, self.current.1); + self.next_token()?; let right_node = self.parse_node(self.current_precedence())?; let right_end = right_node.position.1; 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), )); } (Token::Star, _) => { + let operator = Node::new(BinaryOperator::Multiply, self.current.1); + self.next_token()?; let right_node = self.parse_node(self.current_precedence())?; let right_end = right_node.position.1; 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), )); } @@ -447,12 +476,31 @@ impl<'src> Parser<'src> { #[derive(Debug, PartialEq, Clone)] pub enum ParseError { - LexError { error: LexError, position: Span }, + LexError { + error: LexError, + position: Span, + }, - ExpectedClosingParenthesis { actual: TokenOwned, position: Span }, - ExpectedClosingSquareBrace { actual: TokenOwned, position: Span }, - ExpectedOpeningParenthesis { actual: TokenOwned, position: Span }, - UnexpectedToken { actual: TokenOwned, position: Span }, + ExpectedClosingParenthesis { + 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 { @@ -461,6 +509,7 @@ impl ParseError { Self::LexError { position, .. } => *position, Self::ExpectedClosingParenthesis { position, .. } => *position, Self::ExpectedClosingSquareBrace { position, .. } => *position, + Self::ExpectedIdentifier { position, .. } => *position, Self::ExpectedOpeningParenthesis { position, .. } => *position, Self::UnexpectedToken { position, .. } => *position, } @@ -486,6 +535,9 @@ impl Display for ParseError { Self::ExpectedClosingSquareBrace { actual, .. } => { write!(f, "Expected closing square brace, found {actual}",) } + Self::ExpectedIdentifier { actual, .. } => { + write!(f, "Expected identifier, found {actual}") + } Self::ExpectedOpeningParenthesis { actual, .. } => { write!(f, "Expected opening parenthesis, found {actual}",) } @@ -496,7 +548,7 @@ impl Display for ParseError { #[cfg(test)] mod tests { - use crate::{abstract_tree::ComparisonOperator, Identifier}; + use crate::{abstract_tree::BinaryOperator, Identifier}; use super::*; @@ -508,11 +560,11 @@ mod tests { parse(input), Ok(AbstractSyntaxTree { nodes: [Node::new( - Statement::Comparison( - Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), - Node::new(ComparisonOperator::LessThan, (2, 3)), - Box::new(Node::new(Statement::Constant(Value::integer(2)), (4, 5))) - ), + Statement::BinaryOperation { + left: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), + operator: Node::new(BinaryOperator::Less, (2, 3)), + right: Box::new(Node::new(Statement::Constant(Value::integer(2)), (4, 5))), + }, (0, 5) )] .into() @@ -528,11 +580,11 @@ mod tests { parse(input), Ok(AbstractSyntaxTree { nodes: [Node::new( - Statement::Comparison( - Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), - Node::new(ComparisonOperator::LessThanOrEqual, (2, 4)), - Box::new(Node::new(Statement::Constant(Value::integer(2)), (5, 6))) - ), + Statement::BinaryOperation { + left: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), + operator: Node::new(BinaryOperator::Less, (2, 4)), + right: Box::new(Node::new(Statement::Constant(Value::integer(2)), (5, 6))), + }, (0, 6) )] .into() @@ -548,11 +600,11 @@ mod tests { parse(input), Ok(AbstractSyntaxTree { nodes: [Node::new( - Statement::Comparison( - Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), - Node::new(ComparisonOperator::GreaterThanOrEqual, (2, 4)), - Box::new(Node::new(Statement::Constant(Value::integer(2)), (5, 6))) - ), + Statement::BinaryOperation { + left: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), + operator: Node::new(BinaryOperator::Greater, (2, 4)), + right: Box::new(Node::new(Statement::Constant(Value::integer(2)), (5, 6))), + }, (0, 6) )] .into() @@ -568,11 +620,11 @@ mod tests { parse(input), Ok(AbstractSyntaxTree { nodes: [Node::new( - Statement::Comparison( - Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), - Node::new(ComparisonOperator::GreaterThan, (2, 3)), - Box::new(Node::new(Statement::Constant(Value::integer(2)), (4, 5))) - ), + Statement::BinaryOperation { + left: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), + operator: Node::new(BinaryOperator::Greater, (2, 3)), + right: Box::new(Node::new(Statement::Constant(Value::integer(2)), (4, 5))), + }, (0, 5) )] .into() @@ -588,10 +640,11 @@ mod tests { parse(input), Ok(AbstractSyntaxTree { nodes: [Node::new( - Statement::Subtract( - Box::new(Node::new(Statement::Constant(Value::integer(-1)), (0, 2))), - Box::new(Node::new(Statement::Constant(Value::integer(-2)), (5, 7))) - ), + Statement::BinaryOperation { + left: Node::new(Statement::Constant(Value::integer(1)), (1, 2)).into(), + operator: Node::new(BinaryOperator::Subtract, (3, 4)), + right: Node::new(Statement::Constant(Value::integer(2)), (6, 7)).into() + }, (0, 7) )] .into() @@ -607,17 +660,18 @@ mod tests { parse(input), Ok(AbstractSyntaxTree { nodes: [Node::new( - Statement::Add( - Box::new(Node::new( + Statement::BinaryOperation { + left: Box::new(Node::new( 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!")), - (12, 20) + (11, 19) )) - ), - (0, 20) + }, + (0, 19) )] .into() }) @@ -740,33 +794,42 @@ mod tests { Statement::List(vec![ Node::new(Statement::Constant(Value::integer(1)), (1, 2)), Node::new( - Statement::Add( - Box::new(Node::new(Statement::Constant(Value::integer(1)), (4, 5))), - Box::new(Node::new(Statement::Constant(Value::integer(1)), (8, 9))), - ), - (4, 9), + Statement::BinaryOperation { + left: Box::new(Node::new( + Statement::Constant(Value::integer(1)), + (4, 5) + )), + operator: Node::new(BinaryOperator::Add, (6, 7)), + right: Box::new(Node::new( + Statement::Constant(Value::integer(1)), + (8, 9) + )) + }, + (4, 9) ), Node::new( - Statement::Add( - Box::new(Node::new( + Statement::BinaryOperation { + left: Box::new(Node::new( Statement::Constant(Value::integer(2)), (11, 12) )), - Box::new(Node::new( - Statement::Multiply( - Box::new(Node::new( + operator: Node::new(BinaryOperator::Add, (13, 14)), + right: Box::new(Node::new( + Statement::BinaryOperation { + left: Box::new(Node::new( Statement::Constant(Value::integer(4)), (16, 17) )), - Box::new(Node::new( + operator: Node::new(BinaryOperator::Multiply, (18, 19)), + right: Box::new(Node::new( Statement::Constant(Value::integer(10)), (20, 22) - )), - ), - (15, 23), - ),), - ), - (11, 23), + )) + }, + (15, 23) + )) + }, + (11, 23) ), ]), (0, 24), @@ -827,10 +890,11 @@ mod tests { parse(input), Ok(AbstractSyntaxTree { nodes: [Node::new( - Statement::Add( - Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), - Box::new(Node::new(Statement::Constant(Value::integer(2)), (4, 5))), - ), + Statement::BinaryOperation { + left: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), + operator: Node::new(BinaryOperator::Add, (2, 3)), + right: Box::new(Node::new(Statement::Constant(Value::integer(2)), (4, 5)),) + }, (0, 5), )] .into() @@ -846,10 +910,11 @@ mod tests { parse(input), Ok(AbstractSyntaxTree { nodes: [Node::new( - Statement::Multiply( - Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), - Box::new(Node::new(Statement::Constant(Value::integer(2)), (4, 5))), - ), + Statement::BinaryOperation { + left: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), + operator: Node::new(BinaryOperator::Multiply, (2, 3)), + right: Box::new(Node::new(Statement::Constant(Value::integer(2)), (4, 5)),) + }, (0, 5), )] .into() @@ -865,16 +930,24 @@ mod tests { parse(input), Ok(AbstractSyntaxTree { nodes: [Node::new( - Statement::Add( - Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), - Box::new(Node::new( - Statement::Multiply( - Box::new(Node::new(Statement::Constant(Value::integer(2)), (4, 5))), - Box::new(Node::new(Statement::Constant(Value::integer(3)), (8, 9))), - ), - (4, 9), - )), - ), + Statement::BinaryOperation { + left: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), + operator: Node::new(BinaryOperator::Add, (2, 3)), + right: Box::new(Node::new( + Statement::BinaryOperation { + left: Box::new(Node::new( + Statement::Constant(Value::integer(2)), + (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), )] .into() @@ -890,31 +963,33 @@ mod tests { parse(input), Ok(AbstractSyntaxTree { nodes: [Node::new( - Statement::Assign( - Box::new(Node::new( - Statement::Identifier(Identifier::new("a")), - (0, 1) - )), - Box::new(Node::new( - Statement::Add( - Box::new(Node::new(Statement::Constant(Value::integer(1)), (4, 5))), - Box::new(Node::new( - Statement::Multiply( - Box::new(Node::new( + Statement::Assignment { + identifier: Identifier::new("a"), + value_node: Box::new(Node::new( + Statement::BinaryOperation { + left: Box::new(Node::new( + Statement::Constant(Value::integer(1)), + (4, 5) + )), + operator: Node::new(BinaryOperator::Add, (6, 7)), + right: Box::new(Node::new( + Statement::BinaryOperation { + left: Box::new(Node::new( Statement::Constant(Value::integer(2)), (8, 9) )), - Box::new(Node::new( + operator: Node::new(BinaryOperator::Multiply, (10, 11)), + right: Box::new(Node::new( Statement::Constant(Value::integer(3)), (12, 13) - )), - ), - (8, 13), - )), - ), - (4, 13), - )), - ), + ),) + }, + (8, 13) + ),) + }, + (4, 13) + ),) + }, (0, 13), )] .into() diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index 77c9ee6..5a13278 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -6,7 +6,7 @@ use std::{ }; use crate::{ - abstract_tree::ComparisonOperator, parse, AbstractSyntaxTree, Analyzer, AnalyzerError, + abstract_tree::BinaryOperator, parse, AbstractSyntaxTree, Analyzer, AnalyzerError, BuiltInFunctionError, Identifier, Node, ParseError, Span, Statement, Value, ValueError, }; @@ -52,53 +52,65 @@ impl Vm { variables: &mut HashMap, ) -> Result, VmError> { match node.inner { - Statement::Add(left, right) => { - let left_span = left.position; - let left = if let Some(value) = self.run_node(*left, variables)? { + Statement::Assignment { + identifier, + value_node, + } => { + let value_node_position = value_node.position; + let value = if let Some(value) = self.run_node(*value_node, 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 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, + position: value_node_position, }); }; - variables.insert(identifier.clone(), value); + variables.insert(identifier, value); 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 { function, type_arguments: _, @@ -132,54 +144,6 @@ impl Vm { 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::FunctionCall { function: function_node, @@ -250,32 +214,6 @@ impl Vm { 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) => { let left_span = left.position; let left_value = if let Some(value) = self.run_node(*left, variables)? { @@ -337,32 +275,6 @@ impl Vm { 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)) - } } } }