From a0b754cc1cac25bac86afcfc9e78e908be2ab779 Mon Sep 17 00:00:00 2001 From: Jeff Date: Sun, 16 Jun 2024 03:12:04 -0400 Subject: [PATCH] Begin preparing for type expressions --- dust-lang/src/abstract_tree/as.rs | 20 +- dust-lang/src/abstract_tree/assignment.rs | 30 +- dust-lang/src/abstract_tree/async_block.rs | 12 +- dust-lang/src/abstract_tree/block.rs | 28 +- .../abstract_tree/built_in_function_call.rs | 38 +- dust-lang/src/abstract_tree/expression.rs | 136 ------ dust-lang/src/abstract_tree/function_call.rs | 52 +-- dust-lang/src/abstract_tree/if_else.rs | 48 +-- dust-lang/src/abstract_tree/list_index.rs | 70 ++-- dust-lang/src/abstract_tree/logic.rs | 76 ++-- dust-lang/src/abstract_tree/loop.rs | 6 +- dust-lang/src/abstract_tree/map_index.rs | 168 ++++---- dust-lang/src/abstract_tree/math.rs | 85 ++-- dust-lang/src/abstract_tree/mod.rs | 15 +- dust-lang/src/abstract_tree/statement.rs | 80 ++-- .../src/abstract_tree/structure_definition.rs | 4 - dust-lang/src/abstract_tree/type.rs | 28 +- dust-lang/src/abstract_tree/type_alias.rs | 12 +- .../src/abstract_tree/value_expression.rs | 142 +++++++ dust-lang/src/abstract_tree/value_node.rs | 156 +++---- dust-lang/src/abstract_tree/while.rs | 10 +- dust-lang/src/lib.rs | 2 +- dust-lang/src/parser.rs | 387 ++++++++++-------- dust-lang/src/value.rs | 26 +- dust-lang/tests/functions.rs | 14 - dust-lang/tests/variables.rs | 8 +- 26 files changed, 835 insertions(+), 818 deletions(-) delete mode 100644 dust-lang/src/abstract_tree/expression.rs create mode 100644 dust-lang/src/abstract_tree/value_expression.rs diff --git a/dust-lang/src/abstract_tree/as.rs b/dust-lang/src/abstract_tree/as.rs index 37483b7..07f115f 100644 --- a/dust-lang/src/abstract_tree/as.rs +++ b/dust-lang/src/abstract_tree/as.rs @@ -9,31 +9,27 @@ use crate::{ Value, }; -use super::{AbstractNode, Action, Expression, Type, WithPosition}; +use super::{AbstractNode, Action, ExpectedType, Type, ValueExpression, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct As { - expression: Expression, + expression: ValueExpression, r#type: WithPosition, } impl As { - pub fn new(expression: Expression, r#type: WithPosition) -> Self { + pub fn new(expression: ValueExpression, r#type: WithPosition) -> Self { Self { expression, r#type } } } impl AbstractNode for As { - fn expected_type(&self, _: &mut Context) -> Result { - Ok(self.r#type.item.clone()) - } - fn validate( &self, _context: &mut Context, _manage_memory: bool, ) -> Result<(), ValidationError> { - match self.r#type.item { + match self.r#type.node { Type::Boolean | Type::Float | Type::Integer | Type::String => {} _ => todo!("Create an error for this occurence."), }; @@ -54,7 +50,7 @@ impl AbstractNode for As { ValidationError::InterpreterExpectedReturn(expression_position), )); }; - let (from_value, to_type): (&ValueInner, Type) = (value.inner().borrow(), self.r#type.item); + let (from_value, to_type): (&ValueInner, Type) = (value.inner().borrow(), self.r#type.node); let converted = match (from_value, to_type) { (ValueInner::Boolean(boolean), Type::String) => Value::string(boolean.to_string()), @@ -65,3 +61,9 @@ impl AbstractNode for As { Ok(Action::Return(converted)) } } + +impl ExpectedType for As { + fn expected_type(&self, _: &mut Context) -> Result { + Ok(self.r#type.node.clone()) + } +} diff --git a/dust-lang/src/abstract_tree/assignment.rs b/dust-lang/src/abstract_tree/assignment.rs index 3a72d56..54d543e 100644 --- a/dust-lang/src/abstract_tree/assignment.rs +++ b/dust-lang/src/abstract_tree/assignment.rs @@ -7,7 +7,7 @@ use crate::{ Context, Value, }; -use super::{AbstractNode, Action, Statement, Type, WithPosition}; +use super::{AbstractNode, Action, ExpectedType, Statement, Type, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct Assignment { @@ -41,15 +41,11 @@ impl Assignment { } impl AbstractNode for Assignment { - fn expected_type(&self, _context: &mut Context) -> Result { - Ok(Type::None) - } - fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> { let statement_type = self.statement.expected_type(context)?; if let Some(WithPosition { - item: expected_type, + node: expected_type, position: expected_position, }) = &self.r#type { @@ -61,9 +57,9 @@ impl AbstractNode for Assignment { } })?; - context.set_type(self.identifier.item.clone(), expected_type.clone())?; + context.set_type(self.identifier.node.clone(), expected_type.clone())?; } else { - context.set_type(self.identifier.item.clone(), statement_type)?; + context.set_type(self.identifier.node.clone(), statement_type)?; } self.statement.validate(context, manage_memory)?; @@ -80,13 +76,13 @@ impl AbstractNode for Assignment { match self.operator { AssignmentOperator::Assign => { - context.set_value(self.identifier.item, right)?; + context.set_value(self.identifier.node, right)?; } AssignmentOperator::AddAssign => { let left_option = if manage_memory { - context.use_value(&self.identifier.item)? + context.use_value(&self.identifier.node)? } else { - context.get_value(&self.identifier.item)? + context.get_value(&self.identifier.node)? }; if let Some(left) = left_option { @@ -117,11 +113,11 @@ impl AbstractNode for Assignment { )) } }; - context.set_value(self.identifier.item, new_value)?; + context.set_value(self.identifier.node, new_value)?; } else { return Err(RuntimeError::ValidationFailure( ValidationError::VariableNotFound { - identifier: self.identifier.item, + identifier: self.identifier.node, position: self.identifier.position, }, )); @@ -129,9 +125,9 @@ impl AbstractNode for Assignment { } AssignmentOperator::SubAssign => { let left_option = if manage_memory { - context.use_value(&self.identifier.item)? + context.use_value(&self.identifier.node)? } else { - context.get_value(&self.identifier.item)? + context.get_value(&self.identifier.node)? }; if let Some(left) = left_option { @@ -162,11 +158,11 @@ impl AbstractNode for Assignment { )) } }; - context.set_value(self.identifier.item, new_value)?; + context.set_value(self.identifier.node, new_value)?; } else { return Err(RuntimeError::ValidationFailure( ValidationError::VariableNotFound { - identifier: self.identifier.item, + identifier: self.identifier.node, position: self.identifier.position, }, )); diff --git a/dust-lang/src/abstract_tree/async_block.rs b/dust-lang/src/abstract_tree/async_block.rs index f73815f..69e3712 100644 --- a/dust-lang/src/abstract_tree/async_block.rs +++ b/dust-lang/src/abstract_tree/async_block.rs @@ -8,7 +8,7 @@ use crate::{ error::{RuntimeError, RwLockPoisonError, ValidationError}, }; -use super::{AbstractNode, Action, Statement, Type}; +use super::{AbstractNode, Action, ExpectedType, Statement, Type}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct AsyncBlock { @@ -22,10 +22,6 @@ impl AsyncBlock { } impl AbstractNode for AsyncBlock { - fn expected_type(&self, _context: &mut Context) -> Result { - self.statements.last().unwrap().expected_type(_context) - } - fn validate(&self, _context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> { for statement in &self.statements { statement.validate(_context, manage_memory)?; @@ -65,3 +61,9 @@ impl AbstractNode for AsyncBlock { ) } } + +impl ExpectedType for AsyncBlock { + fn expected_type(&self, _context: &mut Context) -> Result { + self.statements.first().unwrap().expected_type(_context) + } +} diff --git a/dust-lang/src/abstract_tree/block.rs b/dust-lang/src/abstract_tree/block.rs index 1824977..5948ad8 100644 --- a/dust-lang/src/abstract_tree/block.rs +++ b/dust-lang/src/abstract_tree/block.rs @@ -5,7 +5,7 @@ use crate::{ error::{RuntimeError, ValidationError}, }; -use super::{AbstractNode, Action, Statement, Type}; +use super::{AbstractNode, Action, ExpectedType, Statement}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct Block { @@ -27,14 +27,6 @@ impl Block { } impl AbstractNode for Block { - fn expected_type(&self, _context: &mut Context) -> Result { - if let Some(statement) = self.statements.last() { - statement.expected_type(_context) - } else { - Ok(Type::None) - } - } - fn validate( &self, _context: &mut Context, @@ -58,10 +50,16 @@ impl AbstractNode for Block { } } +impl ExpectedType for Block { + fn expected_type(&self, _context: &mut Context) -> Result { + self.last_statement().expected_type(_context) + } +} + #[cfg(test)] mod tests { use crate::{ - abstract_tree::{Expression, ValueNode, WithPos}, + abstract_tree::{Type, ValueExpression, ValueNode, WithPos}, Value, }; @@ -70,13 +68,13 @@ mod tests { #[test] fn run_returns_value_of_final_statement() { let block = Block::new(vec![ - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Integer(1).with_position((0, 0)), )), - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Integer(2).with_position((0, 0)), )), - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Integer(42).with_position((0, 0)), )), ]); @@ -90,10 +88,10 @@ mod tests { #[test] fn expected_type_returns_type_of_final_statement() { let block = Block::new(vec![ - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::String("42".to_string()).with_position((0, 0)), )), - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Integer(42).with_position((0, 0)), )), ]); diff --git a/dust-lang/src/abstract_tree/built_in_function_call.rs b/dust-lang/src/abstract_tree/built_in_function_call.rs index 47499a5..63babec 100644 --- a/dust-lang/src/abstract_tree/built_in_function_call.rs +++ b/dust-lang/src/abstract_tree/built_in_function_call.rs @@ -15,30 +15,19 @@ use crate::{ Value, }; -use super::{AbstractNode, Expression, WithPosition}; +use super::{AbstractNode, ExpectedType, ValueExpression, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub enum BuiltInFunctionCall { - JsonParse(WithPosition, Expression), - Length(Expression), - ReadFile(Expression), + JsonParse(WithPosition, ValueExpression), + Length(ValueExpression), + ReadFile(ValueExpression), ReadLine, - Sleep(Expression), - WriteLine(Expression), + Sleep(ValueExpression), + WriteLine(ValueExpression), } impl AbstractNode for BuiltInFunctionCall { - fn expected_type(&self, _context: &mut Context) -> Result { - match self { - BuiltInFunctionCall::JsonParse(r#type, _) => Ok(r#type.item.clone()), - BuiltInFunctionCall::Length(_) => Ok(Type::Integer), - BuiltInFunctionCall::ReadFile(_) => Ok(Type::String), - BuiltInFunctionCall::ReadLine => Ok(Type::String), - BuiltInFunctionCall::Sleep(_) => Ok(Type::None), - BuiltInFunctionCall::WriteLine(_) => Ok(Type::None), - } - } - fn validate( &self, _context: &mut Context, @@ -64,7 +53,7 @@ impl AbstractNode for BuiltInFunctionCall { fn run(self, context: &mut Context, _manage_memory: bool) -> Result { match self { - BuiltInFunctionCall::JsonParse(r#type, expression) => { + BuiltInFunctionCall::JsonParse(_type, expression) => { let action = expression.clone().run(context, _manage_memory)?; let value = if let Action::Return(value) = action { value @@ -169,3 +158,16 @@ impl AbstractNode for BuiltInFunctionCall { } } } + +impl ExpectedType for BuiltInFunctionCall { + fn expected_type(&self, _context: &mut Context) -> Result { + match self { + BuiltInFunctionCall::JsonParse(r#type, _) => Ok(r#type.node.clone()), + BuiltInFunctionCall::Length(_) => Ok(Type::Integer), + BuiltInFunctionCall::ReadFile(_) => Ok(Type::String), + BuiltInFunctionCall::ReadLine => Ok(Type::String), + BuiltInFunctionCall::Sleep(_) => Ok(Type::None), + BuiltInFunctionCall::WriteLine(_) => Ok(Type::None), + } + } +} diff --git a/dust-lang/src/abstract_tree/expression.rs b/dust-lang/src/abstract_tree/expression.rs deleted file mode 100644 index 3322c6b..0000000 --- a/dust-lang/src/abstract_tree/expression.rs +++ /dev/null @@ -1,136 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::{ - context::Context, - error::{RuntimeError, ValidationError}, - identifier::Identifier, -}; - -use super::{ - AbstractNode, Action, As, BuiltInFunctionCall, FunctionCall, ListIndex, Logic, MapIndex, Math, - SourcePosition, Type, ValueNode, WithPosition, -}; - -#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] -pub enum Expression { - As(WithPosition>), - BuiltInFunctionCall(WithPosition>), - FunctionCall(WithPosition), - Identifier(WithPosition), - MapIndex(WithPosition>), - ListIndex(WithPosition>), - Logic(WithPosition>), - Math(WithPosition>), - Value(WithPosition), -} - -impl Expression { - pub fn position(&self) -> SourcePosition { - match self { - Expression::As(inner) => inner.position, - Expression::FunctionCall(inner) => inner.position, - Expression::Identifier(inner) => inner.position, - Expression::MapIndex(inner) => inner.position, - Expression::ListIndex(inner) => inner.position, - Expression::Logic(inner) => inner.position, - Expression::Math(inner) => inner.position, - Expression::Value(inner) => inner.position, - Expression::BuiltInFunctionCall(inner) => inner.position, - } - } -} - -impl AbstractNode for Expression { - fn expected_type(&self, _context: &mut Context) -> Result { - match self { - Expression::As(r#as) => r#as.item.expected_type(_context), - Expression::FunctionCall(function_call) => function_call.item.expected_type(_context), - Expression::Identifier(identifier) => { - if let Some(r#type) = _context.get_type(&identifier.item)? { - Ok(r#type) - } else { - Err(ValidationError::VariableNotFound { - identifier: identifier.item.clone(), - position: identifier.position, - }) - } - } - Expression::MapIndex(map_index) => map_index.item.expected_type(_context), - Expression::ListIndex(list_index) => list_index.item.expected_type(_context), - Expression::Logic(logic) => logic.item.expected_type(_context), - Expression::Math(math) => math.item.expected_type(_context), - Expression::Value(value_node) => value_node.item.expected_type(_context), - Expression::BuiltInFunctionCall(built_in_function_call) => { - built_in_function_call.item.expected_type(_context) - } - } - } - - fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> { - match self { - Expression::As(r#as) => r#as.item.validate(context, manage_memory), - Expression::FunctionCall(function_call) => { - function_call.item.validate(context, manage_memory) - } - Expression::Identifier(identifier) => { - let found = if manage_memory { - context.add_expected_use(&identifier.item)? - } else { - context.contains(&identifier.item)? - }; - - if found { - Ok(()) - } else { - Err(ValidationError::VariableNotFound { - identifier: identifier.item.clone(), - position: identifier.position, - }) - } - } - Expression::MapIndex(map_index) => map_index.item.validate(context, manage_memory), - Expression::ListIndex(list_index) => list_index.item.validate(context, manage_memory), - Expression::Logic(logic) => logic.item.validate(context, manage_memory), - Expression::Math(math) => math.item.validate(context, manage_memory), - Expression::Value(value_node) => value_node.item.validate(context, manage_memory), - Expression::BuiltInFunctionCall(built_in_function_call) => { - built_in_function_call.item.validate(context, manage_memory) - } - } - } - - fn run(self, context: &mut Context, manage_memory: bool) -> Result { - match self { - Expression::As(r#as) => r#as.item.run(context, manage_memory), - Expression::FunctionCall(function_call) => { - function_call.item.run(context, manage_memory) - } - Expression::Identifier(identifier) => { - let value_option = if manage_memory { - context.use_value(&identifier.item)? - } else { - context.get_value(&identifier.item)? - }; - - if let Some(value) = value_option { - Ok(Action::Return(value)) - } else { - Err(RuntimeError::ValidationFailure( - ValidationError::VariableNotFound { - identifier: identifier.item.clone(), - position: identifier.position, - }, - )) - } - } - Expression::MapIndex(map_index) => map_index.item.run(context, manage_memory), - Expression::ListIndex(list_index) => list_index.item.run(context, manage_memory), - Expression::Logic(logic) => logic.item.run(context, manage_memory), - Expression::Math(math) => math.item.run(context, manage_memory), - Expression::Value(value_node) => value_node.item.run(context, manage_memory), - Expression::BuiltInFunctionCall(built_in_function_call) => { - built_in_function_call.item.run(context, manage_memory) - } - } - } -} diff --git a/dust-lang/src/abstract_tree/function_call.rs b/dust-lang/src/abstract_tree/function_call.rs index fd86885..1d0ba7f 100644 --- a/dust-lang/src/abstract_tree/function_call.rs +++ b/dust-lang/src/abstract_tree/function_call.rs @@ -6,20 +6,20 @@ use crate::{ value::ValueInner, }; -use super::{AbstractNode, Action, Expression, Type, WithPosition}; +use super::{AbstractNode, Action, ExpectedType, Type, ValueExpression, WithPosition}; #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct FunctionCall { - function: Box, + function: Box, type_arguments: Vec>, - arguments: Vec, + arguments: Vec, } impl FunctionCall { pub fn new( - function: Expression, + function: ValueExpression, type_arguments: Vec>, - arguments: Vec, + arguments: Vec, ) -> Self { FunctionCall { function: Box::new(function), @@ -30,19 +30,6 @@ impl FunctionCall { } impl AbstractNode for FunctionCall { - fn expected_type(&self, _context: &mut Context) -> Result { - let function_node_type = self.function.expected_type(_context)?; - - if let Type::Function { return_type, .. } = function_node_type { - Ok(return_type.item) - } else { - Err(ValidationError::ExpectedFunction { - actual: function_node_type, - position: self.function.position(), - }) - } - } - fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> { self.function.validate(context, manage_memory)?; @@ -60,13 +47,13 @@ impl AbstractNode for FunctionCall { for (type_parameter, type_argument) in parameter_types.iter().zip(self.type_arguments.iter()) { - if let Type::Argument(_) = type_parameter.item { + if let Type::Argument(_) = type_parameter.node { continue; } type_parameter - .item - .check(&type_argument.item) + .node + .check(&type_argument.node) .map_err(|conflict| ValidationError::TypeCheck { conflict, actual_position: type_argument.position, @@ -75,13 +62,13 @@ impl AbstractNode for FunctionCall { } for (type_parameter, expression) in parameter_types.iter().zip(self.arguments.iter()) { - if let Type::Argument(_) = type_parameter.item { + if let Type::Argument(_) = type_parameter.node { continue; } let actual = expression.expected_type(context)?; - type_parameter.item.check(&actual).map_err(|conflict| { + type_parameter.node.check(&actual).map_err(|conflict| { ValidationError::TypeCheck { conflict, actual_position: expression.position(), @@ -140,8 +127,8 @@ impl AbstractNode for FunctionCall { for (type_parameter, type_argument) in function .type_parameters() .iter() - .map(|r#type| r#type.item.clone()) - .zip(self.type_arguments.into_iter().map(|r#type| r#type.item)) + .map(|r#type| r#type.node.clone()) + .zip(self.type_arguments.into_iter().map(|r#type| r#type.node)) { if let Type::Argument(identifier) = type_parameter { function_context.set_type(identifier, type_argument)?; @@ -153,3 +140,18 @@ impl AbstractNode for FunctionCall { .call(arguments, &mut function_context, clear_variables) } } + +impl ExpectedType for FunctionCall { + fn expected_type(&self, _context: &mut Context) -> Result { + let function_node_type = self.function.expected_type(_context)?; + + if let Type::Function { return_type, .. } = function_node_type { + Ok(return_type.node) + } else { + Err(ValidationError::ExpectedFunction { + actual: function_node_type, + position: self.function.position(), + }) + } + } +} diff --git a/dust-lang/src/abstract_tree/if_else.rs b/dust-lang/src/abstract_tree/if_else.rs index 5064c92..7c7061f 100644 --- a/dust-lang/src/abstract_tree/if_else.rs +++ b/dust-lang/src/abstract_tree/if_else.rs @@ -6,21 +6,21 @@ use crate::{ value::ValueInner, }; -use super::{AbstractNode, Action, Block, Expression, Type, WithPosition}; +use super::{AbstractNode, Action, Block, ExpectedType, Type, ValueExpression, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct IfElse { - if_expression: Expression, + if_expression: ValueExpression, if_block: WithPosition, - else_ifs: Vec<(Expression, WithPosition)>, + else_ifs: Vec<(ValueExpression, WithPosition)>, else_block: Option>, } impl IfElse { pub fn new( - if_expression: Expression, + if_expression: ValueExpression, if_block: WithPosition, - else_ifs: Vec<(Expression, WithPosition)>, + else_ifs: Vec<(ValueExpression, WithPosition)>, else_block: Option>, ) -> Self { Self { @@ -33,29 +33,25 @@ impl IfElse { } impl AbstractNode for IfElse { - fn expected_type(&self, _context: &mut Context) -> Result { - self.if_block.item.expected_type(_context) - } - fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> { self.if_expression.validate(context, manage_memory)?; - self.if_block.item.validate(context, manage_memory)?; + self.if_block.node.validate(context, manage_memory)?; - let expected_type = self.if_block.item.expected_type(context)?; + let expected_type = self.if_block.node.expected_type(context)?; let if_expression_type = self.if_expression.expected_type(context)?; if let Type::Boolean = if_expression_type { if let Some(else_block) = &self.else_block { - else_block.item.validate(context, manage_memory)?; + else_block.node.validate(context, manage_memory)?; - let actual = else_block.item.expected_type(context)?; + let actual = else_block.node.expected_type(context)?; expected_type .check(&actual) .map_err(|conflict| ValidationError::TypeCheck { conflict, - actual_position: else_block.item.last_statement().position(), - expected_position: self.if_block.item.first_statement().position(), + actual_position: else_block.node.last_statement().position(), + expected_position: self.if_block.node.first_statement().position(), })?; } } else { @@ -69,15 +65,15 @@ impl AbstractNode for IfElse { let expression_type = expression.expected_type(context)?; if let Type::Boolean = expression_type { - block.item.validate(context, manage_memory)?; + block.node.validate(context, manage_memory)?; - let actual = block.item.expected_type(context)?; + let actual = block.node.expected_type(context)?; expected_type .check(&actual) .map_err(|conflict| ValidationError::TypeCheck { conflict, - actual_position: self.if_block.item.last_statement().position(), + actual_position: self.if_block.node.last_statement().position(), expected_position: self.if_expression.position(), })?; } else { @@ -104,7 +100,7 @@ impl AbstractNode for IfElse { if let ValueInner::Boolean(if_boolean) = value.inner().as_ref() { if *if_boolean { - self.if_block.item.run(context, _manage_memory) + self.if_block.node.run(context, _manage_memory) } else { for (expression, block) in self.else_ifs { let expression_position = expression.position(); @@ -119,7 +115,7 @@ impl AbstractNode for IfElse { if let ValueInner::Boolean(else_if_boolean) = value.inner().as_ref() { if *else_if_boolean { - return block.item.run(context, _manage_memory); + return block.node.run(context, _manage_memory); } } else { return Err(RuntimeError::ValidationFailure( @@ -132,7 +128,7 @@ impl AbstractNode for IfElse { } if let Some(else_statement) = self.else_block { - else_statement.item.run(context, _manage_memory) + else_statement.node.run(context, _manage_memory) } else { Ok(Action::None) } @@ -148,6 +144,12 @@ impl AbstractNode for IfElse { } } +impl ExpectedType for IfElse { + fn expected_type(&self, _context: &mut Context) -> Result { + self.if_block.node.expected_type(_context) + } +} + #[cfg(test)] mod tests { use crate::{ @@ -161,8 +163,8 @@ mod tests { fn simple_if() { assert_eq!( IfElse::new( - Expression::Value(ValueNode::Boolean(true).with_position((0, 0))), - Block::new(vec![Statement::Expression(Expression::Value( + ValueExpression::Value(ValueNode::Boolean(true).with_position((0, 0))), + Block::new(vec![Statement::ValueExpression(ValueExpression::Value( ValueNode::String("foo".to_string()).with_position((0, 0)) ))]) .with_position((0, 0)), diff --git a/dust-lang/src/abstract_tree/list_index.rs b/dust-lang/src/abstract_tree/list_index.rs index a1feb35..3bd731d 100644 --- a/dust-lang/src/abstract_tree/list_index.rs +++ b/dust-lang/src/abstract_tree/list_index.rs @@ -5,50 +5,21 @@ use crate::{ error::{RuntimeError, ValidationError}, }; -use super::{AbstractNode, Action, Expression, Type, ValueNode, WithPosition}; +use super::{AbstractNode, Action, ExpectedType, Type, ValueExpression, ValueNode, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct ListIndex { - left: Expression, - right: Expression, + left: ValueExpression, + right: ValueExpression, } impl ListIndex { - pub fn new(left: Expression, right: Expression) -> Self { + pub fn new(left: ValueExpression, right: ValueExpression) -> Self { Self { left, right } } } impl AbstractNode for ListIndex { - fn expected_type(&self, _context: &mut Context) -> Result { - let left_type = self.left.expected_type(_context)?; - - if let ( - Expression::Value(WithPosition { - item: ValueNode::List(expression_list), - .. - }), - Expression::Value(WithPosition { - item: ValueNode::Integer(index), - .. - }), - ) = (&self.left, &self.right) - { - let expression = if let Some(expression) = expression_list.get(*index as usize) { - expression - } else { - return Ok(Type::None); - }; - - expression.expected_type(_context) - } else { - Err(ValidationError::CannotIndex { - r#type: left_type, - position: self.left.position(), - }) - } - } - fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> { self.left.validate(context, _manage_memory)?; self.right.validate(context, _manage_memory)?; @@ -103,7 +74,7 @@ impl AbstractNode for ListIndex { let found_item = list.get(index as usize); if let Some(item) = found_item { - Ok(Action::Return(item.item.clone())) + Ok(Action::Return(item.node.clone())) } else { Ok(Action::None) } @@ -119,3 +90,34 @@ impl AbstractNode for ListIndex { } } } + +impl ExpectedType for ListIndex { + fn expected_type(&self, _context: &mut Context) -> Result { + let left_type = self.left.expected_type(_context)?; + + if let ( + ValueExpression::Value(WithPosition { + node: ValueNode::List(expression_list), + .. + }), + ValueExpression::Value(WithPosition { + node: ValueNode::Integer(index), + .. + }), + ) = (&self.left, &self.right) + { + let expression = if let Some(expression) = expression_list.get(*index as usize) { + expression + } else { + return Ok(Type::None); + }; + + expression.expected_type(_context) + } else { + Err(ValidationError::CannotIndex { + r#type: left_type, + position: self.left.position(), + }) + } + } +} diff --git a/dust-lang/src/abstract_tree/logic.rs b/dust-lang/src/abstract_tree/logic.rs index d88215b..39b9697 100644 --- a/dust-lang/src/abstract_tree/logic.rs +++ b/dust-lang/src/abstract_tree/logic.rs @@ -7,26 +7,22 @@ use crate::{ Value, }; -use super::{AbstractNode, Action, Expression, Type}; +use super::{AbstractNode, Action, ExpectedType, Type, ValueExpression}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub enum Logic { - Equal(Expression, Expression), - NotEqual(Expression, Expression), - Greater(Expression, Expression), - Less(Expression, Expression), - GreaterOrEqual(Expression, Expression), - LessOrEqual(Expression, Expression), - And(Expression, Expression), - Or(Expression, Expression), - Not(Expression), + Equal(ValueExpression, ValueExpression), + NotEqual(ValueExpression, ValueExpression), + Greater(ValueExpression, ValueExpression), + Less(ValueExpression, ValueExpression), + GreaterOrEqual(ValueExpression, ValueExpression), + LessOrEqual(ValueExpression, ValueExpression), + And(ValueExpression, ValueExpression), + Or(ValueExpression, ValueExpression), + Not(ValueExpression), } impl AbstractNode for Logic { - fn expected_type(&self, _context: &mut Context) -> Result { - Ok(Type::Boolean) - } - fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> { match self { Logic::Equal(left, right) @@ -94,7 +90,7 @@ impl AbstractNode for Logic { } fn run(self, context: &mut Context, _manage_memory: bool) -> Result { - let run_and_expect_value = |expression: Expression| -> Result { + let run_and_expect_value = |expression: ValueExpression| -> Result { let expression_position = expression.position(); let action = expression.run(&mut context.clone(), _manage_memory)?; let value = if let Action::Return(value) = action { @@ -108,7 +104,7 @@ impl AbstractNode for Logic { Ok(value) }; - let run_and_expect_boolean = |expression: Expression| -> Result { + let run_and_expect_boolean = |expression: ValueExpression| -> Result { let expression_position = expression.position(); let action = expression.run(&mut context.clone(), _manage_memory)?; let value = if let Action::Return(value) = action { @@ -195,6 +191,12 @@ impl AbstractNode for Logic { } } +impl ExpectedType for Logic { + fn expected_type(&self, _context: &mut Context) -> Result { + Ok(Type::Boolean) + } +} + #[cfg(test)] mod tests { use crate::abstract_tree::{ValueNode, WithPos}; @@ -205,8 +207,8 @@ mod tests { fn equal() { assert_eq!( Logic::Equal( - Expression::Value(ValueNode::Integer(42).with_position((0, 0))), - Expression::Value(ValueNode::Integer(42).with_position((0, 0))) + ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))), + ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))) ) .run(&mut Context::new(None), true), Ok(Action::Return(Value::boolean(true))) @@ -217,8 +219,8 @@ mod tests { fn not_equal() { assert_eq!( Logic::NotEqual( - Expression::Value(ValueNode::Integer(42).with_position((0, 0))), - Expression::Value(ValueNode::Integer(43).with_position((0, 0))) + ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))), + ValueExpression::Value(ValueNode::Integer(43).with_position((0, 0))) ) .run(&mut Context::new(None), true), Ok(Action::Return(Value::boolean(true))) @@ -229,8 +231,8 @@ mod tests { fn greater() { assert_eq!( Logic::Greater( - Expression::Value(ValueNode::Integer(43).with_position((0, 0))), - Expression::Value(ValueNode::Integer(42).with_position((0, 0))) + ValueExpression::Value(ValueNode::Integer(43).with_position((0, 0))), + ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))) ) .run(&mut Context::new(None), true), Ok(Action::Return(Value::boolean(true))) @@ -241,8 +243,8 @@ mod tests { fn less() { assert_eq!( Logic::Less( - Expression::Value(ValueNode::Integer(42).with_position((0, 0))), - Expression::Value(ValueNode::Integer(43).with_position((0, 0))) + ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))), + ValueExpression::Value(ValueNode::Integer(43).with_position((0, 0))) ) .run(&mut Context::new(None), true), Ok(Action::Return(Value::boolean(true))) @@ -253,8 +255,8 @@ mod tests { fn greater_or_equal() { assert_eq!( Logic::GreaterOrEqual( - Expression::Value(ValueNode::Integer(42).with_position((0, 0))), - Expression::Value(ValueNode::Integer(41).with_position((0, 0))) + ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))), + ValueExpression::Value(ValueNode::Integer(41).with_position((0, 0))) ) .run(&mut Context::new(None), true), Ok(Action::Return(Value::boolean(true))) @@ -262,8 +264,8 @@ mod tests { assert_eq!( Logic::GreaterOrEqual( - Expression::Value(ValueNode::Integer(42).with_position((0, 0))), - Expression::Value(ValueNode::Integer(42).with_position((0, 0))), + ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))), + ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))), ) .run(&mut Context::new(None), true), Ok(Action::Return(Value::boolean(true))) @@ -274,8 +276,8 @@ mod tests { fn less_or_equal() { assert_eq!( Logic::LessOrEqual( - Expression::Value(ValueNode::Integer(41).with_position((0, 0))), - Expression::Value(ValueNode::Integer(42).with_position((0, 0))), + ValueExpression::Value(ValueNode::Integer(41).with_position((0, 0))), + ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))), ) .run(&mut Context::new(None), true), Ok(Action::Return(Value::boolean(true))) @@ -283,8 +285,8 @@ mod tests { assert_eq!( Logic::LessOrEqual( - Expression::Value(ValueNode::Integer(42).with_position((0, 0))), - Expression::Value(ValueNode::Integer(42).with_position((0, 0))), + ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))), + ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))), ) .run(&mut Context::new(None), true), Ok(Action::Return(Value::boolean(true))) @@ -295,8 +297,8 @@ mod tests { fn and() { assert_eq!( Logic::And( - Expression::Value(ValueNode::Boolean(true).with_position((0, 0))), - Expression::Value(ValueNode::Boolean(true).with_position((0, 0))), + ValueExpression::Value(ValueNode::Boolean(true).with_position((0, 0))), + ValueExpression::Value(ValueNode::Boolean(true).with_position((0, 0))), ) .run(&mut Context::new(None), true), Ok(Action::Return(Value::boolean(true))) @@ -307,8 +309,8 @@ mod tests { fn or() { assert_eq!( Logic::Or( - Expression::Value(ValueNode::Boolean(true).with_position((0, 0))), - Expression::Value(ValueNode::Boolean(false).with_position((0, 0))), + ValueExpression::Value(ValueNode::Boolean(true).with_position((0, 0))), + ValueExpression::Value(ValueNode::Boolean(false).with_position((0, 0))), ) .run(&mut Context::new(None), true), Ok(Action::Return(Value::boolean(true))) @@ -318,7 +320,7 @@ mod tests { #[test] fn not() { assert_eq!( - Logic::Not(Expression::Value( + Logic::Not(ValueExpression::Value( ValueNode::Boolean(false).with_position((0, 0)) )) .run(&mut Context::new(None), true), diff --git a/dust-lang/src/abstract_tree/loop.rs b/dust-lang/src/abstract_tree/loop.rs index 69f750a..05652fa 100644 --- a/dust-lang/src/abstract_tree/loop.rs +++ b/dust-lang/src/abstract_tree/loop.rs @@ -5,7 +5,7 @@ use crate::{ error::{RuntimeError, ValidationError}, }; -use super::{AbstractNode, Action, Statement, Type}; +use super::{AbstractNode, Action, Statement}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct Loop { @@ -19,10 +19,6 @@ impl Loop { } impl AbstractNode for Loop { - fn expected_type(&self, _context: &mut Context) -> Result { - Ok(Type::None) - } - fn validate( &self, _context: &mut Context, diff --git a/dust-lang/src/abstract_tree/map_index.rs b/dust-lang/src/abstract_tree/map_index.rs index e4ee6c3..5d609b3 100644 --- a/dust-lang/src/abstract_tree/map_index.rs +++ b/dust-lang/src/abstract_tree/map_index.rs @@ -6,16 +6,16 @@ use crate::{ value::ValueInner, }; -use super::{AbstractNode, Action, Expression, Type, ValueNode, WithPosition}; +use super::{AbstractNode, Action, ExpectedType, Type, ValueExpression, ValueNode, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct MapIndex { - collection: Expression, - index: Expression, + collection: ValueExpression, + index: ValueExpression, } impl MapIndex { - pub fn new(left: Expression, right: Expression) -> Self { + pub fn new(left: ValueExpression, right: ValueExpression) -> Self { Self { collection: left, index: right, @@ -24,87 +24,6 @@ impl MapIndex { } impl AbstractNode for MapIndex { - fn expected_type(&self, context: &mut Context) -> Result { - if let (Expression::Identifier(collection), Expression::Identifier(index)) = - (&self.collection, &self.index) - { - let collection = if let Some(collection) = context.get_value(&collection.item)? { - collection - } else { - return Err(ValidationError::VariableNotFound { - identifier: collection.item.clone(), - position: collection.position, - }); - }; - - if let ValueInner::Map(map) = collection.inner().as_ref() { - return if let Some(value) = map.get(&index.item) { - Ok(value.r#type(context)?) - } else { - Err(ValidationError::PropertyNotFound { - identifier: index.item.clone(), - position: index.position, - }) - }; - }; - } - - if let ( - Expression::Value(WithPosition { - item: ValueNode::Map(properties), - .. - }), - Expression::Identifier(index), - ) = (&self.collection, &self.index) - { - return if let Some(type_result) = - properties - .iter() - .find_map(|(property, type_option, expression)| { - if property == &index.item { - if let Some(r#type) = type_option { - Some(r#type.item.expected_type(context)) - } else { - Some(expression.expected_type(context)) - } - } else { - None - } - }) - { - type_result - } else { - Ok(Type::None) - }; - } - - if let ( - Expression::Value(WithPosition { - item: ValueNode::Structure { fields, .. }, - .. - }), - Expression::Identifier(index), - ) = (&self.collection, &self.index) - { - return if let Some(type_result) = fields.iter().find_map(|(property, expression)| { - if property == &index.item { - Some(expression.expected_type(context)) - } else { - None - } - }) { - type_result - } else { - Ok(Type::None) - }; - } - - Err(ValidationError::CannotIndex { - r#type: self.collection.expected_type(context)?, - position: self.collection.position(), - }) - } - fn validate( &self, _context: &mut Context, @@ -124,11 +43,11 @@ impl AbstractNode for MapIndex { )); }; - if let (ValueInner::Map(map), Expression::Identifier(index)) = + if let (ValueInner::Map(map), ValueExpression::Identifier(index)) = (collection.inner().as_ref(), self.index) { let action = map - .get(&index.item) + .get(&index.node) .map(|value| Action::Return(value.clone())) .unwrap_or(Action::None); @@ -143,3 +62,78 @@ impl AbstractNode for MapIndex { } } } + +impl ExpectedType for MapIndex { + fn expected_type(&self, context: &mut Context) -> Result { + if let (ValueExpression::Identifier(collection), ValueExpression::Identifier(index)) = + (&self.collection, &self.index) + { + let collection = if let Some(collection) = context.get_value(&collection.node)? { + collection + } else { + return Err(ValidationError::VariableNotFound { + identifier: collection.node.clone(), + position: collection.position, + }); + }; + + if let ValueInner::Map(map) = collection.inner().as_ref() { + return if let Some(value) = map.get(&index.node) { + Ok(value.r#type(context)?) + } else { + Err(ValidationError::PropertyNotFound { + identifier: index.node.clone(), + position: index.position, + }) + }; + }; + } + + if let ( + ValueExpression::Value(WithPosition { + node: ValueNode::Map(properties), + .. + }), + ValueExpression::Identifier(index), + ) = (&self.collection, &self.index) + { + for (property, type_option, expression) in properties { + if property == &index.node { + return if let Some(r#type) = type_option { + Ok(r#type.node.clone()) + } else { + Ok(expression.expected_type(context)?) + }; + } + } + + return Ok(Type::None); + } + + if let ( + ValueExpression::Value(WithPosition { + node: ValueNode::Structure { fields, .. }, + .. + }), + ValueExpression::Identifier(index), + ) = (&self.collection, &self.index) + { + return if let Some(type_result) = fields.iter().find_map(|(property, expression)| { + if property == &index.node { + Some(expression.expected_type(context)) + } else { + None + } + }) { + type_result + } else { + Ok(Type::None) + }; + } + + Err(ValidationError::CannotIndex { + r#type: self.collection.expected_type(context)?, + position: self.collection.position(), + }) + } +} diff --git a/dust-lang/src/abstract_tree/math.rs b/dust-lang/src/abstract_tree/math.rs index ccb77a6..40189b9 100644 --- a/dust-lang/src/abstract_tree/math.rs +++ b/dust-lang/src/abstract_tree/math.rs @@ -7,41 +7,18 @@ use crate::{ Value, }; -use super::{AbstractNode, Action, Expression, SourcePosition, Type}; +use super::{AbstractNode, Action, ExpectedType, SourcePosition, Type, ValueExpression}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub enum Math { - Add(Expression, Expression), - Subtract(Expression, Expression), - Multiply(Expression, Expression), - Divide(Expression, Expression), - Modulo(Expression, Expression), + Add(ValueExpression, ValueExpression), + Subtract(ValueExpression, ValueExpression), + Multiply(ValueExpression, ValueExpression), + Divide(ValueExpression, ValueExpression), + Modulo(ValueExpression, ValueExpression), } impl AbstractNode for Math { - fn expected_type(&self, _context: &mut Context) -> Result { - match self { - Math::Add(left, right) - | Math::Subtract(left, right) - | Math::Multiply(left, right) - | Math::Divide(left, right) - | Math::Modulo(left, right) => { - let left_type = left.expected_type(_context)?; - let right_type = right.expected_type(_context)?; - - if let Type::Float = left_type { - return Ok(Type::Float); - } - - if let Type::Float = right_type { - return Ok(Type::Float); - } - - Ok(left_type) - } - } - } - fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> { match self { Math::Add(left, right) => { @@ -91,20 +68,21 @@ impl AbstractNode for Math { } fn run(self, _context: &mut Context, _clear_variables: bool) -> Result { - let run_and_expect_value = - |position: SourcePosition, expression: Expression| -> Result { - let action = expression.run(&mut _context.clone(), _clear_variables)?; - let value = if let Action::Return(value) = action { - value - } else { - return Err(RuntimeError::ValidationFailure( - ValidationError::InterpreterExpectedReturn(position), - )); - }; - - Ok(value) + let run_and_expect_value = |position: SourcePosition, + expression: ValueExpression| + -> Result { + let action = expression.run(&mut _context.clone(), _clear_variables)?; + let value = if let Action::Return(value) = action { + value + } else { + return Err(RuntimeError::ValidationFailure( + ValidationError::InterpreterExpectedReturn(position), + )); }; + Ok(value) + }; + let value = match self { Math::Add(left, right) => { let left_position = left.position(); @@ -313,3 +291,28 @@ impl AbstractNode for Math { Ok(Action::Return(value)) } } + +impl ExpectedType for Math { + fn expected_type(&self, _context: &mut Context) -> Result { + match self { + Math::Add(left, right) + | Math::Subtract(left, right) + | Math::Multiply(left, right) + | Math::Divide(left, right) + | Math::Modulo(left, right) => { + let left_type = left.expected_type(_context)?; + let right_type = right.expected_type(_context)?; + + if let Type::Float = left_type { + return Ok(Type::Float); + } + + if let Type::Float = right_type { + return Ok(Type::Float); + } + + Ok(left_type) + } + } + } +} diff --git a/dust-lang/src/abstract_tree/mod.rs b/dust-lang/src/abstract_tree/mod.rs index 3fdf33e..ce3c764 100644 --- a/dust-lang/src/abstract_tree/mod.rs +++ b/dust-lang/src/abstract_tree/mod.rs @@ -3,7 +3,6 @@ pub mod assignment; pub mod async_block; pub mod block; pub mod built_in_function_call; -pub mod expression; pub mod function_call; pub mod if_else; pub mod list_index; @@ -15,6 +14,7 @@ pub mod statement; pub mod structure_definition; pub mod r#type; pub mod type_alias; +pub mod value_expression; pub mod value_node; pub mod r#while; @@ -28,7 +28,6 @@ pub use self::{ async_block::AsyncBlock, block::Block, built_in_function_call::BuiltInFunctionCall, - expression::Expression, function_call::FunctionCall, if_else::IfElse, list_index::ListIndex, @@ -41,7 +40,8 @@ pub use self::{ r#while::While, statement::Statement, structure_definition::StructureDefinition, - type_alias::TypeAlias, + type_alias::TypeAssignment, + value_expression::ValueExpression, value_node::ValueNode, }; @@ -53,14 +53,14 @@ use crate::{ #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct WithPosition { - pub item: T, + pub node: T, pub position: SourcePosition, } pub trait WithPos: Sized { fn with_position>(self, span: T) -> WithPosition { WithPosition { - item: self, + node: self, position: span.into(), } } @@ -188,7 +188,10 @@ impl Index for AbstractTree { } pub trait AbstractNode: Sized { - fn expected_type(&self, context: &mut Context) -> Result; fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError>; fn run(self, context: &mut Context, manage_memory: bool) -> Result; } + +pub trait ExpectedType { + fn expected_type(&self, context: &mut Context) -> Result; +} diff --git a/dust-lang/src/abstract_tree/statement.rs b/dust-lang/src/abstract_tree/statement.rs index 1355acb..d1f929e 100644 --- a/dust-lang/src/abstract_tree/statement.rs +++ b/dust-lang/src/abstract_tree/statement.rs @@ -6,8 +6,9 @@ use crate::{ }; use super::{ - AbstractNode, Action, Assignment, AsyncBlock, Block, Expression, IfElse, Loop, SourcePosition, - StructureDefinition, Type, TypeAlias, While, WithPosition, + AbstractNode, Action, Assignment, AsyncBlock, Block, ExpectedType, IfElse, Loop, + SourcePosition, StructureDefinition, Type, TypeAssignment, ValueExpression, While, + WithPosition, }; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] @@ -16,11 +17,11 @@ pub enum Statement { AsyncBlock(WithPosition), Block(WithPosition), Break(WithPosition<()>), - Expression(Expression), IfElse(WithPosition), Loop(WithPosition), StructureDefinition(WithPosition), - TypeAlias(WithPosition), + TypeAssignment(WithPosition), + ValueExpression(ValueExpression), While(WithPosition), } @@ -31,71 +32,56 @@ impl Statement { Statement::AsyncBlock(inner) => inner.position, Statement::Block(inner) => inner.position, Statement::Break(inner) => inner.position, - Statement::Expression(expression) => expression.position(), + Statement::ValueExpression(expression) => expression.position(), Statement::IfElse(inner) => inner.position, Statement::Loop(inner) => inner.position, Statement::StructureDefinition(inner) => inner.position, - Statement::TypeAlias(inner) => inner.position, + Statement::TypeAssignment(inner) => inner.position, Statement::While(inner) => inner.position, } } } impl AbstractNode for Statement { - fn expected_type(&self, _context: &mut Context) -> Result { - match self { - Statement::Assignment(assignment) => assignment.item.expected_type(_context), - Statement::AsyncBlock(async_block) => async_block.item.expected_type(_context), - Statement::Block(block) => block.item.expected_type(_context), - Statement::Break(_) => Ok(Type::None), - Statement::Expression(expression) => expression.expected_type(_context), - Statement::IfElse(if_else) => if_else.item.expected_type(_context), - Statement::Loop(r#loop) => r#loop.item.expected_type(_context), - Statement::While(r#while) => r#while.item.expected_type(_context), - Statement::TypeAlias(type_alias) => type_alias.item.expected_type(_context), - Statement::StructureDefinition(structure_definition) => { - structure_definition.item.expected_type(_context) - } - } - } - fn validate( &self, _context: &mut Context, _manage_memory: bool, ) -> Result<(), ValidationError> { match self { - Statement::Assignment(assignment) => assignment.item.validate(_context, _manage_memory), + Statement::Assignment(assignment) => assignment.node.validate(_context, _manage_memory), Statement::AsyncBlock(async_block) => { - async_block.item.validate(_context, _manage_memory) + async_block.node.validate(_context, _manage_memory) } - Statement::Block(block) => block.item.validate(_context, _manage_memory), + Statement::Block(block) => block.node.validate(_context, _manage_memory), Statement::Break(_) => Ok(()), - Statement::Expression(expression) => expression.validate(_context, _manage_memory), - Statement::IfElse(if_else) => if_else.item.validate(_context, _manage_memory), - Statement::Loop(r#loop) => r#loop.item.validate(_context, _manage_memory), + Statement::ValueExpression(expression) => expression.validate(_context, _manage_memory), + Statement::IfElse(if_else) => if_else.node.validate(_context, _manage_memory), + Statement::Loop(r#loop) => r#loop.node.validate(_context, _manage_memory), Statement::StructureDefinition(structure_definition) => { - structure_definition.item.validate(_context, _manage_memory) + structure_definition.node.validate(_context, _manage_memory) } - Statement::TypeAlias(type_alias) => type_alias.item.validate(_context, _manage_memory), - Statement::While(r#while) => r#while.item.validate(_context, _manage_memory), + Statement::TypeAssignment(type_alias) => { + type_alias.node.validate(_context, _manage_memory) + } + Statement::While(r#while) => r#while.node.validate(_context, _manage_memory), } } fn run(self, context: &mut Context, manage_memory: bool) -> Result { let result = match self { - Statement::Assignment(assignment) => assignment.item.run(context, manage_memory), - Statement::AsyncBlock(async_block) => async_block.item.run(context, manage_memory), - Statement::Block(block) => block.item.run(context, manage_memory), + Statement::Assignment(assignment) => assignment.node.run(context, manage_memory), + Statement::AsyncBlock(async_block) => async_block.node.run(context, manage_memory), + Statement::Block(block) => block.node.run(context, manage_memory), Statement::Break(_) => Ok(Action::Break), - Statement::Expression(expression) => expression.run(context, manage_memory), - Statement::IfElse(if_else) => if_else.item.run(context, manage_memory), - Statement::Loop(r#loop) => r#loop.item.run(context, manage_memory), + Statement::ValueExpression(expression) => expression.run(context, manage_memory), + Statement::IfElse(if_else) => if_else.node.run(context, manage_memory), + Statement::Loop(r#loop) => r#loop.node.run(context, manage_memory), Statement::StructureDefinition(structure_definition) => { - structure_definition.item.run(context, manage_memory) + structure_definition.node.run(context, manage_memory) } - Statement::TypeAlias(type_alias) => type_alias.item.run(context, manage_memory), - Statement::While(r#while) => r#while.item.run(context, manage_memory), + Statement::TypeAssignment(type_alias) => type_alias.node.run(context, manage_memory), + Statement::While(r#while) => r#while.node.run(context, manage_memory), }; if manage_memory { @@ -105,3 +91,15 @@ impl AbstractNode for Statement { result } } + +impl ExpectedType for Statement { + fn expected_type(&self, _context: &mut Context) -> Result { + match self { + Statement::ValueExpression(expression) => expression.expected_type(_context), + Statement::IfElse(if_else) => if_else.node.expected_type(_context), + Statement::Block(block) => block.node.expected_type(_context), + Statement::AsyncBlock(async_block) => async_block.node.expected_type(_context), + _ => Ok(Type::None), + } + } +} diff --git a/dust-lang/src/abstract_tree/structure_definition.rs b/dust-lang/src/abstract_tree/structure_definition.rs index 2c2629c..8fe1b70 100644 --- a/dust-lang/src/abstract_tree/structure_definition.rs +++ b/dust-lang/src/abstract_tree/structure_definition.rs @@ -21,10 +21,6 @@ impl StructureDefinition { } impl AbstractNode for StructureDefinition { - fn expected_type(&self, _context: &mut Context) -> Result { - Ok(Type::None) - } - fn validate( &self, _context: &mut Context, diff --git a/dust-lang/src/abstract_tree/type.rs b/dust-lang/src/abstract_tree/type.rs index e737ea3..c80dde8 100644 --- a/dust-lang/src/abstract_tree/type.rs +++ b/dust-lang/src/abstract_tree/type.rs @@ -58,27 +58,27 @@ impl Type { } } (Type::ListOf(left), Type::ListOf(right)) => { - if let Ok(()) = left.item.check(&right.item) { + if let Ok(()) = left.node.check(&right.node) { return Ok(()); } } (Type::ListOf(list_of), Type::ListExact(list_exact)) => { for r#type in list_exact { - list_of.item.check(&r#type.item)?; + list_of.node.check(&r#type.node)?; } return Ok(()); } (Type::ListExact(list_exact), Type::ListOf(list_of)) => { for r#type in list_exact { - r#type.item.check(&list_of.item)?; + r#type.node.check(&list_of.node)?; } return Ok(()); } (Type::ListExact(left), Type::ListExact(right)) => { for (left, right) in left.iter().zip(right.iter()) { - left.item.check(&right.item)?; + left.node.check(&right.node)?; } return Ok(()); @@ -97,7 +97,7 @@ impl Type { for ((left_field_name, left_type), (right_field_name, right_type)) in left_fields.iter().zip(right_fields.iter()) { - if left_field_name != right_field_name || left_type.item != right_type.item + if left_field_name != right_field_name || left_type.node != right_type.node { return Err(TypeConflict { actual: other.clone(), @@ -119,11 +119,11 @@ impl Type { return_type: right_return, }, ) => { - if left_return.item == right_return.item { + if left_return.node == right_return.node { for (left_parameter, right_parameter) in left_parameters.iter().zip(right_parameters.iter()) { - if left_parameter.item != right_parameter.item { + if left_parameter.node != right_parameter.node { return Err(TypeConflict { actual: other.clone(), expected: self.clone(), @@ -145,10 +145,6 @@ impl Type { } impl AbstractNode for Type { - fn expected_type(&self, _: &mut Context) -> Result { - Ok(Type::None) - } - fn validate( &self, _context: &mut Context, @@ -170,15 +166,15 @@ impl Display for Type { Type::Float => write!(f, "float"), Type::Integer => write!(f, "int"), Type::List => write!(f, "list"), - Type::ListOf(item_type) => write!(f, "list({})", item_type.item), + Type::ListOf(item_type) => write!(f, "list({})", item_type.node), Type::ListExact(item_types) => { write!(f, "[")?; for (index, item_type) in item_types.into_iter().enumerate() { if index == item_types.len() - 1 { - write!(f, "{}", item_type.item)?; + write!(f, "{}", item_type.node)?; } else { - write!(f, "{}, ", item_type.item)?; + write!(f, "{}, ", item_type.node)?; } } @@ -195,10 +191,10 @@ impl Display for Type { write!(f, "(")?; for r#type in parameter_types { - write!(f, "{} ", r#type.item)?; + write!(f, "{} ", r#type.node)?; } - write!(f, ") : {}", return_type.item) + write!(f, ") : {}", return_type.node) } Type::Structure { name, .. } => write!(f, "{name}"), Type::Argument(identifier) => write!(f, "{identifier}"), diff --git a/dust-lang/src/abstract_tree/type_alias.rs b/dust-lang/src/abstract_tree/type_alias.rs index 10874c6..606e060 100644 --- a/dust-lang/src/abstract_tree/type_alias.rs +++ b/dust-lang/src/abstract_tree/type_alias.rs @@ -9,22 +9,18 @@ use crate::{ use super::{AbstractNode, Action, Type, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] -pub struct TypeAlias { +pub struct TypeAssignment { identifier: WithPosition, r#type: WithPosition, } -impl TypeAlias { +impl TypeAssignment { pub fn new(identifier: WithPosition, r#type: WithPosition) -> Self { Self { identifier, r#type } } } -impl AbstractNode for TypeAlias { - fn expected_type(&self, _context: &mut Context) -> Result { - Ok(Type::None) - } - +impl AbstractNode for TypeAssignment { fn validate( &self, _context: &mut Context, @@ -34,7 +30,7 @@ impl AbstractNode for TypeAlias { } fn run(self, context: &mut Context, _manage_memory: bool) -> Result { - context.set_type(self.identifier.item, self.r#type.item)?; + context.set_type(self.identifier.node, self.r#type.node)?; Ok(Action::None) } diff --git a/dust-lang/src/abstract_tree/value_expression.rs b/dust-lang/src/abstract_tree/value_expression.rs new file mode 100644 index 0000000..4f3b076 --- /dev/null +++ b/dust-lang/src/abstract_tree/value_expression.rs @@ -0,0 +1,142 @@ +use serde::{Deserialize, Serialize}; + +use crate::{ + context::Context, + error::{RuntimeError, ValidationError}, + identifier::Identifier, +}; + +use super::{ + AbstractNode, Action, As, BuiltInFunctionCall, ExpectedType, FunctionCall, ListIndex, Logic, + MapIndex, Math, SourcePosition, Type, ValueNode, WithPosition, +}; + +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub enum ValueExpression { + As(WithPosition>), + BuiltInFunctionCall(WithPosition>), + FunctionCall(WithPosition), + Identifier(WithPosition), + MapIndex(WithPosition>), + ListIndex(WithPosition>), + Logic(WithPosition>), + Math(WithPosition>), + Value(WithPosition), +} + +impl ValueExpression { + pub fn position(&self) -> SourcePosition { + match self { + ValueExpression::As(inner) => inner.position, + ValueExpression::FunctionCall(inner) => inner.position, + ValueExpression::Identifier(inner) => inner.position, + ValueExpression::MapIndex(inner) => inner.position, + ValueExpression::ListIndex(inner) => inner.position, + ValueExpression::Logic(inner) => inner.position, + ValueExpression::Math(inner) => inner.position, + ValueExpression::Value(inner) => inner.position, + ValueExpression::BuiltInFunctionCall(inner) => inner.position, + } + } +} + +impl AbstractNode for ValueExpression { + fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> { + match self { + ValueExpression::As(r#as) => r#as.node.validate(context, manage_memory), + ValueExpression::FunctionCall(function_call) => { + function_call.node.validate(context, manage_memory) + } + ValueExpression::Identifier(identifier) => { + let found = if manage_memory { + context.add_expected_use(&identifier.node)? + } else { + context.contains(&identifier.node)? + }; + + if found { + Ok(()) + } else { + Err(ValidationError::VariableNotFound { + identifier: identifier.node.clone(), + position: identifier.position, + }) + } + } + ValueExpression::MapIndex(map_index) => map_index.node.validate(context, manage_memory), + ValueExpression::ListIndex(list_index) => { + list_index.node.validate(context, manage_memory) + } + ValueExpression::Logic(logic) => logic.node.validate(context, manage_memory), + ValueExpression::Math(math) => math.node.validate(context, manage_memory), + ValueExpression::Value(value_node) => value_node.node.validate(context, manage_memory), + ValueExpression::BuiltInFunctionCall(built_in_function_call) => { + built_in_function_call.node.validate(context, manage_memory) + } + } + } + + fn run(self, context: &mut Context, manage_memory: bool) -> Result { + match self { + ValueExpression::As(r#as) => r#as.node.run(context, manage_memory), + ValueExpression::FunctionCall(function_call) => { + function_call.node.run(context, manage_memory) + } + ValueExpression::Identifier(identifier) => { + let value_option = if manage_memory { + context.use_value(&identifier.node)? + } else { + context.get_value(&identifier.node)? + }; + + if let Some(value) = value_option { + Ok(Action::Return(value)) + } else { + Err(RuntimeError::ValidationFailure( + ValidationError::VariableNotFound { + identifier: identifier.node.clone(), + position: identifier.position, + }, + )) + } + } + ValueExpression::MapIndex(map_index) => map_index.node.run(context, manage_memory), + ValueExpression::ListIndex(list_index) => list_index.node.run(context, manage_memory), + ValueExpression::Logic(logic) => logic.node.run(context, manage_memory), + ValueExpression::Math(math) => math.node.run(context, manage_memory), + ValueExpression::Value(value_node) => value_node.node.run(context, manage_memory), + ValueExpression::BuiltInFunctionCall(built_in_function_call) => { + built_in_function_call.node.run(context, manage_memory) + } + } + } +} + +impl ExpectedType for ValueExpression { + fn expected_type(&self, _context: &mut Context) -> Result { + match self { + ValueExpression::As(r#as) => r#as.node.expected_type(_context), + ValueExpression::FunctionCall(function_call) => { + function_call.node.expected_type(_context) + } + ValueExpression::Identifier(identifier) => { + if let Some(r#type) = _context.get_type(&identifier.node)? { + Ok(r#type) + } else { + Err(ValidationError::VariableNotFound { + identifier: identifier.node.clone(), + position: identifier.position, + }) + } + } + ValueExpression::MapIndex(map_index) => map_index.node.expected_type(_context), + ValueExpression::ListIndex(list_index) => list_index.node.expected_type(_context), + ValueExpression::Logic(logic) => logic.node.expected_type(_context), + ValueExpression::Math(math) => math.node.expected_type(_context), + ValueExpression::Value(value_node) => value_node.node.expected_type(_context), + ValueExpression::BuiltInFunctionCall(built_in_function_call) => { + built_in_function_call.node.expected_type(_context) + } + } + } +} diff --git a/dust-lang/src/abstract_tree/value_node.rs b/dust-lang/src/abstract_tree/value_node.rs index eef0896..8bbdd6a 100644 --- a/dust-lang/src/abstract_tree/value_node.rs +++ b/dust-lang/src/abstract_tree/value_node.rs @@ -9,20 +9,22 @@ use crate::{ Value, }; -use super::{AbstractNode, Action, Block, Expression, Type, WithPos, WithPosition}; +use super::{ + AbstractNode, Action, Block, ExpectedType, Type, ValueExpression, WithPos, WithPosition, +}; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub enum ValueNode { Boolean(bool), Float(f64), Integer(i64), - List(Vec), - Map(Vec<(Identifier, Option>, Expression)>), + List(Vec), + Map(Vec<(Identifier, Option>, ValueExpression)>), Range(Range), String(String), Structure { name: WithPosition, - fields: Vec<(Identifier, Expression)>, + fields: Vec<(Identifier, ValueExpression)>, }, ParsedFunction { type_arguments: Vec>, @@ -33,66 +35,6 @@ pub enum ValueNode { } impl AbstractNode for ValueNode { - fn expected_type(&self, context: &mut Context) -> Result { - let r#type = match self { - ValueNode::Boolean(_) => Type::Boolean, - ValueNode::Float(_) => Type::Float, - ValueNode::Integer(_) => Type::Integer, - ValueNode::List(items) => { - let mut item_types = Vec::with_capacity(items.len()); - - for expression in items { - item_types.push( - expression - .expected_type(context)? - .with_position(expression.position()), - ); - } - - Type::ListExact(item_types) - } - ValueNode::Map(_) => Type::Map, - ValueNode::Range(_) => Type::Range, - ValueNode::String(_) => Type::String, - ValueNode::ParsedFunction { - parameters, - return_type, - .. - } => Type::Function { - parameter_types: parameters - .iter() - .map(|(_, r#type)| r#type.clone()) - .collect(), - return_type: Box::new(return_type.clone()), - }, - ValueNode::Structure { - name, - fields: expressions, - } => { - let mut types = Vec::with_capacity(expressions.len()); - - for (identifier, expression) in expressions { - let r#type = expression.expected_type(context)?; - - types.push(( - identifier.clone(), - WithPosition { - item: r#type, - position: expression.position(), - }, - )); - } - - Type::Structure { - name: name.item.clone(), - fields: types, - } - } - }; - - Ok(r#type) - } - fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> { if let ValueNode::Map(map_assignments) = self { for (_identifier, r#type, expression) in map_assignments { @@ -101,7 +43,7 @@ impl AbstractNode for ValueNode { if let Some(expected_type) = r#type { let actual_type = expression.expected_type(context)?; - expected_type.item.check(&actual_type).map_err(|conflict| { + expected_type.node.check(&actual_type).map_err(|conflict| { ValidationError::TypeCheck { conflict, actual_position: expression.position(), @@ -124,21 +66,21 @@ impl AbstractNode for ValueNode { let mut function_context = Context::new(Some(&context)); for r#type in type_arguments { - if let Type::Argument(identifier) = &r#type.item { - function_context.set_type(identifier.clone(), r#type.item.clone())?; + if let Type::Argument(identifier) = &r#type.node { + function_context.set_type(identifier.clone(), r#type.node.clone())?; } } for (identifier, r#type) in parameters { - function_context.set_type(identifier.clone(), r#type.item.clone())?; + function_context.set_type(identifier.clone(), r#type.node.clone())?; } - body.item.validate(&mut function_context, _manage_memory)?; + body.node.validate(&mut function_context, _manage_memory)?; - let actual_return_type = body.item.expected_type(&mut function_context)?; + let actual_return_type = body.node.expected_type(&mut function_context)?; return_type - .item + .node .check(&actual_return_type) .map_err(|conflict| ValidationError::TypeCheck { conflict, @@ -154,9 +96,9 @@ impl AbstractNode for ValueNode { fields: expressions, } = self { - if !context.contains(&name.item)? { + if !context.contains(&name.node)? { return Err(ValidationError::VariableNotFound { - identifier: name.item.clone(), + identifier: name.node.clone(), position: name.position, }); } @@ -164,12 +106,12 @@ impl AbstractNode for ValueNode { if let Some(Type::Structure { name: _, fields: types, - }) = context.get_type(&name.item)? + }) = context.get_type(&name.node)? { for ((_, expression), (_, expected_type)) in expressions.iter().zip(types.iter()) { let actual_type = expression.expected_type(context)?; - expected_type.item.check(&actual_type).map_err(|conflict| { + expected_type.node.check(&actual_type).map_err(|conflict| { ValidationError::TypeCheck { conflict, actual_position: expression.position(), @@ -196,7 +138,7 @@ impl AbstractNode for ValueNode { let action = expression.run(_context, _manage_memory)?; let value = if let Action::Return(value) = action { WithPosition { - item: value, + node: value, position: expression_position, } } else { @@ -357,3 +299,65 @@ impl Ord for ValueNode { } } } + +impl ExpectedType for ValueNode { + fn expected_type(&self, context: &mut Context) -> Result { + let r#type = match self { + ValueNode::Boolean(_) => Type::Boolean, + ValueNode::Float(_) => Type::Float, + ValueNode::Integer(_) => Type::Integer, + ValueNode::List(items) => { + let mut item_types = Vec::with_capacity(items.len()); + + for expression in items { + item_types.push( + expression + .expected_type(context)? + .with_position(expression.position()), + ); + } + + Type::ListExact(item_types) + } + ValueNode::Map(_) => Type::Map, + ValueNode::Range(_) => Type::Range, + ValueNode::String(_) => Type::String, + ValueNode::ParsedFunction { + parameters, + return_type, + .. + } => Type::Function { + parameter_types: parameters + .iter() + .map(|(_, r#type)| r#type.clone()) + .collect(), + return_type: Box::new(return_type.clone()), + }, + ValueNode::Structure { + name, + fields: expressions, + } => { + let mut types = Vec::with_capacity(expressions.len()); + + for (identifier, expression) in expressions { + let r#type = expression.expected_type(context)?; + + types.push(( + identifier.clone(), + WithPosition { + node: r#type, + position: expression.position(), + }, + )); + } + + Type::Structure { + name: name.node.clone(), + fields: types, + } + } + }; + + Ok(r#type) + } +} diff --git a/dust-lang/src/abstract_tree/while.rs b/dust-lang/src/abstract_tree/while.rs index 439c631..8236332 100644 --- a/dust-lang/src/abstract_tree/while.rs +++ b/dust-lang/src/abstract_tree/while.rs @@ -7,16 +7,16 @@ use crate::{ Value, }; -use super::{AbstractNode, Action, Expression, Statement, Type}; +use super::{AbstractNode, Action, Statement, ValueExpression}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct While { - expression: Expression, + expression: ValueExpression, statements: Vec, } impl While { - pub fn new(expression: Expression, statements: Vec) -> Self { + pub fn new(expression: ValueExpression, statements: Vec) -> Self { Self { expression, statements, @@ -25,10 +25,6 @@ impl While { } impl AbstractNode for While { - fn expected_type(&self, _context: &mut Context) -> Result { - Ok(Type::None) - } - fn validate( &self, _context: &mut Context, diff --git a/dust-lang/src/lib.rs b/dust-lang/src/lib.rs index 22a01ed..fff73d9 100644 --- a/dust-lang/src/lib.rs +++ b/dust-lang/src/lib.rs @@ -403,7 +403,7 @@ impl InterpreterError { .with_message(format!("This has type {}.", actual.fg(type_color),)), ) } - ValidationError::ExpectedString { actual, position } => todo!(), + ValidationError::ExpectedString { .. } => todo!(), } } let report = builder.finish(); diff --git a/dust-lang/src/parser.rs b/dust-lang/src/parser.rs index 8635478..1102220 100644 --- a/dust-lang/src/parser.rs +++ b/dust-lang/src/parser.rs @@ -62,7 +62,7 @@ pub fn parser<'src>( Token::Integer(integer) => ValueNode::Integer(integer), Token::String(text) => ValueNode::String(text.to_string()), } - .map_with(|value, state| Expression::Value(value.with_position(state.span()))); + .map_with(|value, state| ValueExpression::Value(value.with_position(state.span()))); let r#type = recursive(|r#type| { let function_type = just(Token::Keyword(Keyword::Fn)) @@ -161,6 +161,7 @@ pub fn parser<'src>( let block = statement .clone() .repeated() + .at_least(1) .collect() .delimited_by( just(Token::Control(Control::CurlyOpen)), @@ -172,7 +173,7 @@ pub fn parser<'src>( let allow_built_ins = allow_built_ins.clone(); let identifier_expression = identifier.clone().map_with(|identifier, state| { - Expression::Identifier(identifier.with_position(state.span())) + ValueExpression::Identifier(identifier.with_position(state.span())) }); let raw_integer = select! { @@ -184,7 +185,7 @@ pub fn parser<'src>( .then_ignore(just(Token::Control(Control::DoubleDot))) .then(raw_integer) .map_with(|(start, end), state| { - Expression::Value(ValueNode::Range(start..end).with_position(state.span())) + ValueExpression::Value(ValueNode::Range(start..end).with_position(state.span())) }); let list = expression @@ -197,7 +198,7 @@ pub fn parser<'src>( just(Token::Control(Control::SquareClose)), ) .map_with(|list, state| { - Expression::Value(ValueNode::List(list).with_position(state.span())) + ValueExpression::Value(ValueNode::List(list).with_position(state.span())) }); let map_assignment = identifier @@ -216,7 +217,7 @@ pub fn parser<'src>( just(Token::Control(Control::CurlyClose)), ) .map_with(|map_assigment_list, state| { - Expression::Value( + ValueExpression::Value( ValueNode::Map(map_assigment_list).with_position(state.span()), ) }); @@ -249,7 +250,7 @@ pub fn parser<'src>( ) .map_with( |(type_arguments, ((parameters, return_type), body)), state| { - Expression::Value( + ValueExpression::Value( ValueNode::ParsedFunction { type_arguments: type_arguments .unwrap_or_else(|| Vec::with_capacity(0)), @@ -266,7 +267,7 @@ pub fn parser<'src>( just(Token::Keyword(Keyword::Length)) .ignore_then(expression.clone()) .map_with(|argument, state| { - Expression::BuiltInFunctionCall( + ValueExpression::BuiltInFunctionCall( Box::new(BuiltInFunctionCall::Length(argument)) .with_position(state.span()), ) @@ -274,20 +275,20 @@ pub fn parser<'src>( just(Token::Keyword(Keyword::ReadFile)) .ignore_then(expression.clone()) .map_with(|argument, state| { - Expression::BuiltInFunctionCall( + ValueExpression::BuiltInFunctionCall( Box::new(BuiltInFunctionCall::ReadFile(argument)) .with_position(state.span()), ) }), just(Token::Keyword(Keyword::ReadLine)).map_with(|_, state| { - Expression::BuiltInFunctionCall( + ValueExpression::BuiltInFunctionCall( Box::new(BuiltInFunctionCall::ReadLine).with_position(state.span()), ) }), just(Token::Keyword(Keyword::Sleep)) .ignore_then(expression.clone()) .map_with(|argument, state| { - Expression::BuiltInFunctionCall( + ValueExpression::BuiltInFunctionCall( Box::new(BuiltInFunctionCall::Sleep(argument)) .with_position(state.span()), ) @@ -295,7 +296,7 @@ pub fn parser<'src>( just(Token::Keyword(Keyword::WriteLine)) .ignore_then(expression.clone()) .map_with(|argument, state| { - Expression::BuiltInFunctionCall( + ValueExpression::BuiltInFunctionCall( Box::new(BuiltInFunctionCall::WriteLine(argument)) .with_position(state.span()), ) @@ -304,7 +305,7 @@ pub fn parser<'src>( .ignore_then(r#type.clone()) .then(expression.clone()) .map_with(|(r#type, argument), state| { - Expression::BuiltInFunctionCall( + ValueExpression::BuiltInFunctionCall( Box::new(BuiltInFunctionCall::JsonParse(r#type, argument)) .with_position(state.span()), ) @@ -339,7 +340,7 @@ pub fn parser<'src>( ), ) .map_with(|(name, fields), state| { - Expression::Value( + ValueExpression::Value( ValueNode::Structure { name, fields }.with_position(state.span()), ) }); @@ -377,7 +378,7 @@ pub fn parser<'src>( 2, just(Token::Operator(Operator::Not)), |_, expression, span| { - Expression::Logic(Box::new(Logic::Not(expression)).with_position(span)) + ValueExpression::Logic(Box::new(Logic::Not(expression)).with_position(span)) }, ), postfix( @@ -387,7 +388,7 @@ pub fn parser<'src>( just(Token::Control(Control::SquareClose)), ), |left, right, span| { - Expression::ListIndex( + ValueExpression::ListIndex( Box::new(ListIndex::new(left, right)).with_position(span), ) }, @@ -395,8 +396,8 @@ pub fn parser<'src>( infix( left(4), just(Token::Control(Control::Dot)), - |left: Expression, _: Token, right: Expression, span| { - Expression::MapIndex( + |left: ValueExpression, _: Token, right: ValueExpression, span| { + ValueExpression::MapIndex( Box::new(MapIndex::new(left, right)).with_position(span), ) }, @@ -416,10 +417,10 @@ pub fn parser<'src>( |function_expression, (type_arguments, arguments): ( Option>>, - Vec, + Vec, ), span| { - Expression::FunctionCall( + ValueExpression::FunctionCall( FunctionCall::new( function_expression, type_arguments.unwrap_or_else(|| Vec::with_capacity(0)), @@ -433,14 +434,16 @@ pub fn parser<'src>( left(1), just(Token::Operator(Operator::Equal)), |left, _, right, span| { - Expression::Logic(Box::new(Logic::Equal(left, right)).with_position(span)) + ValueExpression::Logic( + Box::new(Logic::Equal(left, right)).with_position(span), + ) }, ), infix( left(1), just(Token::Operator(Operator::NotEqual)), |left, _, right, span| { - Expression::Logic( + ValueExpression::Logic( Box::new(Logic::NotEqual(left, right)).with_position(span), ) }, @@ -449,21 +452,25 @@ pub fn parser<'src>( left(1), just(Token::Operator(Operator::Greater)), |left, _, right, span| { - Expression::Logic(Box::new(Logic::Greater(left, right)).with_position(span)) + ValueExpression::Logic( + Box::new(Logic::Greater(left, right)).with_position(span), + ) }, ), infix( left(1), just(Token::Operator(Operator::Less)), |left, _, right, span| { - Expression::Logic(Box::new(Logic::Less(left, right)).with_position(span)) + ValueExpression::Logic( + Box::new(Logic::Less(left, right)).with_position(span), + ) }, ), infix( left(1), just(Token::Operator(Operator::GreaterOrEqual)), |left, _, right, span| { - Expression::Logic( + ValueExpression::Logic( Box::new(Logic::GreaterOrEqual(left, right)).with_position(span), ) }, @@ -472,7 +479,7 @@ pub fn parser<'src>( left(1), just(Token::Operator(Operator::LessOrEqual)), |left, _, right, span| { - Expression::Logic( + ValueExpression::Logic( Box::new(Logic::LessOrEqual(left, right)).with_position(span), ) }, @@ -481,56 +488,68 @@ pub fn parser<'src>( left(1), just(Token::Operator(Operator::And)), |left, _, right, span| { - Expression::Logic(Box::new(Logic::And(left, right)).with_position(span)) + ValueExpression::Logic( + Box::new(Logic::And(left, right)).with_position(span), + ) }, ), infix( left(1), just(Token::Operator(Operator::Or)), |left, _, right, span| { - Expression::Logic(Box::new(Logic::Or(left, right)).with_position(span)) + ValueExpression::Logic(Box::new(Logic::Or(left, right)).with_position(span)) }, ), infix( left(1), just(Token::Operator(Operator::Add)), |left, _, right, span| { - Expression::Math(Box::new(Math::Add(left, right)).with_position(span)) + ValueExpression::Math(Box::new(Math::Add(left, right)).with_position(span)) }, ), infix( left(1), just(Token::Operator(Operator::Subtract)), |left, _, right, span| { - Expression::Math(Box::new(Math::Subtract(left, right)).with_position(span)) + ValueExpression::Math( + Box::new(Math::Subtract(left, right)).with_position(span), + ) }, ), infix( left(2), just(Token::Operator(Operator::Multiply)), |left, _, right, span| { - Expression::Math(Box::new(Math::Multiply(left, right)).with_position(span)) + ValueExpression::Math( + Box::new(Math::Multiply(left, right)).with_position(span), + ) }, ), infix( left(2), just(Token::Operator(Operator::Divide)), |left, _, right, span| { - Expression::Math(Box::new(Math::Divide(left, right)).with_position(span)) + ValueExpression::Math( + Box::new(Math::Divide(left, right)).with_position(span), + ) }, ), infix( left(1), just(Token::Operator(Operator::Modulo)), |left, _, right, span| { - Expression::Math(Box::new(Math::Modulo(left, right)).with_position(span)) + ValueExpression::Math( + Box::new(Math::Modulo(left, right)).with_position(span), + ) }, ), postfix( 2, just(Token::Keyword(Keyword::As)).ignore_then(r#type.clone()), |expression, r#type, span| { - Expression::As(Box::new(As::new(expression, r#type)).with_position(span)) + ValueExpression::As( + Box::new(As::new(expression, r#type)).with_position(span), + ) }, ), )); @@ -550,7 +569,7 @@ pub fn parser<'src>( let expression_statement = expression .clone() - .map(|expression| Statement::Expression(expression)); + .map(|expression| Statement::ValueExpression(expression)); let async_block = just(Token::Keyword(Keyword::Async)) .ignore_then(statement.clone().repeated().collect().delimited_by( @@ -635,7 +654,9 @@ pub fn parser<'src>( .then_ignore(just(Token::Operator(Operator::Assign))) .then(r#type.clone()) .map_with(|(identifier, r#type), state| { - Statement::TypeAlias(TypeAlias::new(identifier, r#type).with_position(state.span())) + Statement::TypeAssignment( + TypeAssignment::new(identifier, r#type).with_position(state.span()), + ) }); choice(( @@ -672,8 +693,8 @@ mod tests { fn type_alias() { assert_eq!( parse(&lex("type MyType = str").unwrap()).unwrap()[0], - Statement::TypeAlias( - TypeAlias::new( + Statement::TypeAssignment( + TypeAssignment::new( Identifier::new("MyType").with_position((5, 11)), Type::String.with_position((14, 17)) ) @@ -686,9 +707,9 @@ mod tests { fn r#as() { assert_eq!( parse(&lex("1 as str").unwrap()).unwrap()[0], - Statement::Expression(Expression::As( + Statement::ValueExpression(ValueExpression::As( Box::new(As::new( - Expression::Value(ValueNode::Integer(1).with_position((0, 1))), + ValueExpression::Value(ValueNode::Integer(1).with_position((0, 1))), Type::String.with_position((5, 8)) )) .with_position((0, 8)) @@ -712,7 +733,7 @@ mod tests { assert_eq!( statements[0], - Statement::Expression(Expression::BuiltInFunctionCall( + Statement::ValueExpression(ValueExpression::BuiltInFunctionCall( Box::new(BuiltInFunctionCall::ReadLine).with_position((0, 9)) )) ); @@ -731,8 +752,8 @@ mod tests { assert_eq!( statements[0], - Statement::Expression(Expression::BuiltInFunctionCall( - Box::new(BuiltInFunctionCall::WriteLine(Expression::Value( + Statement::ValueExpression(ValueExpression::BuiltInFunctionCall( + Box::new(BuiltInFunctionCall::WriteLine(ValueExpression::Value( ValueNode::String("hiya".to_string()).with_position((11, 17)) ))) .with_position((0, 17)) @@ -756,13 +777,13 @@ mod tests { .unwrap()[0], Statement::AsyncBlock( AsyncBlock::new(vec![ - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Integer(1).with_position((53, 54)) )), - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Integer(2).with_position((79, 80)) )), - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Integer(3).with_position((105, 106)) )), ]) @@ -784,17 +805,17 @@ mod tests { .unwrap() ) .unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Structure { name: Identifier::new("Foo").with_position((21, 24)), fields: vec![ ( Identifier::new("bar"), - Expression::Value(ValueNode::Integer(42).with_position((57, 59))) + ValueExpression::Value(ValueNode::Integer(42).with_position((57, 59))) ), ( Identifier::new("baz"), - Expression::Value( + ValueExpression::Value( ValueNode::String("hiya".to_string()).with_position((91, 97)) ) ), @@ -841,27 +862,27 @@ mod tests { fn map_index() { assert_eq!( parse(&lex("{ x = 42 }.x").unwrap()).unwrap()[0], - Statement::Expression(Expression::MapIndex( + Statement::ValueExpression(ValueExpression::MapIndex( Box::new(MapIndex::new( - Expression::Value( + ValueExpression::Value( ValueNode::Map(vec![( Identifier::new("x"), None, - Expression::Value(ValueNode::Integer(42).with_position((6, 8))) + ValueExpression::Value(ValueNode::Integer(42).with_position((6, 8))) )]) .with_position((0, 10)) ), - Expression::Identifier(Identifier::new("x").with_position((11, 12))) + ValueExpression::Identifier(Identifier::new("x").with_position((11, 12))) )) .with_position((0, 12)) )) ); assert_eq!( parse(&lex("foo.x").unwrap()).unwrap()[0], - Statement::Expression(Expression::MapIndex( + Statement::ValueExpression(ValueExpression::MapIndex( Box::new(MapIndex::new( - Expression::Identifier(Identifier::new("foo").with_position((0, 3))), - Expression::Identifier(Identifier::new("x").with_position((4, 5))) + ValueExpression::Identifier(Identifier::new("foo").with_position((0, 3))), + ValueExpression::Identifier(Identifier::new("x").with_position((4, 5))) )) .with_position((0, 5)) )) @@ -874,14 +895,14 @@ mod tests { parse(&lex("while true { output('hi') }").unwrap()).unwrap()[0], Statement::While( While::new( - Expression::Value(ValueNode::Boolean(true).with_position((6, 10))), - vec![Statement::Expression(Expression::FunctionCall( + ValueExpression::Value(ValueNode::Boolean(true).with_position((6, 10))), + vec![Statement::ValueExpression(ValueExpression::FunctionCall( FunctionCall::new( - Expression::Identifier( + ValueExpression::Identifier( Identifier::new("output").with_position((13, 19)) ), Vec::with_capacity(0), - vec![Expression::Value( + vec![ValueExpression::Value( ValueNode::String("hi".to_string()).with_position((20, 24)) )] ) @@ -902,7 +923,7 @@ mod tests { Identifier::new("foobar").with_position((0, 6)), Some(Type::Boolean.with_position((9, 13))), AssignmentOperator::Assign, - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Boolean(true).with_position((16, 20)) )) ) @@ -920,7 +941,7 @@ mod tests { Identifier::new("foobar").with_position((0, 6)), Some(Type::List.with_position((8, 12))), AssignmentOperator::Assign, - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::List(vec![]).with_position((15, 17)) )) ) @@ -941,8 +962,8 @@ mod tests { .with_position((9, 19)) ), AssignmentOperator::Assign, - Statement::Expression(Expression::Value( - ValueNode::List(vec![Expression::Value( + Statement::ValueExpression(ValueExpression::Value( + ValueNode::List(vec![ValueExpression::Value( ValueNode::Boolean(true).with_position((23, 27)) )]) .with_position((22, 28)) @@ -968,10 +989,12 @@ mod tests { .with_position((9, 20)) ), AssignmentOperator::Assign, - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::List(vec![ - Expression::Value(ValueNode::Boolean(true).with_position((24, 28))), - Expression::Value( + ValueExpression::Value( + ValueNode::Boolean(true).with_position((24, 28)) + ), + ValueExpression::Value( ValueNode::String("42".to_string()).with_position((30, 34)) ) ]) @@ -998,7 +1021,7 @@ mod tests { .with_position((9, 20)) ), AssignmentOperator::Assign, - Statement::Expression(Expression::Identifier( + Statement::ValueExpression(ValueExpression::Identifier( Identifier::new("some_function").with_position((23, 36)) )) ) @@ -1011,9 +1034,9 @@ mod tests { fn function_call() { assert_eq!( parse(&lex("foobar()").unwrap()).unwrap()[0], - Statement::Expression(Expression::FunctionCall( + Statement::ValueExpression(ValueExpression::FunctionCall( FunctionCall::new( - Expression::Identifier(Identifier::new("foobar").with_position((0, 6))), + ValueExpression::Identifier(Identifier::new("foobar").with_position((0, 6))), Vec::with_capacity(0), Vec::with_capacity(0), ) @@ -1026,11 +1049,11 @@ mod tests { fn function_call_with_type_arguments() { assert_eq!( parse(&lex("foobar::(str)::('hi')").unwrap()).unwrap()[0], - Statement::Expression(Expression::FunctionCall( + Statement::ValueExpression(ValueExpression::FunctionCall( FunctionCall::new( - Expression::Identifier(Identifier::new("foobar").with_position((0, 6))), + ValueExpression::Identifier(Identifier::new("foobar").with_position((0, 6))), vec![Type::String.with_position((9, 12))], - vec![Expression::Value( + vec![ValueExpression::Value( ValueNode::String("hi".to_string()).with_position((16, 20)) )], ) @@ -1043,7 +1066,7 @@ mod tests { fn range() { assert_eq!( parse(&lex("1..10").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Range(1..10).with_position((0, 5)) )) ) @@ -1053,14 +1076,14 @@ mod tests { fn function() { assert_eq!( parse(&lex("fn (x: int) int { x }").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::ParsedFunction { type_arguments: Vec::with_capacity(0), parameters: vec![(Identifier::new("x"), Type::Integer.with_position((7, 10)))], return_type: Type::Integer.with_position((12, 15)), - body: Block::new(vec![Statement::Expression(Expression::Identifier( - Identifier::new("x").with_position((18, 19)) - ))]) + body: Block::new(vec![Statement::ValueExpression( + ValueExpression::Identifier(Identifier::new("x").with_position((18, 19))) + )]) .with_position((16, 21)), } .with_position((0, 21)) @@ -1072,7 +1095,7 @@ mod tests { fn function_with_type_arguments() { assert_eq!( parse(&lex("fn (T, U)(x: T, y: U) T { x }").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::ParsedFunction { type_arguments: vec![ Type::Argument(Identifier::new("T")).with_position((4, 5)), @@ -1089,9 +1112,9 @@ mod tests { ) ], return_type: Type::Argument(Identifier::new("T")).with_position((22, 23)), - body: Block::new(vec![Statement::Expression(Expression::Identifier( - Identifier::new("x").with_position((26, 27)) - ))]) + body: Block::new(vec![Statement::ValueExpression( + ValueExpression::Identifier(Identifier::new("x").with_position((26, 27))) + )]) .with_position((24, 29)), } .with_position((0, 29)) @@ -1105,8 +1128,8 @@ mod tests { parse(&lex("if true { 'foo' }").unwrap()).unwrap()[0], Statement::IfElse( IfElse::new( - Expression::Value(ValueNode::Boolean(true).with_position((3, 7))), - Block::new(vec![Statement::Expression(Expression::Value( + ValueExpression::Value(ValueNode::Boolean(true).with_position((3, 7))), + Block::new(vec![Statement::ValueExpression(ValueExpression::Value( ValueNode::String("foo".to_string()).with_position((10, 15)) ))]) .with_position((8, 17)), @@ -1124,14 +1147,14 @@ mod tests { parse(&lex("if true {'foo' } else { 'bar' }").unwrap()).unwrap()[0], Statement::IfElse( IfElse::new( - Expression::Value(ValueNode::Boolean(true).with_position((3, 7))), - Block::new(vec![Statement::Expression(Expression::Value( + ValueExpression::Value(ValueNode::Boolean(true).with_position((3, 7))), + Block::new(vec![Statement::ValueExpression(ValueExpression::Value( ValueNode::String("foo".to_string()).with_position((9, 14)) ))]) .with_position((8, 16)), Vec::with_capacity(0), Some( - Block::new(vec![Statement::Expression(Expression::Value( + Block::new(vec![Statement::ValueExpression(ValueExpression::Value( ValueNode::String("bar".to_string()).with_position((24, 29)) ))]) .with_position((22, 31)) @@ -1146,28 +1169,30 @@ mod tests { fn map() { assert_eq!( parse(&lex("{ foo = 'bar' }").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Map(vec![( Identifier::new("foo"), None, - Expression::Value(ValueNode::String("bar".to_string()).with_position((8, 13))) + ValueExpression::Value( + ValueNode::String("bar".to_string()).with_position((8, 13)) + ) )]) .with_position((0, 15)) ),) ); assert_eq!( parse(&lex("{ x = 1, y = 2, }").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Map(vec![ ( Identifier::new("x"), None, - Expression::Value(ValueNode::Integer(1).with_position((6, 7))) + ValueExpression::Value(ValueNode::Integer(1).with_position((6, 7))) ), ( Identifier::new("y"), None, - Expression::Value(ValueNode::Integer(2).with_position((13, 14))) + ValueExpression::Value(ValueNode::Integer(2).with_position((13, 14))) ), ]) .with_position((0, 17)) @@ -1175,17 +1200,17 @@ mod tests { ); assert_eq!( parse(&lex("{ x = 1 y = 2 }").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Map(vec![ ( Identifier::new("x"), None, - Expression::Value(ValueNode::Integer(1).with_position((6, 7))) + ValueExpression::Value(ValueNode::Integer(1).with_position((6, 7))) ), ( Identifier::new("y"), None, - Expression::Value(ValueNode::Integer(2).with_position((12, 13))) + ValueExpression::Value(ValueNode::Integer(2).with_position((12, 13))) ), ]) .with_position((0, 15)) @@ -1197,10 +1222,10 @@ mod tests { fn math() { assert_eq!( parse(&lex("1 + 1").unwrap()).unwrap()[0], - Statement::Expression(Expression::Math( + Statement::ValueExpression(ValueExpression::Math( Box::new(Math::Add( - Expression::Value(ValueNode::Integer(1).with_position((0, 1))), - Expression::Value(ValueNode::Integer(1).with_position((4, 5))) + ValueExpression::Value(ValueNode::Integer(1).with_position((0, 1))), + ValueExpression::Value(ValueNode::Integer(1).with_position((4, 5))) )) .with_position((0, 5)) )) @@ -1212,7 +1237,7 @@ mod tests { assert_eq!( parse(&lex("loop { 42 }").unwrap()).unwrap()[0], Statement::Loop( - Loop::new(vec![Statement::Expression(Expression::Value( + Loop::new(vec![Statement::ValueExpression(ValueExpression::Value( ValueNode::Integer(42).with_position((7, 9)) ))]) .with_position((0, 11)) @@ -1223,12 +1248,14 @@ mod tests { Statement::Loop( Loop::new(vec![Statement::IfElse( IfElse::new( - Expression::Logic( + ValueExpression::Logic( Box::new(Logic::Greater( - Expression::Identifier( + ValueExpression::Identifier( Identifier::new("i").with_position((10, 11)) ), - Expression::Value(ValueNode::Integer(2).with_position((14, 15))) + ValueExpression::Value( + ValueNode::Integer(2).with_position((14, 15)) + ) )) .with_position((10, 15)) ), @@ -1241,7 +1268,7 @@ mod tests { Identifier::new("i").with_position((33, 34)), None, AssignmentOperator::AddAssign, - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Integer(1).with_position((38, 39)) )) ) @@ -1262,9 +1289,9 @@ mod tests { assert_eq!( parse(&lex("{ x }").unwrap()).unwrap()[0], Statement::Block( - Block::new(vec![Statement::Expression(Expression::Identifier( - Identifier::new("x").with_position((2, 3)) - ),)]) + Block::new(vec![Statement::ValueExpression( + ValueExpression::Identifier(Identifier::new("x").with_position((2, 3))), + )]) .with_position((0, 5)) ) ); @@ -1283,13 +1310,13 @@ mod tests { .unwrap()[0], Statement::Block( Block::new(vec![ - Statement::Expression(Expression::Identifier( + Statement::ValueExpression(ValueExpression::Identifier( Identifier::new("x").with_position((39, 40)) )), - Statement::Expression(Expression::Identifier( + Statement::ValueExpression(ValueExpression::Identifier( Identifier::new("y").with_position((62, 63)) )), - Statement::Expression(Expression::Identifier( + Statement::ValueExpression(ValueExpression::Identifier( Identifier::new("z").with_position((85, 86)) )), ]) @@ -1310,14 +1337,14 @@ mod tests { .unwrap()[0], Statement::Block( Block::new(vec![ - Statement::Expression(Expression::Logic( + Statement::ValueExpression(ValueExpression::Logic( Box::new(Logic::Equal( - Expression::Value(ValueNode::Integer(1).with_position((39, 40))), - Expression::Value(ValueNode::Integer(1).with_position((44, 45))) + ValueExpression::Value(ValueNode::Integer(1).with_position((39, 40))), + ValueExpression::Value(ValueNode::Integer(1).with_position((44, 45))) )) .with_position((39, 45)) )), - Statement::Expression(Expression::Identifier( + Statement::ValueExpression(ValueExpression::Identifier( Identifier::new("z").with_position((66, 67)) )), ]) @@ -1330,19 +1357,19 @@ mod tests { fn identifier() { assert_eq!( parse(&lex("x").unwrap()).unwrap()[0], - Statement::Expression(Expression::Identifier( + Statement::ValueExpression(ValueExpression::Identifier( Identifier::new("x").with_position((0, 1)) )) ); assert_eq!( parse(&lex("foobar").unwrap()).unwrap()[0], - Statement::Expression(Expression::Identifier( + Statement::ValueExpression(ValueExpression::Identifier( Identifier::new("foobar").with_position((0, 6)) )) ); assert_eq!( parse(&lex("HELLO").unwrap()).unwrap()[0], - Statement::Expression(Expression::Identifier( + Statement::ValueExpression(ValueExpression::Identifier( Identifier::new("HELLO").with_position((0, 5)) )) ); @@ -1357,7 +1384,7 @@ mod tests { Identifier::new("foobar").with_position((0, 6)), None, AssignmentOperator::Assign, - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Integer(1).with_position((9, 10)) )) ) @@ -1375,7 +1402,7 @@ mod tests { Identifier::new("foobar").with_position((0, 6)), Some(Type::Integer.with_position((8, 11))), AssignmentOperator::Assign, - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Integer(1).with_position((14, 15)) )) ) @@ -1388,10 +1415,10 @@ mod tests { fn logic() { assert_eq!( parse(&lex("x == 1").unwrap()).unwrap()[0], - Statement::Expression(Expression::Logic( + Statement::ValueExpression(ValueExpression::Logic( Box::new(Logic::Equal( - Expression::Identifier(Identifier::new("x").with_position((0, 1))), - Expression::Value(ValueNode::Integer(1).with_position((5, 6))), + ValueExpression::Identifier(Identifier::new("x").with_position((0, 1))), + ValueExpression::Value(ValueNode::Integer(1).with_position((5, 6))), )) .with_position((0, 6)) )) @@ -1399,19 +1426,21 @@ mod tests { assert_eq!( parse(&lex("(x == 1) && (y == 2)").unwrap()).unwrap()[0], - Statement::Expression(Expression::Logic( + Statement::ValueExpression(ValueExpression::Logic( Box::new(Logic::And( - Expression::Logic( + ValueExpression::Logic( Box::new(Logic::Equal( - Expression::Identifier(Identifier::new("x").with_position((1, 2))), - Expression::Value(ValueNode::Integer(1).with_position((6, 7))), + ValueExpression::Identifier(Identifier::new("x").with_position((1, 2))), + ValueExpression::Value(ValueNode::Integer(1).with_position((6, 7))), )) .with_position((1, 7)) ), - Expression::Logic( + ValueExpression::Logic( Box::new(Logic::Equal( - Expression::Identifier(Identifier::new("y").with_position((13, 14))), - Expression::Value(ValueNode::Integer(2).with_position((18, 19))), + ValueExpression::Identifier( + Identifier::new("y").with_position((13, 14)) + ), + ValueExpression::Value(ValueNode::Integer(2).with_position((18, 19))), )) .with_position((13, 19)) ) @@ -1422,25 +1451,27 @@ mod tests { assert_eq!( parse(&lex("(x == 1) && (y == 2) && true").unwrap()).unwrap()[0], - Statement::Expression(Expression::Logic( + Statement::ValueExpression(ValueExpression::Logic( Box::new(Logic::And( - Expression::Logic( + ValueExpression::Logic( Box::new(Logic::And( - Expression::Logic( + ValueExpression::Logic( Box::new(Logic::Equal( - Expression::Identifier( + ValueExpression::Identifier( Identifier::new("x").with_position((1, 2)) ), - Expression::Value(ValueNode::Integer(1).with_position((6, 7))) + ValueExpression::Value( + ValueNode::Integer(1).with_position((6, 7)) + ) )) .with_position((1, 7)) ), - Expression::Logic( + ValueExpression::Logic( Box::new(Logic::Equal( - Expression::Identifier( + ValueExpression::Identifier( Identifier::new("y").with_position((13, 14)) ), - Expression::Value( + ValueExpression::Value( ValueNode::Integer(2).with_position((18, 19)) ) )) @@ -1449,7 +1480,7 @@ mod tests { )) .with_position((0, 20)) ), - Expression::Value(ValueNode::Boolean(true).with_position((24, 28))) + ValueExpression::Value(ValueNode::Boolean(true).with_position((24, 28))) )) .with_position((0, 28)) )) @@ -1460,14 +1491,14 @@ mod tests { fn list() { assert_eq!( parse(&lex("[]").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::List(Vec::with_capacity(0)).with_position((0, 2)) ),) ); assert_eq!( parse(&lex("[42]").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( - ValueNode::List(vec![Expression::Value( + Statement::ValueExpression(ValueExpression::Value( + ValueNode::List(vec![ValueExpression::Value( ValueNode::Integer(42).with_position((1, 3)) )]) .with_position((0, 4)) @@ -1475,16 +1506,20 @@ mod tests { ); assert_eq!( parse(&lex("[42, 'foo', 'bar', [1, 2, 3,]]").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::List(vec![ - Expression::Value(ValueNode::Integer(42).with_position((1, 3))), - Expression::Value(ValueNode::String("foo".to_string()).with_position((5, 10))), - Expression::Value(ValueNode::String("bar".to_string()).with_position((12, 17))), - Expression::Value( + ValueExpression::Value(ValueNode::Integer(42).with_position((1, 3))), + ValueExpression::Value( + ValueNode::String("foo".to_string()).with_position((5, 10)) + ), + ValueExpression::Value( + ValueNode::String("bar".to_string()).with_position((12, 17)) + ), + ValueExpression::Value( ValueNode::List(vec![ - Expression::Value(ValueNode::Integer(1).with_position((20, 21))), - Expression::Value(ValueNode::Integer(2).with_position((23, 24))), - Expression::Value(ValueNode::Integer(3).with_position((26, 27))), + ValueExpression::Value(ValueNode::Integer(1).with_position((20, 21))), + ValueExpression::Value(ValueNode::Integer(2).with_position((23, 24))), + ValueExpression::Value(ValueNode::Integer(3).with_position((26, 27))), ]) .with_position((19, 29)) ) @@ -1498,7 +1533,7 @@ mod tests { fn r#true() { assert_eq!( parse(&lex("true").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Boolean(true).with_position((0, 4)) )) ); @@ -1508,7 +1543,7 @@ mod tests { fn r#false() { assert_eq!( parse(&lex("false").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Boolean(false).with_position((0, 5)) )) ); @@ -1518,13 +1553,13 @@ mod tests { fn positive_float() { assert_eq!( parse(&lex("0.0").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Float(0.0).with_position((0, 3)) )) ); assert_eq!( parse(&lex("42.0").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Float(42.0).with_position((0, 4)) )) ); @@ -1533,7 +1568,7 @@ mod tests { assert_eq!( parse(&lex(&max_float).unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Float(f64::MAX).with_position((0, 311)) )) ); @@ -1542,7 +1577,7 @@ mod tests { assert_eq!( parse(&lex(&min_positive_float).unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Float(f64::MIN_POSITIVE).with_position((0, 326)) ),) ); @@ -1552,13 +1587,13 @@ mod tests { fn negative_float() { assert_eq!( parse(&lex("-0.0").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Float(-0.0).with_position((0, 4)) )) ); assert_eq!( parse(&lex("-42.0").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Float(-42.0).with_position((0, 5)) )) ); @@ -1567,7 +1602,7 @@ mod tests { assert_eq!( parse(&lex(&min_float).unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Float(f64::MIN).with_position((0, 312)) )) ); @@ -1576,7 +1611,7 @@ mod tests { assert_eq!( parse(&lex(&max_negative_float).unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Float(-f64::MIN_POSITIVE).with_position((0, 327)) ),) ); @@ -1586,19 +1621,19 @@ mod tests { fn other_float() { assert_eq!( parse(&lex("Infinity").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Float(f64::INFINITY).with_position((0, 8)) )) ); assert_eq!( parse(&lex("-Infinity").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Float(f64::NEG_INFINITY).with_position((0, 9)) )) ); - if let Statement::Expression(Expression::Value(WithPosition { - item: ValueNode::Float(float), + if let Statement::ValueExpression(ValueExpression::Value(WithPosition { + node: ValueNode::Float(float), .. })) = &parse(&lex("NaN").unwrap()).unwrap()[0] { @@ -1617,7 +1652,7 @@ mod tests { assert_eq!( statements[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Integer(i).with_position((0, 1)) )) ) @@ -1625,7 +1660,7 @@ mod tests { assert_eq!( parse(&lex("42").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Integer(42).with_position((0, 2)) )) ); @@ -1634,7 +1669,7 @@ mod tests { assert_eq!( parse(&lex(&maximum_integer).unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Integer(i64::MAX).with_position((0, 19)) )) ); @@ -1649,7 +1684,7 @@ mod tests { assert_eq!( statements[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Integer(i).with_position((0, 2)) )) ) @@ -1657,7 +1692,7 @@ mod tests { assert_eq!( parse(&lex("-42").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Integer(-42).with_position((0, 3)) )) ); @@ -1666,7 +1701,7 @@ mod tests { assert_eq!( parse(&lex(&minimum_integer).unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::Integer(i64::MIN).with_position((0, 20)) )) ); @@ -1676,19 +1711,19 @@ mod tests { fn double_quoted_string() { assert_eq!( parse(&lex("\"\"").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::String("".to_string()).with_position((0, 2)) )) ); assert_eq!( parse(&lex("\"42\"").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::String("42".to_string()).with_position((0, 4)) ),) ); assert_eq!( parse(&lex("\"foobar\"").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::String("foobar".to_string()).with_position((0, 8)) ),) ); @@ -1698,19 +1733,19 @@ mod tests { fn single_quoted_string() { assert_eq!( parse(&lex("''").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::String("".to_string()).with_position((0, 2)) )) ); assert_eq!( parse(&lex("'42'").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::String("42".to_string()).with_position((0, 4)) ),) ); assert_eq!( parse(&lex("'foobar'").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::String("foobar".to_string()).with_position((0, 8)) ),) ); @@ -1720,19 +1755,19 @@ mod tests { fn grave_quoted_string() { assert_eq!( parse(&lex("``").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::String("".to_string()).with_position((0, 2)) )) ); assert_eq!( parse(&lex("`42`").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::String("42".to_string()).with_position((0, 4)) ),) ); assert_eq!( parse(&lex("`foobar`").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( + Statement::ValueExpression(ValueExpression::Value( ValueNode::String("foobar".to_string()).with_position((0, 8)) ),) ); diff --git a/dust-lang/src/value.rs b/dust-lang/src/value.rs index 3c21e45..f381625 100644 --- a/dust-lang/src/value.rs +++ b/dust-lang/src/value.rs @@ -109,9 +109,9 @@ impl Display for Value { for (index, value) in list.into_iter().enumerate() { if index == list.len() - 1 { - write!(f, "{}", value.item)?; + write!(f, "{}", value.node)?; } else { - write!(f, "{}, ", value.item)?; + write!(f, "{}, ", value.node)?; } } @@ -139,9 +139,9 @@ impl Display for Value { for (index, r#type) in type_arguments.into_iter().enumerate() { if index == type_arguments.len() - 1 { - write!(f, "{}", r#type.item)?; + write!(f, "{}", r#type.node)?; } else { - write!(f, "{} ", r#type.item)?; + write!(f, "{} ", r#type.node)?; } } @@ -151,13 +151,13 @@ impl Display for Value { write!(f, "(")?; for (identifier, r#type) in parameters { - write!(f, "{identifier}: {}", r#type.item)?; + write!(f, "{identifier}: {}", r#type.node)?; } - write!(f, "): {} {:?}", return_type.item, body.item) + write!(f, "): {} {:?}", return_type.node, body.node) } ValueInner::Structure { name, fields } => { - write!(f, "{}\n{{", name.item)?; + write!(f, "{}\n{{", name.node)?; for (key, value) in fields { writeln!(f, "{key} = {value},")?; @@ -184,7 +184,7 @@ impl Ord for Value { } impl Serialize for Value { - fn serialize(&self, serializer: S) -> Result + fn serialize(&self, _serializer: S) -> Result where S: serde::Serializer, { @@ -193,7 +193,7 @@ impl Serialize for Value { } impl<'de> Deserialize<'de> for Value { - fn deserialize(deserializer: D) -> Result + fn deserialize(_deserializer: D) -> Result where D: serde::Deserializer<'de>, { @@ -227,7 +227,7 @@ impl ValueInner { let mut types = Vec::with_capacity(values.len()); for value in values { - types.push(value.item.r#type(context)?.with_position(value.position)); + types.push(value.node.r#type(context)?.with_position(value.position)); } Type::ListExact(types) @@ -244,11 +244,11 @@ impl ValueInner { return_type: Box::new(function.return_type.clone()), }, ValueInner::Structure { name, .. } => { - if let Some(r#type) = context.get_type(&name.item)? { + if let Some(r#type) = context.get_type(&name.node)? { r#type } else { return Err(ValidationError::VariableNotFound { - identifier: name.item.clone(), + identifier: name.node.clone(), position: name.position, }); } @@ -342,6 +342,6 @@ impl Function { context.set_value(identifier.clone(), value)?; } - self.body.item.run(context, clear_variables) + self.body.node.run(context, clear_variables) } } diff --git a/dust-lang/tests/functions.rs b/dust-lang/tests/functions.rs index ad88d88..2bd4e96 100644 --- a/dust-lang/tests/functions.rs +++ b/dust-lang/tests/functions.rs @@ -28,20 +28,6 @@ fn function_call() { ); } -#[test] -fn call_empty_function() { - assert_eq!( - interpret( - "test", - " - foobar = fn (message : str) none {} - foobar('Hiya') - ", - ), - Ok(None) - ); -} - #[test] fn callback() { assert_eq!( diff --git a/dust-lang/tests/variables.rs b/dust-lang/tests/variables.rs index 50ab1ae..b52ad46 100644 --- a/dust-lang/tests/variables.rs +++ b/dust-lang/tests/variables.rs @@ -1,5 +1,5 @@ use dust_lang::{ - abstract_tree::{Block, Expression, Statement, Type, WithPos}, + abstract_tree::{Block, Statement, Type, ValueExpression, WithPos}, error::{Error, TypeConflict, ValidationError}, identifier::Identifier, *, @@ -49,9 +49,9 @@ fn function_variable() { Vec::with_capacity(0), vec![(Identifier::new("x"), Type::Integer.with_position((16, 19)))], Type::Integer.with_position((21, 24)), - Block::new(vec![Statement::Expression(Expression::Identifier( - Identifier::new("x").with_position((27, 28)) - ))]) + Block::new(vec![Statement::ValueExpression( + ValueExpression::Identifier(Identifier::new("x").with_position((27, 28))) + )]) .with_position((25, 30)) ))) );