diff --git a/dust-lang/src/abstract_tree/as.rs b/dust-lang/src/abstract_tree/as.rs index 07f115f..2346f05 100644 --- a/dust-lang/src/abstract_tree/as.rs +++ b/dust-lang/src/abstract_tree/as.rs @@ -9,17 +9,22 @@ use crate::{ Value, }; -use super::{AbstractNode, Action, ExpectedType, Type, ValueExpression, WithPosition}; +use super::{ + AbstractNode, Evaluation, ExpectedType, Expression, Type, TypeConstructor, WithPosition, +}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct As { - expression: ValueExpression, - r#type: WithPosition, + expression: Expression, + constructor: WithPosition, } impl As { - pub fn new(expression: ValueExpression, r#type: WithPosition) -> Self { - Self { expression, r#type } + pub fn new(expression: Expression, constructor: WithPosition) -> Self { + Self { + expression, + constructor, + } } } @@ -29,28 +34,35 @@ impl AbstractNode for As { _context: &mut Context, _manage_memory: bool, ) -> Result<(), ValidationError> { - match self.r#type.node { - Type::Boolean | Type::Float | Type::Integer | Type::String => {} + match self.constructor.node { + TypeConstructor::Type(_) => {} _ => todo!("Create an error for this occurence."), }; match self.expression.expected_type(_context)? { - Type::Boolean | Type::Float | Type::Integer | Type::String => Ok(()), + Type::Boolean | Type::Float | Type::Integer | Type::String => {} _ => todo!("Create an error for this occurence."), - } + }; + + Ok(()) } - fn run(self, _context: &mut Context, _manage_memory: bool) -> Result { + fn evaluate( + self, + context: &mut Context, + _manage_memory: bool, + ) -> Result { let expression_position = self.expression.position(); - let action = self.expression.run(_context, _manage_memory)?; - let value = if let Action::Return(value) = action { + let action = self.expression.evaluate(context, _manage_memory)?; + let value = if let Evaluation::Return(value) = action { value } else { return Err(RuntimeError::ValidationFailure( ValidationError::InterpreterExpectedReturn(expression_position), )); }; - let (from_value, to_type): (&ValueInner, Type) = (value.inner().borrow(), self.r#type.node); + let r#type = self.constructor.node.construct(&context)?; + let (from_value, to_type): (&ValueInner, Type) = (value.inner().borrow(), r#type); let converted = match (from_value, to_type) { (ValueInner::Boolean(boolean), Type::String) => Value::string(boolean.to_string()), @@ -58,12 +70,12 @@ impl AbstractNode for As { _ => todo!("Create an error for this occurence."), }; - Ok(Action::Return(converted)) + Ok(Evaluation::Return(converted)) } } impl ExpectedType for As { - fn expected_type(&self, _: &mut Context) -> Result { - Ok(self.r#type.node.clone()) + fn expected_type(&self, context: &mut Context) -> Result { + self.constructor.node.clone().construct(&context) } } diff --git a/dust-lang/src/abstract_tree/assignment.rs b/dust-lang/src/abstract_tree/assignment.rs index 54d543e..214fd69 100644 --- a/dust-lang/src/abstract_tree/assignment.rs +++ b/dust-lang/src/abstract_tree/assignment.rs @@ -7,12 +7,12 @@ use crate::{ Context, Value, }; -use super::{AbstractNode, Action, ExpectedType, Statement, Type, WithPosition}; +use super::{AbstractNode, Evaluation, ExpectedType, Statement, TypeConstructor, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct Assignment { identifier: WithPosition, - r#type: Option>, + constructor: Option>, operator: AssignmentOperator, statement: Box, } @@ -27,13 +27,13 @@ pub enum AssignmentOperator { impl Assignment { pub fn new( identifier: WithPosition, - r#type: Option>, + constructor: Option>, operator: AssignmentOperator, statement: Statement, ) -> Self { Self { identifier, - r#type, + constructor, operator, statement: Box::new(statement), } @@ -45,19 +45,21 @@ impl AbstractNode for Assignment { let statement_type = self.statement.expected_type(context)?; if let Some(WithPosition { - node: expected_type, + node: constructor, position: expected_position, - }) = &self.r#type + }) = &self.constructor { - expected_type.check(&statement_type).map_err(|conflict| { - ValidationError::TypeCheck { + let r#type = constructor.clone().construct(&context)?; + + r#type + .check(&statement_type) + .map_err(|conflict| ValidationError::TypeCheck { conflict, actual_position: self.statement.position(), - expected_position: expected_position.clone(), - } - })?; + expected_position: Some(expected_position.clone()), + })?; - context.set_type(self.identifier.node.clone(), expected_type.clone())?; + context.set_type(self.identifier.node.clone(), r#type.clone())?; } else { context.set_type(self.identifier.node.clone(), statement_type)?; } @@ -67,10 +69,14 @@ impl AbstractNode for Assignment { Ok(()) } - fn run(self, context: &mut Context, manage_memory: bool) -> Result { - let action = self.statement.run(context, manage_memory)?; + fn evaluate( + self, + context: &mut Context, + manage_memory: bool, + ) -> Result { + let action = self.statement.evaluate(context, manage_memory)?; let right = match action { - Action::Return(value) => value, + Evaluation::Return(value) => value, r#break => return Ok(r#break), }; @@ -170,6 +176,6 @@ impl AbstractNode for Assignment { } } - Ok(Action::None) + Ok(Evaluation::None) } } diff --git a/dust-lang/src/abstract_tree/async_block.rs b/dust-lang/src/abstract_tree/async_block.rs index 69e3712..aa25f32 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, ExpectedType, Statement, Type}; +use super::{AbstractNode, Evaluation, ExpectedType, Statement, Type}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct AsyncBlock { @@ -30,15 +30,19 @@ impl AbstractNode for AsyncBlock { Ok(()) } - fn run(self, _context: &mut Context, _manage_memory: bool) -> Result { + fn evaluate( + self, + _context: &mut Context, + _manage_memory: bool, + ) -> Result { let statement_count = self.statements.len(); - let final_result = RwLock::new(Ok(Action::None)); + let final_result = RwLock::new(Ok(Evaluation::None)); self.statements .into_par_iter() .enumerate() .find_map_first(|(index, statement)| { - let result = statement.run(&mut _context.clone(), false); + let result = statement.evaluate(&mut _context.clone(), false); if index == statement_count - 1 { let get_write_lock = final_result.write(); diff --git a/dust-lang/src/abstract_tree/block.rs b/dust-lang/src/abstract_tree/block.rs index 5948ad8..91dc89d 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, ExpectedType, Statement}; +use super::{AbstractNode, Evaluation, ExpectedType, Statement, Type}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct Block { @@ -39,11 +39,15 @@ impl AbstractNode for Block { Ok(()) } - fn run(self, _context: &mut Context, _manage_memory: bool) -> Result { - let mut previous = Action::None; + fn evaluate( + self, + _context: &mut Context, + _manage_memory: bool, + ) -> Result { + let mut previous = Evaluation::None; for statement in self.statements { - previous = statement.run(_context, _manage_memory)?; + previous = statement.evaluate(_context, _manage_memory)?; } Ok(previous) @@ -51,7 +55,7 @@ impl AbstractNode for Block { } impl ExpectedType for Block { - fn expected_type(&self, _context: &mut Context) -> Result { + fn expected_type(&self, _context: &mut Context) -> Result { self.last_statement().expected_type(_context) } } @@ -59,7 +63,7 @@ impl ExpectedType for Block { #[cfg(test)] mod tests { use crate::{ - abstract_tree::{Type, ValueExpression, ValueNode, WithPos}, + abstract_tree::{Expression, ValueNode, WithPos}, Value, }; @@ -68,30 +72,30 @@ mod tests { #[test] fn run_returns_value_of_final_statement() { let block = Block::new(vec![ - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Integer(1).with_position((0, 0)), )), - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Integer(2).with_position((0, 0)), )), - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Integer(42).with_position((0, 0)), )), ]); assert_eq!( - block.run(&mut Context::new(None), true).unwrap(), - Action::Return(Value::integer(42)) + block.evaluate(&mut Context::new(None), true).unwrap(), + Evaluation::Return(Value::integer(42)) ) } #[test] fn expected_type_returns_type_of_final_statement() { let block = Block::new(vec![ - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::String("42".to_string()).with_position((0, 0)), )), - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::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 63babec..51fb8a6 100644 --- a/dust-lang/src/abstract_tree/built_in_function_call.rs +++ b/dust-lang/src/abstract_tree/built_in_function_call.rs @@ -8,23 +8,22 @@ use std::{ use serde::{Deserialize, Serialize}; use crate::{ - abstract_tree::{Action, Type}, context::Context, error::{RuntimeError, ValidationError}, value::ValueInner, Value, }; -use super::{AbstractNode, ExpectedType, ValueExpression, WithPosition}; +use super::{AbstractNode, Evaluation, ExpectedType, Expression, Type, TypeConstructor}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub enum BuiltInFunctionCall { - JsonParse(WithPosition, ValueExpression), - Length(ValueExpression), - ReadFile(ValueExpression), + JsonParse(TypeConstructor, Expression), + Length(Expression), + ReadFile(Expression), ReadLine, - Sleep(ValueExpression), - WriteLine(ValueExpression), + Sleep(Expression), + WriteLine(Expression), } impl AbstractNode for BuiltInFunctionCall { @@ -51,11 +50,15 @@ impl AbstractNode for BuiltInFunctionCall { } } - fn run(self, context: &mut Context, _manage_memory: bool) -> Result { + fn evaluate( + self, + context: &mut Context, + _manage_memory: bool, + ) -> Result { match self { BuiltInFunctionCall::JsonParse(_type, expression) => { - let action = expression.clone().run(context, _manage_memory)?; - let value = if let Action::Return(value) = action { + let action = expression.clone().evaluate(context, _manage_memory)?; + let value = if let Evaluation::Return(value) = action { value } else { return Err(RuntimeError::ValidationFailure( @@ -66,7 +69,7 @@ impl AbstractNode for BuiltInFunctionCall { if let ValueInner::String(string) = value.inner().as_ref() { let deserialized = serde_json::from_str(string)?; - Ok(Action::Return(deserialized)) + Ok(Evaluation::Return(deserialized)) } else { Err(RuntimeError::ValidationFailure( ValidationError::ExpectedString { @@ -77,8 +80,8 @@ impl AbstractNode for BuiltInFunctionCall { } } BuiltInFunctionCall::Length(expression) => { - let action = expression.clone().run(context, _manage_memory)?; - let value = if let Action::Return(value) = action { + let action = expression.clone().evaluate(context, _manage_memory)?; + let value = if let Evaluation::Return(value) = action { value } else { return Err(RuntimeError::ValidationFailure( @@ -91,11 +94,11 @@ impl AbstractNode for BuiltInFunctionCall { 0 }; - Ok(Action::Return(Value::integer(length))) + Ok(Evaluation::Return(Value::integer(length))) } BuiltInFunctionCall::ReadFile(expression) => { - let action = expression.clone().run(context, _manage_memory)?; - let value = if let Action::Return(value) = action { + let action = expression.clone().evaluate(context, _manage_memory)?; + let value = if let Evaluation::Return(value) = action { value } else { return Err(RuntimeError::ValidationFailure( @@ -108,20 +111,20 @@ impl AbstractNode for BuiltInFunctionCall { String::with_capacity(0) }; - Ok(Action::Return(Value::string(file_contents))) + Ok(Evaluation::Return(Value::string(file_contents))) } BuiltInFunctionCall::ReadLine => { let mut buffer = String::new(); stdin().read_line(&mut buffer)?; - Ok(Action::Return(Value::string( + Ok(Evaluation::Return(Value::string( buffer.strip_suffix('\n').unwrap_or(&buffer), ))) } BuiltInFunctionCall::Sleep(expression) => { - let action = expression.clone().run(context, _manage_memory)?; - let value = if let Action::Return(value) = action { + let action = expression.clone().evaluate(context, _manage_memory)?; + let value = if let Evaluation::Return(value) = action { value } else { return Err(RuntimeError::ValidationFailure( @@ -133,11 +136,11 @@ impl AbstractNode for BuiltInFunctionCall { thread::sleep(Duration::from_millis(*milliseconds as u64)); } - Ok(Action::None) + Ok(Evaluation::None) } BuiltInFunctionCall::WriteLine(expression) => { - let action = expression.clone().run(context, _manage_memory)?; - let value = if let Action::Return(value) = action { + let action = expression.clone().evaluate(context, _manage_memory)?; + let value = if let Evaluation::Return(value) = action { value } else { return Err(RuntimeError::ValidationFailure( @@ -153,16 +156,16 @@ impl AbstractNode for BuiltInFunctionCall { stdout.flush()?; } - Ok(Action::None) + Ok(Evaluation::None) } } } } impl ExpectedType for BuiltInFunctionCall { - fn expected_type(&self, _context: &mut Context) -> Result { + fn expected_type(&self, context: &mut Context) -> Result { match self { - BuiltInFunctionCall::JsonParse(r#type, _) => Ok(r#type.node.clone()), + BuiltInFunctionCall::JsonParse(r#type, _) => Ok(r#type.clone().construct(&context)?), BuiltInFunctionCall::Length(_) => Ok(Type::Integer), BuiltInFunctionCall::ReadFile(_) => Ok(Type::String), BuiltInFunctionCall::ReadLine => Ok(Type::String), diff --git a/dust-lang/src/abstract_tree/function_call.rs b/dust-lang/src/abstract_tree/function_call.rs index 1d0ba7f..49d918a 100644 --- a/dust-lang/src/abstract_tree/function_call.rs +++ b/dust-lang/src/abstract_tree/function_call.rs @@ -6,25 +6,27 @@ use crate::{ value::ValueInner, }; -use super::{AbstractNode, Action, ExpectedType, Type, ValueExpression, WithPosition}; +use super::{ + AbstractNode, Evaluation, ExpectedType, Expression, Type, TypeConstructor, WithPosition, +}; #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct FunctionCall { - function: Box, - type_arguments: Vec>, - arguments: Vec, + function: Box, + type_arguments: Option>>, + value_arguments: Vec, } impl FunctionCall { pub fn new( - function: ValueExpression, - type_arguments: Vec>, - arguments: Vec, + function: Expression, + type_arguments: Option>>, + value_arguments: Vec, ) -> Self { FunctionCall { function: Box::new(function), type_arguments, - arguments, + value_arguments, } } } @@ -33,48 +35,28 @@ impl AbstractNode for FunctionCall { fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> { self.function.validate(context, manage_memory)?; - for expression in &self.arguments { + for expression in &self.value_arguments { expression.validate(context, manage_memory)?; } let function_node_type = self.function.expected_type(context)?; if let Type::Function { - parameter_types, + type_parameters, + value_parameters: _, return_type: _, } = function_node_type { - for (type_parameter, type_argument) in - parameter_types.iter().zip(self.type_arguments.iter()) - { - if let Type::Argument(_) = type_parameter.node { - continue; - } - - type_parameter - .node - .check(&type_argument.node) - .map_err(|conflict| ValidationError::TypeCheck { - conflict, - actual_position: type_argument.position, - expected_position: type_parameter.position, - })?; - } - - for (type_parameter, expression) in parameter_types.iter().zip(self.arguments.iter()) { - if let Type::Argument(_) = type_parameter.node { - continue; - } - - let actual = expression.expected_type(context)?; - - type_parameter.node.check(&actual).map_err(|conflict| { - ValidationError::TypeCheck { - conflict, - actual_position: expression.position(), - expected_position: type_parameter.position, + match (type_parameters, &self.type_arguments) { + (Some(type_parameters), Some(type_arguments)) => { + if type_parameters.len() != type_arguments.len() { + return Err(ValidationError::WrongTypeArgumentCount { + actual: type_parameters.len(), + expected: type_arguments.len(), + }); } - })?; + } + _ => {} } Ok(()) @@ -86,10 +68,14 @@ impl AbstractNode for FunctionCall { } } - fn run(self, context: &mut Context, clear_variables: bool) -> Result { + fn evaluate( + self, + context: &mut Context, + clear_variables: bool, + ) -> Result { let function_position = self.function.position(); - let action = self.function.run(context, clear_variables)?; - let value = if let Action::Return(value) = action { + let action = self.function.evaluate(context, clear_variables)?; + let value = if let Evaluation::Return(value) = action { value } else { return Err(RuntimeError::ValidationFailure( @@ -97,7 +83,7 @@ impl AbstractNode for FunctionCall { )); }; let function = if let ValueInner::Function(function) = value.inner().as_ref() { - function + function.clone() } else { return Err(RuntimeError::ValidationFailure( ValidationError::ExpectedFunction { @@ -106,12 +92,12 @@ impl AbstractNode for FunctionCall { }, )); }; - let mut arguments = Vec::with_capacity(self.arguments.len()); + let mut arguments = Vec::with_capacity(self.value_arguments.len()); - for expression in self.arguments { + for expression in self.value_arguments { let expression_position = expression.position(); - let action = expression.run(context, clear_variables)?; - let value = if let Action::Return(value) = action { + let action = expression.evaluate(context, clear_variables)?; + let value = if let Evaluation::Return(value) = action { value } else { return Err(RuntimeError::ValidationFailure( @@ -124,15 +110,17 @@ impl AbstractNode for FunctionCall { let mut function_context = Context::new(Some(&context)); - for (type_parameter, type_argument) in function - .type_parameters() - .iter() - .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)?; + match (function.type_parameters(), self.type_arguments) { + (Some(type_parameters), Some(type_arguments)) => { + for (parameter, constructor) in + type_parameters.into_iter().zip(type_arguments.into_iter()) + { + let r#type = constructor.node.construct(context)?; + + function_context.set_type(parameter.clone(), r#type)?; + } } + _ => {} } function @@ -146,7 +134,7 @@ impl ExpectedType for FunctionCall { let function_node_type = self.function.expected_type(_context)?; if let Type::Function { return_type, .. } = function_node_type { - Ok(return_type.node) + Ok(*return_type) } else { Err(ValidationError::ExpectedFunction { actual: function_node_type, diff --git a/dust-lang/src/abstract_tree/if_else.rs b/dust-lang/src/abstract_tree/if_else.rs index 7c7061f..33461f5 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, ExpectedType, Type, ValueExpression, WithPosition}; +use super::{AbstractNode, Block, Evaluation, ExpectedType, Expression, Type, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct IfElse { - if_expression: ValueExpression, + if_expression: Expression, if_block: WithPosition, - else_ifs: Vec<(ValueExpression, WithPosition)>, + else_ifs: Vec<(Expression, WithPosition)>, else_block: Option>, } impl IfElse { pub fn new( - if_expression: ValueExpression, + if_expression: Expression, if_block: WithPosition, - else_ifs: Vec<(ValueExpression, WithPosition)>, + else_ifs: Vec<(Expression, WithPosition)>, else_block: Option>, ) -> Self { Self { @@ -51,7 +51,7 @@ impl AbstractNode for IfElse { .map_err(|conflict| ValidationError::TypeCheck { conflict, actual_position: else_block.node.last_statement().position(), - expected_position: self.if_block.node.first_statement().position(), + expected_position: Some(self.if_block.node.first_statement().position()), })?; } } else { @@ -74,7 +74,7 @@ impl AbstractNode for IfElse { .map_err(|conflict| ValidationError::TypeCheck { conflict, actual_position: self.if_block.node.last_statement().position(), - expected_position: self.if_expression.position(), + expected_position: Some(self.if_expression.position()), })?; } else { return Err(ValidationError::ExpectedBoolean { @@ -87,10 +87,14 @@ impl AbstractNode for IfElse { Ok(()) } - fn run(self, context: &mut Context, _manage_memory: bool) -> Result { + fn evaluate( + self, + context: &mut Context, + _manage_memory: bool, + ) -> Result { let if_position = self.if_expression.position(); - let action = self.if_expression.run(context, _manage_memory)?; - let value = if let Action::Return(value) = action { + let action = self.if_expression.evaluate(context, _manage_memory)?; + let value = if let Evaluation::Return(value) = action { value } else { return Err(RuntimeError::ValidationFailure( @@ -100,12 +104,12 @@ impl AbstractNode for IfElse { if let ValueInner::Boolean(if_boolean) = value.inner().as_ref() { if *if_boolean { - self.if_block.node.run(context, _manage_memory) + self.if_block.node.evaluate(context, _manage_memory) } else { for (expression, block) in self.else_ifs { let expression_position = expression.position(); - let action = expression.run(context, _manage_memory)?; - let value = if let Action::Return(value) = action { + let action = expression.evaluate(context, _manage_memory)?; + let value = if let Evaluation::Return(value) = action { value } else { return Err(RuntimeError::ValidationFailure( @@ -115,7 +119,7 @@ impl AbstractNode for IfElse { if let ValueInner::Boolean(else_if_boolean) = value.inner().as_ref() { if *else_if_boolean { - return block.node.run(context, _manage_memory); + return block.node.evaluate(context, _manage_memory); } } else { return Err(RuntimeError::ValidationFailure( @@ -128,9 +132,9 @@ impl AbstractNode for IfElse { } if let Some(else_statement) = self.else_block { - else_statement.node.run(context, _manage_memory) + else_statement.node.evaluate(context, _manage_memory) } else { - Ok(Action::None) + Ok(Evaluation::None) } } } else { @@ -163,17 +167,17 @@ mod tests { fn simple_if() { assert_eq!( IfElse::new( - ValueExpression::Value(ValueNode::Boolean(true).with_position((0, 0))), - Block::new(vec![Statement::ValueExpression(ValueExpression::Value( + Expression::Value(ValueNode::Boolean(true).with_position((0, 0))), + Block::new(vec![Statement::ValueExpression(Expression::Value( ValueNode::String("foo".to_string()).with_position((0, 0)) ))]) .with_position((0, 0)), Vec::with_capacity(0), None ) - .run(&mut Context::new(None), true) + .evaluate(&mut Context::new(None), true) .unwrap(), - Action::Return(Value::string("foo".to_string())) + Evaluation::Return(Value::string("foo".to_string())) ) } } diff --git a/dust-lang/src/abstract_tree/list_index.rs b/dust-lang/src/abstract_tree/list_index.rs index 3bd731d..b242a91 100644 --- a/dust-lang/src/abstract_tree/list_index.rs +++ b/dust-lang/src/abstract_tree/list_index.rs @@ -5,64 +5,72 @@ use crate::{ error::{RuntimeError, ValidationError}, }; -use super::{AbstractNode, Action, ExpectedType, Type, ValueExpression, ValueNode, WithPosition}; +use super::{AbstractNode, Evaluation, ExpectedType, Expression, Type, ValueNode, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct ListIndex { - left: ValueExpression, - right: ValueExpression, + collection: Expression, + index: Expression, } impl ListIndex { - pub fn new(left: ValueExpression, right: ValueExpression) -> Self { - Self { left, right } + pub fn new(left: Expression, right: Expression) -> Self { + Self { + collection: left, + index: right, + } } } impl AbstractNode for ListIndex { fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> { - self.left.validate(context, _manage_memory)?; - self.right.validate(context, _manage_memory)?; + self.collection.validate(context, _manage_memory)?; + self.index.validate(context, _manage_memory)?; - let left_type = self.left.expected_type(context)?; + let collection_type = self.collection.expected_type(context)?; + let index_type = self.index.expected_type(context)?; - match left_type { - Type::List => todo!(), - Type::ListOf(_) => todo!(), - Type::ListExact(_) => { - let right_type = self.right.expected_type(context)?; - - if let Type::Integer = right_type { + match collection_type { + Type::List { + length: _, + item_type: _, + } => { + if index_type == Type::Integer { Ok(()) } else { Err(ValidationError::CannotIndexWith { - collection_type: left_type, - collection_position: self.left.position(), - index_type: right_type, - index_position: self.right.position(), + collection_type, + collection_position: self.collection.position(), + index_type, + index_position: self.index.position(), }) } } + Type::ListOf(_) => todo!(), _ => Err(ValidationError::CannotIndex { - r#type: left_type, - position: self.left.position(), + r#type: collection_type, + position: self.collection.position(), }), } } - fn run(self, context: &mut Context, _clear_variables: bool) -> Result { - let left_position = self.left.position(); - let left_action = self.left.run(context, _clear_variables)?; - let left_value = if let Action::Return(value) = left_action { + fn evaluate( + self, + context: &mut Context, + _clear_variables: bool, + ) -> Result { + let left_position = self.collection.position(); + let left_action = self.collection.evaluate(context, _clear_variables)?; + let left_value = if let Evaluation::Return(value) = left_action { value } else { return Err(RuntimeError::ValidationFailure( ValidationError::InterpreterExpectedReturn(left_position), )); }; - let right_position = self.right.position(); - let right_action = self.right.run(context, _clear_variables)?; - let right_value = if let Action::Return(value) = right_action { + let right_position = self.index.position(); + let right_action = self.index.evaluate(context, _clear_variables)?; + let right_value = if let Evaluation::Return(value) = right_action { value } else { return Err(RuntimeError::ValidationFailure( @@ -74,9 +82,9 @@ impl AbstractNode for ListIndex { let found_item = list.get(index as usize); if let Some(item) = found_item { - Ok(Action::Return(item.node.clone())) + Ok(Evaluation::Return(item.node.clone())) } else { - Ok(Action::None) + Ok(Evaluation::None) } } else { Err(RuntimeError::ValidationFailure( @@ -93,18 +101,18 @@ impl AbstractNode for ListIndex { impl ExpectedType for ListIndex { fn expected_type(&self, _context: &mut Context) -> Result { - let left_type = self.left.expected_type(_context)?; + let left_type = self.collection.expected_type(_context)?; if let ( - ValueExpression::Value(WithPosition { + Expression::Value(WithPosition { node: ValueNode::List(expression_list), .. }), - ValueExpression::Value(WithPosition { + Expression::Value(WithPosition { node: ValueNode::Integer(index), .. }), - ) = (&self.left, &self.right) + ) = (&self.collection, &self.index) { let expression = if let Some(expression) = expression_list.get(*index as usize) { expression @@ -116,7 +124,7 @@ impl ExpectedType for ListIndex { } else { Err(ValidationError::CannotIndex { r#type: left_type, - position: self.left.position(), + position: self.collection.position(), }) } } diff --git a/dust-lang/src/abstract_tree/logic.rs b/dust-lang/src/abstract_tree/logic.rs index 39b9697..28231a2 100644 --- a/dust-lang/src/abstract_tree/logic.rs +++ b/dust-lang/src/abstract_tree/logic.rs @@ -7,19 +7,19 @@ use crate::{ Value, }; -use super::{AbstractNode, Action, ExpectedType, Type, ValueExpression}; +use super::{AbstractNode, Evaluation, ExpectedType, Expression, Type}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub enum Logic { - 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), + 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), } impl AbstractNode for Logic { @@ -42,7 +42,7 @@ impl AbstractNode for Logic { .map_err(|conflict| ValidationError::TypeCheck { conflict, actual_position: left.position(), - expected_position: right.position(), + expected_position: Some(right.position()), })?; Ok(()) @@ -89,11 +89,15 @@ impl AbstractNode for Logic { } } - fn run(self, context: &mut Context, _manage_memory: bool) -> Result { - let run_and_expect_value = |expression: ValueExpression| -> Result { + fn evaluate( + self, + context: &mut Context, + _manage_memory: bool, + ) -> Result { + let run_and_expect_value = |expression: Expression| -> Result { let expression_position = expression.position(); - let action = expression.run(&mut context.clone(), _manage_memory)?; - let value = if let Action::Return(value) = action { + let action = expression.evaluate(&mut context.clone(), _manage_memory)?; + let value = if let Evaluation::Return(value) = action { value } else { return Err(RuntimeError::ValidationFailure( @@ -104,10 +108,10 @@ impl AbstractNode for Logic { Ok(value) }; - let run_and_expect_boolean = |expression: ValueExpression| -> Result { + let run_and_expect_boolean = |expression: Expression| -> Result { let expression_position = expression.position(); - let action = expression.run(&mut context.clone(), _manage_memory)?; - let value = if let Action::Return(value) = action { + let action = expression.evaluate(&mut context.clone(), _manage_memory)?; + let value = if let Evaluation::Return(value) = action { value } else { return Err(RuntimeError::ValidationFailure( @@ -187,7 +191,7 @@ impl AbstractNode for Logic { } }; - Ok(Action::Return(Value::boolean(boolean))) + Ok(Evaluation::Return(Value::boolean(boolean))) } } @@ -207,11 +211,11 @@ mod tests { fn equal() { assert_eq!( Logic::Equal( - ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))), - ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))) + Expression::Value(ValueNode::Integer(42).with_position((0, 0))), + Expression::Value(ValueNode::Integer(42).with_position((0, 0))) ) - .run(&mut Context::new(None), true), - Ok(Action::Return(Value::boolean(true))) + .evaluate(&mut Context::new(None), true), + Ok(Evaluation::Return(Value::boolean(true))) ) } @@ -219,11 +223,11 @@ mod tests { fn not_equal() { assert_eq!( Logic::NotEqual( - ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))), - ValueExpression::Value(ValueNode::Integer(43).with_position((0, 0))) + Expression::Value(ValueNode::Integer(42).with_position((0, 0))), + Expression::Value(ValueNode::Integer(43).with_position((0, 0))) ) - .run(&mut Context::new(None), true), - Ok(Action::Return(Value::boolean(true))) + .evaluate(&mut Context::new(None), true), + Ok(Evaluation::Return(Value::boolean(true))) ) } @@ -231,11 +235,11 @@ mod tests { fn greater() { assert_eq!( Logic::Greater( - ValueExpression::Value(ValueNode::Integer(43).with_position((0, 0))), - ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))) + Expression::Value(ValueNode::Integer(43).with_position((0, 0))), + Expression::Value(ValueNode::Integer(42).with_position((0, 0))) ) - .run(&mut Context::new(None), true), - Ok(Action::Return(Value::boolean(true))) + .evaluate(&mut Context::new(None), true), + Ok(Evaluation::Return(Value::boolean(true))) ) } @@ -243,11 +247,11 @@ mod tests { fn less() { assert_eq!( Logic::Less( - ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))), - ValueExpression::Value(ValueNode::Integer(43).with_position((0, 0))) + Expression::Value(ValueNode::Integer(42).with_position((0, 0))), + Expression::Value(ValueNode::Integer(43).with_position((0, 0))) ) - .run(&mut Context::new(None), true), - Ok(Action::Return(Value::boolean(true))) + .evaluate(&mut Context::new(None), true), + Ok(Evaluation::Return(Value::boolean(true))) ) } @@ -255,20 +259,20 @@ mod tests { fn greater_or_equal() { assert_eq!( Logic::GreaterOrEqual( - ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))), - ValueExpression::Value(ValueNode::Integer(41).with_position((0, 0))) + Expression::Value(ValueNode::Integer(42).with_position((0, 0))), + Expression::Value(ValueNode::Integer(41).with_position((0, 0))) ) - .run(&mut Context::new(None), true), - Ok(Action::Return(Value::boolean(true))) + .evaluate(&mut Context::new(None), true), + Ok(Evaluation::Return(Value::boolean(true))) ); assert_eq!( Logic::GreaterOrEqual( - ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))), - ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))), + Expression::Value(ValueNode::Integer(42).with_position((0, 0))), + Expression::Value(ValueNode::Integer(42).with_position((0, 0))), ) - .run(&mut Context::new(None), true), - Ok(Action::Return(Value::boolean(true))) + .evaluate(&mut Context::new(None), true), + Ok(Evaluation::Return(Value::boolean(true))) ); } @@ -276,20 +280,20 @@ mod tests { fn less_or_equal() { assert_eq!( Logic::LessOrEqual( - ValueExpression::Value(ValueNode::Integer(41).with_position((0, 0))), - ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))), + Expression::Value(ValueNode::Integer(41).with_position((0, 0))), + Expression::Value(ValueNode::Integer(42).with_position((0, 0))), ) - .run(&mut Context::new(None), true), - Ok(Action::Return(Value::boolean(true))) + .evaluate(&mut Context::new(None), true), + Ok(Evaluation::Return(Value::boolean(true))) ); assert_eq!( Logic::LessOrEqual( - ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))), - ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))), + Expression::Value(ValueNode::Integer(42).with_position((0, 0))), + Expression::Value(ValueNode::Integer(42).with_position((0, 0))), ) - .run(&mut Context::new(None), true), - Ok(Action::Return(Value::boolean(true))) + .evaluate(&mut Context::new(None), true), + Ok(Evaluation::Return(Value::boolean(true))) ); } @@ -297,11 +301,11 @@ mod tests { fn and() { assert_eq!( Logic::And( - ValueExpression::Value(ValueNode::Boolean(true).with_position((0, 0))), - ValueExpression::Value(ValueNode::Boolean(true).with_position((0, 0))), + Expression::Value(ValueNode::Boolean(true).with_position((0, 0))), + Expression::Value(ValueNode::Boolean(true).with_position((0, 0))), ) - .run(&mut Context::new(None), true), - Ok(Action::Return(Value::boolean(true))) + .evaluate(&mut Context::new(None), true), + Ok(Evaluation::Return(Value::boolean(true))) ) } @@ -309,22 +313,22 @@ mod tests { fn or() { assert_eq!( Logic::Or( - ValueExpression::Value(ValueNode::Boolean(true).with_position((0, 0))), - ValueExpression::Value(ValueNode::Boolean(false).with_position((0, 0))), + Expression::Value(ValueNode::Boolean(true).with_position((0, 0))), + Expression::Value(ValueNode::Boolean(false).with_position((0, 0))), ) - .run(&mut Context::new(None), true), - Ok(Action::Return(Value::boolean(true))) + .evaluate(&mut Context::new(None), true), + Ok(Evaluation::Return(Value::boolean(true))) ) } #[test] fn not() { assert_eq!( - Logic::Not(ValueExpression::Value( + Logic::Not(Expression::Value( ValueNode::Boolean(false).with_position((0, 0)) )) - .run(&mut Context::new(None), true), - Ok(Action::Return(Value::boolean(true))) + .evaluate(&mut Context::new(None), true), + Ok(Evaluation::Return(Value::boolean(true))) ) } } diff --git a/dust-lang/src/abstract_tree/loop.rs b/dust-lang/src/abstract_tree/loop.rs index 05652fa..543e377 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}; +use super::{AbstractNode, Evaluation, Statement}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct Loop { @@ -31,15 +31,19 @@ impl AbstractNode for Loop { Ok(()) } - fn run(self, _context: &mut Context, _manage_memory: bool) -> Result { + fn evaluate( + self, + _context: &mut Context, + _manage_memory: bool, + ) -> Result { loop { for statement in &self.statements { - let action = statement.clone().run(_context, false)?; + let action = statement.clone().evaluate(_context, false)?; match action { - Action::Return(_) => {} - Action::None => {} - Action::Break => return Ok(Action::Break), + Evaluation::Return(_) => {} + Evaluation::None => {} + Evaluation::Break => return Ok(Evaluation::Break), } } } diff --git a/dust-lang/src/abstract_tree/map_index.rs b/dust-lang/src/abstract_tree/map_index.rs index 5d609b3..9d553c7 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, ExpectedType, Type, ValueExpression, ValueNode, WithPosition}; +use super::{AbstractNode, Evaluation, ExpectedType, Expression, Type, ValueNode, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct MapIndex { - collection: ValueExpression, - index: ValueExpression, + collection: Expression, + index: Expression, } impl MapIndex { - pub fn new(left: ValueExpression, right: ValueExpression) -> Self { + pub fn new(left: Expression, right: Expression) -> Self { Self { collection: left, index: right, @@ -32,10 +32,14 @@ impl AbstractNode for MapIndex { self.collection.validate(_context, _manage_memory) } - fn run(self, context: &mut Context, _manage_memory: bool) -> Result { + fn evaluate( + self, + context: &mut Context, + _manage_memory: bool, + ) -> Result { let collection_position = self.collection.position(); - let action = self.collection.run(context, _manage_memory)?; - let collection = if let Action::Return(value) = action { + let action = self.collection.evaluate(context, _manage_memory)?; + let collection = if let Evaluation::Return(value) = action { value } else { return Err(RuntimeError::ValidationFailure( @@ -43,13 +47,13 @@ impl AbstractNode for MapIndex { )); }; - if let (ValueInner::Map(map), ValueExpression::Identifier(index)) = + if let (ValueInner::Map(map), Expression::Identifier(index)) = (collection.inner().as_ref(), self.index) { let action = map .get(&index.node) - .map(|value| Action::Return(value.clone())) - .unwrap_or(Action::None); + .map(|value| Evaluation::Return(value.clone())) + .unwrap_or(Evaluation::None); Ok(action) } else { @@ -65,7 +69,7 @@ impl AbstractNode for MapIndex { impl ExpectedType for MapIndex { fn expected_type(&self, context: &mut Context) -> Result { - if let (ValueExpression::Identifier(collection), ValueExpression::Identifier(index)) = + if let (Expression::Identifier(collection), Expression::Identifier(index)) = (&self.collection, &self.index) { let collection = if let Some(collection) = context.get_value(&collection.node)? { @@ -90,17 +94,19 @@ impl ExpectedType for MapIndex { } if let ( - ValueExpression::Value(WithPosition { + Expression::Value(WithPosition { node: ValueNode::Map(properties), .. }), - ValueExpression::Identifier(index), + Expression::Identifier(index), ) = (&self.collection, &self.index) { - for (property, type_option, expression) in properties { + for (property, constructor_option, expression) in properties { if property == &index.node { - return if let Some(r#type) = type_option { - Ok(r#type.node.clone()) + return if let Some(constructor) = constructor_option { + let r#type = constructor.node.clone().construct(&context)?; + + Ok(r#type) } else { Ok(expression.expected_type(context)?) }; @@ -111,15 +117,15 @@ impl ExpectedType for MapIndex { } if let ( - ValueExpression::Value(WithPosition { + Expression::Value(WithPosition { node: ValueNode::Structure { fields, .. }, .. }), - ValueExpression::Identifier(index), + Expression::Identifier(index), ) = (&self.collection, &self.index) { return if let Some(type_result) = fields.iter().find_map(|(property, expression)| { - if property == &index.node { + if property.node == index.node { Some(expression.expected_type(context)) } else { None diff --git a/dust-lang/src/abstract_tree/math.rs b/dust-lang/src/abstract_tree/math.rs index 40189b9..bd69a23 100644 --- a/dust-lang/src/abstract_tree/math.rs +++ b/dust-lang/src/abstract_tree/math.rs @@ -7,15 +7,15 @@ use crate::{ Value, }; -use super::{AbstractNode, Action, ExpectedType, SourcePosition, Type, ValueExpression}; +use super::{AbstractNode, Evaluation, ExpectedType, Expression, SourcePosition, Type}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub enum Math { - Add(ValueExpression, ValueExpression), - Subtract(ValueExpression, ValueExpression), - Multiply(ValueExpression, ValueExpression), - Divide(ValueExpression, ValueExpression), - Modulo(ValueExpression, ValueExpression), + Add(Expression, Expression), + Subtract(Expression, Expression), + Multiply(Expression, Expression), + Divide(Expression, Expression), + Modulo(Expression, Expression), } impl AbstractNode for Math { @@ -67,21 +67,24 @@ impl AbstractNode for Math { } } - fn run(self, _context: &mut Context, _clear_variables: bool) -> Result { - 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), - )); - }; + fn evaluate( + self, + _context: &mut Context, + _clear_variables: bool, + ) -> Result { + let run_and_expect_value = + |position: SourcePosition, expression: Expression| -> Result { + let action = expression.evaluate(&mut _context.clone(), _clear_variables)?; + let value = if let Evaluation::Return(value) = action { + value + } else { + return Err(RuntimeError::ValidationFailure( + ValidationError::InterpreterExpectedReturn(position), + )); + }; - Ok(value) - }; + Ok(value) + }; let value = match self { Math::Add(left, right) => { @@ -288,7 +291,7 @@ impl AbstractNode for Math { } }; - Ok(Action::Return(value)) + Ok(Evaluation::Return(value)) } } diff --git a/dust-lang/src/abstract_tree/mod.rs b/dust-lang/src/abstract_tree/mod.rs index ce3c764..657feba 100644 --- a/dust-lang/src/abstract_tree/mod.rs +++ b/dust-lang/src/abstract_tree/mod.rs @@ -14,6 +14,7 @@ pub mod statement; pub mod structure_definition; pub mod r#type; pub mod type_alias; +pub mod type_constructor; pub mod value_expression; pub mod value_node; pub mod r#while; @@ -41,7 +42,8 @@ pub use self::{ statement::Statement, structure_definition::StructureDefinition, type_alias::TypeAssignment, - value_expression::ValueExpression, + type_constructor::TypeConstructor, + value_expression::Expression, value_node::ValueNode, }; @@ -84,7 +86,7 @@ impl From<(usize, usize)> for SourcePosition { } #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)] -pub enum Action { +pub enum Evaluation { Return(Value), Break, None, @@ -114,12 +116,12 @@ impl AbstractTree { for statement in valid_statements { let position = statement.position(); - let run = statement.run(context, manage_memory); + let run = statement.evaluate(context, manage_memory); match run { Ok(action) => match action { - Action::Return(value) => previous_value = Some(value), - Action::None => previous_value = None, + Evaluation::Return(value) => previous_value = Some(value), + Evaluation::None => previous_value = None, _ => {} }, Err(runtime_error) => { @@ -153,7 +155,7 @@ impl AbstractTree { } else if errors.is_empty() { if let Statement::StructureDefinition(_) = statement { let position = statement.position(); - let run = statement.run(context, true); + let run = statement.evaluate(context, true); if let Err(runtime_error) = run { errors.push(Error::Runtime { @@ -189,7 +191,11 @@ impl Index for AbstractTree { pub trait AbstractNode: Sized { fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError>; - fn run(self, context: &mut Context, manage_memory: bool) -> Result; + fn evaluate( + self, + context: &mut Context, + manage_memory: bool, + ) -> Result; } pub trait ExpectedType { diff --git a/dust-lang/src/abstract_tree/statement.rs b/dust-lang/src/abstract_tree/statement.rs index d1f929e..b7c50b7 100644 --- a/dust-lang/src/abstract_tree/statement.rs +++ b/dust-lang/src/abstract_tree/statement.rs @@ -6,9 +6,8 @@ use crate::{ }; use super::{ - AbstractNode, Action, Assignment, AsyncBlock, Block, ExpectedType, IfElse, Loop, - SourcePosition, StructureDefinition, Type, TypeAssignment, ValueExpression, While, - WithPosition, + AbstractNode, Assignment, AsyncBlock, Block, Evaluation, ExpectedType, Expression, IfElse, + Loop, SourcePosition, StructureDefinition, Type, TypeAssignment, While, WithPosition, }; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] @@ -21,7 +20,7 @@ pub enum Statement { Loop(WithPosition), StructureDefinition(WithPosition), TypeAssignment(WithPosition), - ValueExpression(ValueExpression), + ValueExpression(Expression), While(WithPosition), } @@ -68,20 +67,26 @@ impl AbstractNode for Statement { } } - fn run(self, context: &mut Context, manage_memory: bool) -> Result { + fn evaluate( + self, + context: &mut Context, + manage_memory: bool, + ) -> Result { let result = match self { - 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::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::Assignment(assignment) => assignment.node.evaluate(context, manage_memory), + Statement::AsyncBlock(async_block) => async_block.node.evaluate(context, manage_memory), + Statement::Block(block) => block.node.evaluate(context, manage_memory), + Statement::Break(_) => Ok(Evaluation::Break), + Statement::ValueExpression(expression) => expression.evaluate(context, manage_memory), + Statement::IfElse(if_else) => if_else.node.evaluate(context, manage_memory), + Statement::Loop(r#loop) => r#loop.node.evaluate(context, manage_memory), Statement::StructureDefinition(structure_definition) => { - structure_definition.node.run(context, manage_memory) + structure_definition.node.evaluate(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), + Statement::TypeAssignment(type_alias) => { + type_alias.node.evaluate(context, manage_memory) + } + Statement::While(r#while) => r#while.node.evaluate(context, manage_memory), }; if manage_memory { diff --git a/dust-lang/src/abstract_tree/structure_definition.rs b/dust-lang/src/abstract_tree/structure_definition.rs index 8fe1b70..50f8f82 100644 --- a/dust-lang/src/abstract_tree/structure_definition.rs +++ b/dust-lang/src/abstract_tree/structure_definition.rs @@ -6,16 +6,16 @@ use crate::{ identifier::Identifier, }; -use super::{AbstractNode, Action, Type, WithPosition}; +use super::{AbstractNode, Evaluation, Type, TypeConstructor, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct StructureDefinition { name: Identifier, - fields: Vec<(Identifier, WithPosition)>, + fields: Vec<(Identifier, WithPosition)>, } impl StructureDefinition { - pub fn new(name: Identifier, fields: Vec<(Identifier, WithPosition)>) -> Self { + pub fn new(name: Identifier, fields: Vec<(Identifier, WithPosition)>) -> Self { Self { name, fields } } } @@ -29,14 +29,26 @@ impl AbstractNode for StructureDefinition { Ok(()) } - fn run(self, context: &mut Context, _manage_memory: bool) -> Result { + fn evaluate( + self, + context: &mut Context, + _manage_memory: bool, + ) -> Result { + let mut fields = Vec::with_capacity(self.fields.len()); + + for (identifier, constructor) in self.fields { + let r#type = constructor.node.construct(&context)?; + + fields.push((identifier, r#type)); + } + let struct_type = Type::Structure { name: self.name.clone(), - fields: self.fields, + fields, }; context.set_type(self.name, struct_type)?; - Ok(Action::None) + Ok(Evaluation::None) } } diff --git a/dust-lang/src/abstract_tree/type.rs b/dust-lang/src/abstract_tree/type.rs index c80dde8..03c8ebd 100644 --- a/dust-lang/src/abstract_tree/type.rs +++ b/dust-lang/src/abstract_tree/type.rs @@ -9,29 +9,31 @@ use crate::{ identifier::Identifier, }; -use super::{AbstractNode, Action, WithPosition}; +use super::{AbstractNode, Evaluation}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub enum Type { Any, - Argument(Identifier), Boolean, Float, Function { - parameter_types: Vec>, - return_type: Box>, + type_parameters: Option>, + value_parameters: Vec<(Identifier, Type)>, + return_type: Box, }, Integer, - List, - ListOf(Box>), - ListExact(Vec>), + List { + length: usize, + item_type: Box, + }, + ListOf(Box), Map, None, Range, String, Structure { name: Identifier, - fields: Vec<(Identifier, WithPosition)>, + fields: Vec<(Identifier, Type)>, }, } @@ -43,46 +45,15 @@ impl Type { | (Type::Boolean, Type::Boolean) | (Type::Float, Type::Float) | (Type::Integer, Type::Integer) - | (Type::List, Type::List) - | (Type::List, Type::ListOf(_)) - | (Type::List, Type::ListExact(_)) - | (Type::ListOf(_), Type::List) - | (Type::ListExact(_), Type::List) | (Type::Map, Type::Map) | (Type::None, Type::None) | (Type::Range, Type::Range) | (Type::String, Type::String) => return Ok(()), - (Type::Argument(left), Type::Argument(right)) => { - if left == right { - return Ok(()); - } - } (Type::ListOf(left), Type::ListOf(right)) => { - if let Ok(()) = left.node.check(&right.node) { + if let Ok(()) = left.check(&right) { return Ok(()); } } - (Type::ListOf(list_of), Type::ListExact(list_exact)) => { - for r#type in list_exact { - 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.node.check(&list_of.node)?; - } - - return Ok(()); - } - (Type::ListExact(left), Type::ListExact(right)) => { - for (left, right) in left.iter().zip(right.iter()) { - left.node.check(&right.node)?; - } - - return Ok(()); - } ( Type::Structure { name: left_name, @@ -97,8 +68,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.node != right_type.node - { + if left_field_name != right_field_name || left_type != right_type { return Err(TypeConflict { actual: other.clone(), expected: self.clone(), @@ -111,19 +81,33 @@ impl Type { } ( Type::Function { - parameter_types: left_parameters, + type_parameters: left_type_parameters, + value_parameters: left_value_parameters, return_type: left_return, }, Type::Function { - parameter_types: right_parameters, + type_parameters: right_type_parameters, + value_parameters: right_value_parameters, return_type: right_return, }, ) => { - if left_return.node == right_return.node { - for (left_parameter, right_parameter) in - left_parameters.iter().zip(right_parameters.iter()) + if left_return == right_return { + for (left_parameter, right_parameter) in left_type_parameters + .iter() + .zip(right_type_parameters.iter()) { - if left_parameter.node != right_parameter.node { + if left_parameter != right_parameter { + return Err(TypeConflict { + actual: other.clone(), + expected: self.clone(), + }); + } + } + for (left_parameter, right_parameter) in left_value_parameters + .iter() + .zip(right_value_parameters.iter()) + { + if left_parameter != right_parameter { return Err(TypeConflict { actual: other.clone(), expected: self.clone(), @@ -153,8 +137,12 @@ impl AbstractNode for Type { Ok(()) } - fn run(self, _context: &mut Context, _manage_memory: bool) -> Result { - Ok(Action::None) + fn evaluate( + self, + _context: &mut Context, + _manage_memory: bool, + ) -> Result { + Ok(Evaluation::None) } } @@ -165,47 +153,40 @@ impl Display for Type { Type::Boolean => write!(f, "bool"), Type::Float => write!(f, "float"), Type::Integer => write!(f, "int"), - Type::List => write!(f, "list"), - 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.node)?; - } else { - write!(f, "{}, ", item_type.node)?; - } - } - - write!(f, "]") - } + Type::List { length, item_type } => write!(f, "[{length}; {}]", item_type), + Type::ListOf(item_type) => write!(f, "list({})", item_type), Type::Map => write!(f, "map"), Type::None => write!(f, "none"), Type::Range => write!(f, "range"), Type::String => write!(f, "str"), Type::Function { - parameter_types, + type_parameters, + value_parameters, return_type, } => { write!(f, "(")?; - for r#type in parameter_types { - write!(f, "{} ", r#type.node)?; + if let Some(type_parameters) = type_parameters { + for identifier in type_parameters { + write!(f, "{} ", identifier)?; + } + + write!(f, ")(")?; } - write!(f, ") : {}", return_type.node) + for (identifier, r#type) in value_parameters { + write!(f, "{identifier}: {type}")?; + } + + write!(f, ") : {}", return_type) } Type::Structure { name, .. } => write!(f, "{name}"), - Type::Argument(identifier) => write!(f, "{identifier}"), } } } #[cfg(test)] mod tests { - use crate::abstract_tree::WithPos; - use super::*; #[test] @@ -214,18 +195,22 @@ mod tests { assert_eq!(Type::Boolean.check(&Type::Boolean), Ok(())); assert_eq!(Type::Float.check(&Type::Float), Ok(())); assert_eq!(Type::Integer.check(&Type::Integer), Ok(())); - assert_eq!(Type::List.check(&Type::List), Ok(())); assert_eq!( - Type::ListOf(Box::new(Type::Integer.with_position((0, 0)))) - .check(&Type::ListOf(Box::new(Type::Integer.with_position((0, 0))))), + Type::List { + length: 4, + item_type: Box::new(Type::Boolean), + } + .check(&Type::List { + length: 4, + item_type: Box::new(Type::Boolean), + }), + Ok(()) + ); + assert_eq!( + Type::ListOf(Box::new(Type::Integer)).check(&Type::ListOf(Box::new(Type::Integer))), Ok(()) ); - assert_eq!( - Type::ListExact(vec![Type::Float.with_position((0, 0))]) - .check(&Type::ListExact(vec![Type::Float.with_position((0, 0))])), - Ok(()) - ); assert_eq!(Type::Map.check(&Type::Map), Ok(())); assert_eq!(Type::None.check(&Type::None), Ok(())); assert_eq!(Type::Range.check(&Type::Range), Ok(())); @@ -257,9 +242,11 @@ mod tests { Type::Boolean, Type::Float, Type::Integer, - Type::List, - Type::ListOf(Box::new(Type::Boolean.with_position((0, 0)))), - Type::ListExact(vec![Type::Integer.with_position((0, 0))]), + Type::List { + length: 10, + item_type: Box::new(Type::Integer), + }, + Type::ListOf(Box::new(Type::Boolean)), Type::Map, Type::None, Type::Range, @@ -283,18 +270,13 @@ mod tests { #[test] fn check_list_types() { - let list = Type::List; - let list_exact = Type::ListExact(vec![ - Type::Integer.with_position((0, 0)), - Type::Integer.with_position((0, 0)), - ]); - let list_of = Type::ListOf(Box::new(Type::Integer.with_position((0, 0)))); + let list = Type::List { + length: 42, + item_type: Box::new(Type::Integer), + }; + let list_of = Type::ListOf(Box::new(Type::Integer)); - assert_eq!(list.check(&list_exact), Ok(())); assert_eq!(list.check(&list_of), Ok(())); - assert_eq!(list_exact.check(&list), Ok(())); - assert_eq!(list_exact.check(&list_of), Ok(())); assert_eq!(list_of.check(&list), Ok(())); - assert_eq!(list_of.check(&list_exact), Ok(())); } } diff --git a/dust-lang/src/abstract_tree/type_alias.rs b/dust-lang/src/abstract_tree/type_alias.rs index 606e060..4c1a682 100644 --- a/dust-lang/src/abstract_tree/type_alias.rs +++ b/dust-lang/src/abstract_tree/type_alias.rs @@ -6,17 +6,23 @@ use crate::{ identifier::Identifier, }; -use super::{AbstractNode, Action, Type, WithPosition}; +use super::{AbstractNode, Evaluation, TypeConstructor, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct TypeAssignment { identifier: WithPosition, - r#type: WithPosition, + constructor: WithPosition, } impl TypeAssignment { - pub fn new(identifier: WithPosition, r#type: WithPosition) -> Self { - Self { identifier, r#type } + pub fn new( + identifier: WithPosition, + constructor: WithPosition, + ) -> Self { + Self { + identifier, + constructor, + } } } @@ -29,9 +35,15 @@ impl AbstractNode for TypeAssignment { Ok(()) } - fn run(self, context: &mut Context, _manage_memory: bool) -> Result { - context.set_type(self.identifier.node, self.r#type.node)?; + fn evaluate( + self, + context: &mut Context, + _manage_memory: bool, + ) -> Result { + let r#type = self.constructor.node.construct(&context)?; - Ok(Action::None) + context.set_type(self.identifier.node, r#type)?; + + Ok(Evaluation::None) } } diff --git a/dust-lang/src/abstract_tree/type_constructor.rs b/dust-lang/src/abstract_tree/type_constructor.rs new file mode 100644 index 0000000..5643437 --- /dev/null +++ b/dust-lang/src/abstract_tree/type_constructor.rs @@ -0,0 +1,78 @@ +use std::fmt::{self, Display, Formatter}; + +use serde::{Deserialize, Serialize}; + +use crate::{context::Context, error::ValidationError, identifier::Identifier}; + +use super::{ExpectedType, Type, WithPosition}; + +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub enum TypeConstructor { + Function { + type_parameters: Option>>, + value_parameters: Vec<(WithPosition, Box>)>, + return_type: Box>, + }, + Identifier(WithPosition), + List { + length: usize, + item_type: Box>, + }, + ListOf(WithPosition>), + Type(Type), +} + +impl TypeConstructor { + pub fn validate( + &self, + _context: &mut Context, + _manage_memory: bool, + ) -> Result<(), ValidationError> { + todo!() + } + + pub fn construct(self, context: &Context) -> Result { + match self { + TypeConstructor::Function { + type_parameters: _, + value_parameters: _, + return_type: _, + } => todo!(), + TypeConstructor::Identifier(WithPosition { + node: identifier, + position, + }) => { + if let Some(r#type) = context.get_type(&identifier)? { + Ok(r#type) + } else { + Err(ValidationError::VariableNotFound { + identifier, + position, + }) + } + } + TypeConstructor::List { length, item_type } => { + let constructed_type = item_type.node.construct(context)?; + + Ok(Type::List { + length, + item_type: Box::new(constructed_type), + }) + } + TypeConstructor::Type(r#type) => Ok(r#type), + TypeConstructor::ListOf(_) => todo!(), + } + } +} + +impl ExpectedType for TypeConstructor { + fn expected_type(&self, _: &mut Context) -> Result { + Ok(Type::None) + } +} + +impl Display for TypeConstructor { + fn fmt(&self, _: &mut Formatter) -> fmt::Result { + todo!() + } +} diff --git a/dust-lang/src/abstract_tree/value_expression.rs b/dust-lang/src/abstract_tree/value_expression.rs index 4f3b076..a43e030 100644 --- a/dust-lang/src/abstract_tree/value_expression.rs +++ b/dust-lang/src/abstract_tree/value_expression.rs @@ -7,12 +7,12 @@ use crate::{ }; use super::{ - AbstractNode, Action, As, BuiltInFunctionCall, ExpectedType, FunctionCall, ListIndex, Logic, - MapIndex, Math, SourcePosition, Type, ValueNode, WithPosition, + AbstractNode, As, BuiltInFunctionCall, Evaluation, ExpectedType, FunctionCall, ListIndex, + Logic, MapIndex, Math, SourcePosition, Type, ValueNode, WithPosition, }; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] -pub enum ValueExpression { +pub enum Expression { As(WithPosition>), BuiltInFunctionCall(WithPosition>), FunctionCall(WithPosition), @@ -24,30 +24,30 @@ pub enum ValueExpression { Value(WithPosition), } -impl ValueExpression { +impl Expression { 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, + 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 ValueExpression { +impl AbstractNode for Expression { 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) => { + Expression::As(r#as) => r#as.node.validate(context, manage_memory), + Expression::FunctionCall(function_call) => { function_call.node.validate(context, manage_memory) } - ValueExpression::Identifier(identifier) => { + Expression::Identifier(identifier) => { let found = if manage_memory { context.add_expected_use(&identifier.node)? } else { @@ -63,26 +63,28 @@ impl AbstractNode for ValueExpression { }) } } - 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) => { + Expression::MapIndex(map_index) => map_index.node.validate(context, manage_memory), + Expression::ListIndex(list_index) => list_index.node.validate(context, manage_memory), + Expression::Logic(logic) => logic.node.validate(context, manage_memory), + Expression::Math(math) => math.node.validate(context, manage_memory), + Expression::Value(value_node) => value_node.node.validate(context, manage_memory), + Expression::BuiltInFunctionCall(built_in_function_call) => { built_in_function_call.node.validate(context, manage_memory) } } } - fn run(self, context: &mut Context, manage_memory: bool) -> Result { + fn evaluate( + 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) + Expression::As(r#as) => r#as.node.evaluate(context, manage_memory), + Expression::FunctionCall(function_call) => { + function_call.node.evaluate(context, manage_memory) } - ValueExpression::Identifier(identifier) => { + Expression::Identifier(identifier) => { let value_option = if manage_memory { context.use_value(&identifier.node)? } else { @@ -90,7 +92,7 @@ impl AbstractNode for ValueExpression { }; if let Some(value) = value_option { - Ok(Action::Return(value)) + Ok(Evaluation::Return(value)) } else { Err(RuntimeError::ValidationFailure( ValidationError::VariableNotFound { @@ -100,26 +102,24 @@ impl AbstractNode for ValueExpression { )) } } - 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) + Expression::MapIndex(map_index) => map_index.node.evaluate(context, manage_memory), + Expression::ListIndex(list_index) => list_index.node.evaluate(context, manage_memory), + Expression::Logic(logic) => logic.node.evaluate(context, manage_memory), + Expression::Math(math) => math.node.evaluate(context, manage_memory), + Expression::Value(value_node) => value_node.node.evaluate(context, manage_memory), + Expression::BuiltInFunctionCall(built_in_function_call) => { + built_in_function_call.node.evaluate(context, manage_memory) } } } } -impl ExpectedType for ValueExpression { +impl ExpectedType for Expression { 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) => { + Expression::As(r#as) => r#as.node.expected_type(_context), + Expression::FunctionCall(function_call) => function_call.node.expected_type(_context), + Expression::Identifier(identifier) => { if let Some(r#type) = _context.get_type(&identifier.node)? { Ok(r#type) } else { @@ -129,12 +129,12 @@ impl ExpectedType for ValueExpression { }) } } - 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) => { + Expression::MapIndex(map_index) => map_index.node.expected_type(_context), + Expression::ListIndex(list_index) => list_index.node.expected_type(_context), + Expression::Logic(logic) => logic.node.expected_type(_context), + Expression::Math(math) => math.node.expected_type(_context), + Expression::Value(value_node) => value_node.node.expected_type(_context), + Expression::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 8bbdd6a..64227ee 100644 --- a/dust-lang/src/abstract_tree/value_node.rs +++ b/dust-lang/src/abstract_tree/value_node.rs @@ -10,7 +10,7 @@ use crate::{ }; use super::{ - AbstractNode, Action, Block, ExpectedType, Type, ValueExpression, WithPos, WithPosition, + AbstractNode, Block, Evaluation, ExpectedType, Expression, Type, TypeConstructor, WithPosition, }; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] @@ -18,18 +18,24 @@ pub enum ValueNode { Boolean(bool), Float(f64), Integer(i64), - List(Vec), - Map(Vec<(Identifier, Option>, ValueExpression)>), + List(Vec), + Map( + Vec<( + Identifier, + Option>, + Expression, + )>, + ), Range(Range), String(String), Structure { name: WithPosition, - fields: Vec<(Identifier, ValueExpression)>, + fields: Vec<(WithPosition, Expression)>, }, ParsedFunction { - type_arguments: Vec>, - parameters: Vec<(Identifier, WithPosition)>, - return_type: WithPosition, + type_parameters: Option>>, + value_parameters: Vec<(Identifier, WithPosition)>, + return_type: WithPosition, body: WithPosition, }, } @@ -37,17 +43,18 @@ pub enum ValueNode { impl AbstractNode for ValueNode { 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 { + for (_identifier, constructor_option, expression) in map_assignments { expression.validate(context, _manage_memory)?; - if let Some(expected_type) = r#type { + if let Some(constructor) = constructor_option { let actual_type = expression.expected_type(context)?; + let exprected_type = constructor.node.clone().construct(&context)?; - expected_type.node.check(&actual_type).map_err(|conflict| { + exprected_type.check(&actual_type).map_err(|conflict| { ValidationError::TypeCheck { conflict, actual_position: expression.position(), - expected_position: expected_type.position, + expected_position: Some(constructor.position), } })?; } @@ -57,22 +64,18 @@ impl AbstractNode for ValueNode { } if let ValueNode::ParsedFunction { - type_arguments, - parameters, + type_parameters: _, + value_parameters, return_type, body, } = self { let mut function_context = Context::new(Some(&context)); - for r#type in type_arguments { - if let Type::Argument(identifier) = &r#type.node { - function_context.set_type(identifier.clone(), r#type.node.clone())?; - } - } + for (identifier, type_constructor) in value_parameters { + let r#type = type_constructor.node.clone().construct(&function_context)?; - for (identifier, r#type) in parameters { - function_context.set_type(identifier.clone(), r#type.node.clone())?; + function_context.set_type(identifier.clone(), r#type)?; } body.node.validate(&mut function_context, _manage_memory)?; @@ -81,11 +84,13 @@ impl AbstractNode for ValueNode { return_type .node + .clone() + .construct(&function_context)? .check(&actual_return_type) .map_err(|conflict| ValidationError::TypeCheck { conflict, actual_position: body.position, - expected_position: return_type.position, + expected_position: Some(return_type.position), })?; return Ok(()); @@ -111,11 +116,11 @@ impl AbstractNode for ValueNode { for ((_, expression), (_, expected_type)) in expressions.iter().zip(types.iter()) { let actual_type = expression.expected_type(context)?; - expected_type.node.check(&actual_type).map_err(|conflict| { + expected_type.check(&actual_type).map_err(|conflict| { ValidationError::TypeCheck { conflict, actual_position: expression.position(), - expected_position: expected_type.position, + expected_position: None, } })? } @@ -125,7 +130,11 @@ impl AbstractNode for ValueNode { Ok(()) } - fn run(self, _context: &mut Context, _manage_memory: bool) -> Result { + fn evaluate( + self, + context: &mut Context, + _manage_memory: bool, + ) -> Result { let value = match self { ValueNode::Boolean(boolean) => Value::boolean(boolean), ValueNode::Float(float) => Value::float(float), @@ -135,8 +144,8 @@ impl AbstractNode for ValueNode { for expression in expression_list { let expression_position = expression.position(); - let action = expression.run(_context, _manage_memory)?; - let value = if let Action::Return(value) = action { + let action = expression.evaluate(context, _manage_memory)?; + let value = if let Evaluation::Return(value) = action { WithPosition { node: value, position: expression_position, @@ -157,8 +166,8 @@ impl AbstractNode for ValueNode { for (identifier, _type, expression) in property_list { let expression_position = expression.position(); - let action = expression.run(_context, _manage_memory)?; - let value = if let Action::Return(value) = action { + let action = expression.evaluate(context, _manage_memory)?; + let value = if let Evaluation::Return(value) = action { value } else { return Err(RuntimeError::ValidationFailure( @@ -174,11 +183,29 @@ impl AbstractNode for ValueNode { ValueNode::Range(range) => Value::range(range), ValueNode::String(string) => Value::string(string), ValueNode::ParsedFunction { - type_arguments, - parameters, + type_parameters, + value_parameters: constructors, return_type, body, - } => Value::function(type_arguments, parameters, return_type, body), + } => { + let type_parameters = type_parameters.map(|parameter_list| { + parameter_list + .into_iter() + .map(|parameter| parameter.node) + .collect() + }); + let mut value_parameters = Vec::with_capacity(constructors.len()); + + for (identifier, constructor) in constructors { + let r#type = constructor.node.construct(&context)?; + + value_parameters.push((identifier, r#type)); + } + + let return_type = return_type.node.construct(&context)?; + + Value::function(type_parameters, value_parameters, return_type, body.node) + } ValueNode::Structure { name, fields: expressions, @@ -187,8 +214,8 @@ impl AbstractNode for ValueNode { for (identifier, expression) in expressions { let expression_position = expression.position(); - let action = expression.run(_context, _manage_memory)?; - let value = if let Action::Return(value) = action { + let action = expression.evaluate(context, _manage_memory)?; + let value = if let Evaluation::Return(value) = action { value } else { return Err(RuntimeError::ValidationFailure( @@ -196,14 +223,14 @@ impl AbstractNode for ValueNode { )); }; - fields.push((identifier, value)); + fields.push((identifier.node, value)); } Value::structure(name, fields) } }; - Ok(Action::Return(value)) + Ok(Evaluation::Return(value)) } } @@ -244,14 +271,14 @@ impl Ord for ValueNode { (String(_), _) => Ordering::Greater, ( ParsedFunction { - type_arguments: left_type_arguments, - parameters: left_parameters, + type_parameters: left_type_arguments, + value_parameters: left_parameters, return_type: left_return, body: left_body, }, ParsedFunction { - type_arguments: right_type_arguments, - parameters: right_parameters, + type_parameters: right_type_arguments, + value_parameters: right_parameters, return_type: right_return, body: right_body, }, @@ -307,32 +334,44 @@ impl ExpectedType for ValueNode { ValueNode::Float(_) => Type::Float, ValueNode::Integer(_) => Type::Integer, ValueNode::List(items) => { - let mut item_types = Vec::with_capacity(items.len()); + let item_type = items.first().unwrap().expected_type(context)?; - for expression in items { - item_types.push( - expression - .expected_type(context)? - .with_position(expression.position()), - ); + Type::List { + length: items.len(), + item_type: Box::new(item_type), } - - Type::ListExact(item_types) } ValueNode::Map(_) => Type::Map, ValueNode::Range(_) => Type::Range, ValueNode::String(_) => Type::String, ValueNode::ParsedFunction { - parameters, + type_parameters, + value_parameters, return_type, .. - } => Type::Function { - parameter_types: parameters - .iter() - .map(|(_, r#type)| r#type.clone()) - .collect(), - return_type: Box::new(return_type.clone()), - }, + } => { + let mut value_parameter_types = Vec::with_capacity(value_parameters.len()); + + for (identifier, type_constructor) in value_parameters { + let r#type = type_constructor.node.clone().construct(&context)?; + + value_parameter_types.push((identifier.clone(), r#type)); + } + + let type_parameters = type_parameters.clone().map(|parameters| { + parameters + .iter() + .map(|identifier| identifier.node.clone()) + .collect() + }); + let return_type = return_type.node.clone().construct(&context)?; + + Type::Function { + type_parameters, + value_parameters: value_parameter_types, + return_type: Box::new(return_type), + } + } ValueNode::Structure { name, fields: expressions, @@ -353,7 +392,10 @@ impl ExpectedType for ValueNode { Type::Structure { name: name.node.clone(), - fields: types, + fields: types + .into_iter() + .map(|(identifier, r#type)| (identifier.node, r#type.node)) + .collect(), } } }; diff --git a/dust-lang/src/abstract_tree/while.rs b/dust-lang/src/abstract_tree/while.rs index 8236332..eeea140 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, Statement, ValueExpression}; +use super::{AbstractNode, Evaluation, Expression, Statement}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct While { - expression: ValueExpression, + expression: Expression, statements: Vec, } impl While { - pub fn new(expression: ValueExpression, statements: Vec) -> Self { + pub fn new(expression: Expression, statements: Vec) -> Self { Self { expression, statements, @@ -39,12 +39,19 @@ impl AbstractNode for While { Ok(()) } - fn run(self, _context: &mut Context, _manage_memory: bool) -> Result { + fn evaluate( + self, + _context: &mut Context, + _manage_memory: bool, + ) -> Result { let get_boolean = || -> Result { let expression_position = self.expression.position(); - let action = self.expression.clone().run(&mut _context.clone(), false)?; + let action = self + .expression + .clone() + .evaluate(&mut _context.clone(), false)?; - if let Action::Return(value) = action { + if let Evaluation::Return(value) = action { Ok(value) } else { Err(RuntimeError::ValidationFailure( @@ -55,16 +62,16 @@ impl AbstractNode for While { while let ValueInner::Boolean(true) = get_boolean()?.inner().as_ref() { for statement in &self.statements { - let action = statement.clone().run(&mut _context.clone(), false)?; + let action = statement.clone().evaluate(&mut _context.clone(), false)?; match action { - Action::Return(_) => {} - Action::None => {} - Action::Break => return Ok(Action::Break), + Evaluation::Return(_) => {} + Evaluation::None => {} + Evaluation::Break => return Ok(Evaluation::Break), } } } - Ok(Action::None) + Ok(Evaluation::None) } } diff --git a/dust-lang/src/context.rs b/dust-lang/src/context.rs index a7f71fa..c1d1b50 100644 --- a/dust-lang/src/context.rs +++ b/dust-lang/src/context.rs @@ -12,7 +12,7 @@ use crate::{ #[derive(Clone, Debug)] pub struct Context<'a> { - variables: Arc>>, + variables: Arc>>, parent: Option<&'a Context<'a>>, is_clean: Arc>, } @@ -28,7 +28,7 @@ impl<'a> Context<'a> { pub fn inner( &self, - ) -> Result>, RwLockPoisonError> + ) -> Result>, RwLockPoisonError> { Ok(self.variables.read()?) } @@ -50,8 +50,8 @@ impl<'a> Context<'a> { log::trace!("Getting {identifier}'s type."); let r#type = match value_data { - ValueData::Type(r#type) => r#type.clone(), - ValueData::Value(value) => value.r#type(self)?, + VariableData::Type(r#type) => r#type.clone(), + VariableData::Value(value) => value.r#type(self)?, }; Ok(Some(r#type.clone())) @@ -63,7 +63,8 @@ impl<'a> Context<'a> { } pub fn use_value(&self, identifier: &Identifier) -> Result, RwLockPoisonError> { - if let Some((ValueData::Value(value), usage_data)) = self.variables.read()?.get(identifier) + if let Some((VariableData::Value(value), usage_data)) = + self.variables.read()?.get(identifier) { log::trace!("Using {identifier}'s value."); @@ -79,7 +80,7 @@ impl<'a> Context<'a> { } pub fn get_value(&self, identifier: &Identifier) -> Result, RwLockPoisonError> { - if let Some((ValueData::Value(value), _)) = self.variables.read()?.get(identifier) { + if let Some((VariableData::Value(value), _)) = self.variables.read()?.get(identifier) { log::trace!("Getting {identifier}'s value."); Ok(Some(value.clone())) @@ -93,7 +94,7 @@ impl<'a> Context<'a> { pub fn get_data( &self, identifier: &Identifier, - ) -> Result, RwLockPoisonError> { + ) -> Result, RwLockPoisonError> { if let Some(full_data) = self.variables.read()?.get(identifier) { log::trace!("Getting {identifier}'s value."); @@ -110,7 +111,7 @@ impl<'a> Context<'a> { self.variables .write()? - .insert(identifier, (ValueData::Type(r#type), UsageData::new())); + .insert(identifier, (VariableData::Type(r#type), UsageData::new())); Ok(()) } @@ -128,9 +129,9 @@ impl<'a> Context<'a> { .map(|(_, usage_data)| usage_data); if let Some(usage_data) = old_usage_data { - variables.insert(identifier, (ValueData::Value(value), usage_data)); + variables.insert(identifier, (VariableData::Value(value), usage_data)); } else { - variables.insert(identifier, (ValueData::Value(value), UsageData::new())); + variables.insert(identifier, (VariableData::Value(value), UsageData::new())); } Ok(()) @@ -144,7 +145,7 @@ impl<'a> Context<'a> { self.variables .write()? .retain(|identifier, (value_data, usage_data)| { - if let ValueData::Value(_) = value_data { + if let VariableData::Value(_) = value_data { let usage = usage_data.inner().read().unwrap(); if usage.actual < usage.expected { @@ -196,7 +197,7 @@ impl<'a> Context<'a> { } #[derive(Clone, Debug, PartialEq)] -pub enum ValueData { +pub enum VariableData { Type(Type), Value(Value), } diff --git a/dust-lang/src/error.rs b/dust-lang/src/error.rs index c85d175..b392a08 100644 --- a/dust-lang/src/error.rs +++ b/dust-lang/src/error.rs @@ -3,7 +3,7 @@ use std::{io, sync::PoisonError}; use chumsky::{prelude::Rich, span::Span}; use crate::{ - abstract_tree::{SourcePosition, Type}, + abstract_tree::{r#type::Type, SourcePosition, TypeConstructor}, identifier::Identifier, lexer::Token, }; @@ -141,11 +141,15 @@ pub enum ValidationError { actual_position: SourcePosition, /// The position of the item that gave the "expected" type. - expected_position: SourcePosition, + expected_position: Option, + }, + WrongTypeArgumentCount { + expected: usize, + actual: usize, }, WrongArguments { - expected: Vec, - actual: Vec, + expected: Vec, + actual: Vec, }, VariableNotFound { identifier: Identifier, diff --git a/dust-lang/src/lib.rs b/dust-lang/src/lib.rs index fff73d9..e57b9cc 100644 --- a/dust-lang/src/lib.rs +++ b/dust-lang/src/lib.rs @@ -325,21 +325,23 @@ impl InterpreterError { } => { let TypeConflict { actual, expected } = conflict; - builder.add_labels([ - Label::new(( - self.source_id.clone(), - expected_position.0..expected_position.1, - )) - .with_message(format!( - "Type {} established here.", - expected.fg(type_color) - )), + if let Some(position) = expected_position { + builder.add_label( + Label::new((self.source_id.clone(), position.0..position.1)) + .with_message(format!( + "Type {} established here.", + expected.fg(type_color) + )), + ) + } + + builder.add_label( Label::new(( self.source_id.clone(), actual_position.0..actual_position.1, )) .with_message(format!("Got type {} here.", actual.fg(type_color))), - ]); + ); } ValidationError::VariableNotFound { identifier, @@ -390,6 +392,7 @@ impl InterpreterError { ValidationError::ExpectedValue(_) => todo!(), ValidationError::PropertyNotFound { .. } => todo!(), ValidationError::WrongArguments { .. } => todo!(), + ValidationError::WrongTypeArgumentCount { .. } => todo!(), ValidationError::ExpectedIntegerFloatOrString { actual, position } => { builder = builder.with_message(format!( "Expected an {}, {} or {}.", diff --git a/dust-lang/src/parser.rs b/dust-lang/src/parser.rs index 1102220..0a2c988 100644 --- a/dust-lang/src/parser.rs +++ b/dust-lang/src/parser.rs @@ -1,4 +1,4 @@ -use std::{cell::RefCell, collections::HashMap, rc::Rc}; +use std::{cell::RefCell, collections::HashMap}; use chumsky::{input::SpannedInput, pratt::*, prelude::*}; @@ -32,10 +32,6 @@ pub fn parser<'src>( allow_built_ins: bool, ) -> impl Parser<'src, ParserInput<'src>, Vec, ParserExtra<'src>> { let identifiers: RefCell> = RefCell::new(HashMap::new()); - let _custom_types: Rc>> = - Rc::new(RefCell::new(HashMap::new())); - let custom_types = (_custom_types.clone(), _custom_types.clone()); - let identifier = select! { Token::Identifier(text) => { let mut identifiers = identifiers.borrow_mut(); @@ -62,98 +58,99 @@ pub fn parser<'src>( Token::Integer(integer) => ValueNode::Integer(integer), Token::String(text) => ValueNode::String(text.to_string()), } - .map_with(|value, state| ValueExpression::Value(value.with_position(state.span()))); + .map_with(|value, state| Expression::Value(value.with_position(state.span()))); + + let raw_integer = select! { + Token::Integer(integer) => integer + }; + + let type_constructor = recursive(|type_constructor| { + let positioned_type_constructor = + type_constructor + .clone() + .map_with(|constructor: TypeConstructor, state| { + constructor.with_position(state.span()) + }); + + let primitive_type = choice(( + just(Token::Keyword(Keyword::Any)).to(Type::Any), + just(Token::Keyword(Keyword::Bool)).to(Type::Boolean), + just(Token::Keyword(Keyword::Float)).to(Type::Float), + just(Token::Keyword(Keyword::Int)).to(Type::Integer), + just(Token::Keyword(Keyword::None)).to(Type::None), + just(Token::Keyword(Keyword::Range)).to(Type::Range), + just(Token::Keyword(Keyword::Str)).to(Type::String), + )) + .map(|r#type| TypeConstructor::Type(r#type)); - let r#type = recursive(|r#type| { let function_type = just(Token::Keyword(Keyword::Fn)) .ignore_then( - r#type + positioned_identifier .clone() .separated_by(just(Token::Control(Control::Comma))) .collect() + .delimited_by( + just(Token::Control(Control::ParenOpen)), + just(Token::Control(Control::ParenClose)), + ) + .or_not(), + ) + .then( + positioned_identifier + .clone() + .then_ignore(just(Token::Control(Control::Colon))) + .then(type_constructor.clone().map_with(|constructor, state| { + Box::new(constructor.with_position(state.span())) + })) + .separated_by(just(Token::Control(Control::Comma))) + .collect() .delimited_by( just(Token::Control(Control::ParenOpen)), just(Token::Control(Control::ParenClose)), ), ) .then_ignore(just(Token::Control(Control::SkinnyArrow))) - .then(r#type.clone()) - .map(|(parameter_types, return_type)| Type::Function { - parameter_types, - return_type: Box::new(return_type), - }); + .then(positioned_type_constructor.clone()) + .map( + |((type_parameters, value_parameters), return_type)| TypeConstructor::Function { + type_parameters, + value_parameters, + return_type: Box::new(return_type), + }, + ); - let list_of = just(Token::Keyword(Keyword::List)) - .ignore_then(r#type.clone().delimited_by( - just(Token::Control(Control::ParenOpen)), - just(Token::Control(Control::ParenClose)), - )) - .map(|item_type| Type::ListOf(Box::new(item_type))); - - let list_exact = r#type + let list = positioned_type_constructor .clone() - .separated_by(just(Token::Control(Control::Comma))) - .collect() + .clone() + .then_ignore(just(Token::Control(Control::Semicolon))) + .then(raw_integer.clone()) .delimited_by( just(Token::Control(Control::SquareOpen)), just(Token::Control(Control::SquareClose)), ) - .map(|types| Type::ListExact(types)); + .map(|(item_type, length)| TypeConstructor::List { + length: length as usize, + item_type: Box::new(item_type), + }); - choice(( - function_type, - list_of, - list_exact, - just(Token::Keyword(Keyword::Any)).to(Type::Any), - just(Token::Keyword(Keyword::Bool)).to(Type::Boolean), - just(Token::Keyword(Keyword::Float)).to(Type::Float), - just(Token::Keyword(Keyword::Int)).to(Type::Integer), - just(Token::Keyword(Keyword::None)).to(Type::None), - just(Token::Keyword(Keyword::Range)).to(Type::Range), - just(Token::Keyword(Keyword::Str)).to(Type::String), - just(Token::Keyword(Keyword::List)).to(Type::List), - identifier.clone().map(move |identifier| { - if let Some(r#type) = custom_types.0.borrow().get(&identifier) { - r#type.clone() - } else { - Type::Argument(identifier) - } - }), - )) - .map_with(|r#type, state| r#type.with_position(state.span())) + let list_of = just(Token::Keyword(Keyword::List)) + .ignore_then(type_constructor.clone().delimited_by( + just(Token::Control(Control::ParenOpen)), + just(Token::Control(Control::ParenClose)), + )) + .map_with(|item_type, state| { + TypeConstructor::ListOf(Box::new(item_type).with_position(state.span())) + }); + + choice((function_type, list, list_of, primitive_type)) }); - let type_argument = identifier + let positioned_type_constructor = type_constructor .clone() - .map_with(|identifier, state| Type::Argument(identifier).with_position(state.span())); + .map_with(|constructor: TypeConstructor, state| constructor.with_position(state.span())); - let type_specification = just(Token::Control(Control::Colon)).ignore_then(r#type.clone()); - - let structure_field_definition = identifier.clone().then(type_specification.clone()); - - let structure_definition = just(Token::Keyword(Keyword::Struct)) - .ignore_then(identifier.clone()) - .then( - structure_field_definition - .separated_by(just(Token::Control(Control::Comma))) - .allow_trailing() - .collect::)>>() - .delimited_by( - just(Token::Control(Control::CurlyOpen)), - just(Token::Control(Control::CurlyClose)), - ), - ) - .map_with(move |(name, fields), state| { - let definition = StructureDefinition::new(name.clone(), fields.clone()); - let r#type = Type::Structure { - name: name.clone(), - fields, - }; - - custom_types.1.borrow_mut().insert(name, r#type); - - Statement::StructureDefinition(definition.with_position(state.span())) - }); + let type_specification = + just(Token::Control(Control::Colon)).ignore_then(positioned_type_constructor.clone()); let statement = recursive(|statement| { let allow_built_ins = allow_built_ins.clone(); @@ -173,19 +170,15 @@ pub fn parser<'src>( let allow_built_ins = allow_built_ins.clone(); let identifier_expression = identifier.clone().map_with(|identifier, state| { - ValueExpression::Identifier(identifier.with_position(state.span())) + Expression::Identifier(identifier.with_position(state.span())) }); - let raw_integer = select! { - Token::Integer(integer) => integer - }; - let range = raw_integer .clone() .then_ignore(just(Token::Control(Control::DoubleDot))) .then(raw_integer) .map_with(|(start, end), state| { - ValueExpression::Value(ValueNode::Range(start..end).with_position(state.span())) + Expression::Value(ValueNode::Range(start..end).with_position(state.span())) }); let list = expression @@ -198,63 +191,41 @@ pub fn parser<'src>( just(Token::Control(Control::SquareClose)), ) .map_with(|list, state| { - ValueExpression::Value(ValueNode::List(list).with_position(state.span())) + Expression::Value(ValueNode::List(list).with_position(state.span())) }); - let map_assignment = identifier - .clone() - .then(type_specification.clone().or_not()) - .then_ignore(just(Token::Operator(Operator::Assign))) - .then(expression.clone()) - .map(|((identifier, r#type), expression)| (identifier, r#type, expression)); - - let map = map_assignment - .separated_by(just(Token::Control(Control::Comma)).or_not()) - .allow_trailing() - .collect() - .delimited_by( - just(Token::Control(Control::CurlyOpen)), - just(Token::Control(Control::CurlyClose)), - ) - .map_with(|map_assigment_list, state| { - ValueExpression::Value( - ValueNode::Map(map_assigment_list).with_position(state.span()), - ) - }); - - let type_arguments = type_argument - .clone() - .separated_by(just(Token::Control(Control::Comma))) - .at_least(1) - .collect() - .delimited_by( - just(Token::Control(Control::ParenOpen)), - just(Token::Control(Control::ParenClose)), - ); - let parsed_function = just(Token::Keyword(Keyword::Fn)) .ignore_then( - type_arguments.or_not().then( - identifier - .clone() - .then(type_specification.clone()) - .separated_by(just(Token::Control(Control::Comma))) - .collect() - .delimited_by( - just(Token::Control(Control::ParenOpen)), - just(Token::Control(Control::ParenClose)), - ) - .then(r#type.clone()) - .then(block.clone()), - ), + positioned_identifier + .clone() + .separated_by(just(Token::Control(Control::Comma))) + .collect() + .delimited_by( + just(Token::Control(Control::ParenOpen)), + just(Token::Control(Control::ParenClose)), + ) + .or_not(), ) + .then( + identifier + .then_ignore(just(Token::Control(Control::Colon))) + .then(positioned_type_constructor.clone()) + .separated_by(just(Token::Control(Control::Comma))) + .collect() + .delimited_by( + just(Token::Control(Control::ParenOpen)), + just(Token::Control(Control::ParenClose)), + ), + ) + .then_ignore(just(Token::Control(Control::SkinnyArrow))) + .then(positioned_type_constructor.clone()) + .then(block.clone()) .map_with( - |(type_arguments, ((parameters, return_type), body)), state| { - ValueExpression::Value( + |(((type_parameters, value_parameters), return_type), body), state| { + Expression::Value( ValueNode::ParsedFunction { - type_arguments: type_arguments - .unwrap_or_else(|| Vec::with_capacity(0)), - parameters, + type_parameters, + value_parameters, return_type, body, } @@ -267,7 +238,7 @@ pub fn parser<'src>( just(Token::Keyword(Keyword::Length)) .ignore_then(expression.clone()) .map_with(|argument, state| { - ValueExpression::BuiltInFunctionCall( + Expression::BuiltInFunctionCall( Box::new(BuiltInFunctionCall::Length(argument)) .with_position(state.span()), ) @@ -275,20 +246,20 @@ pub fn parser<'src>( just(Token::Keyword(Keyword::ReadFile)) .ignore_then(expression.clone()) .map_with(|argument, state| { - ValueExpression::BuiltInFunctionCall( + Expression::BuiltInFunctionCall( Box::new(BuiltInFunctionCall::ReadFile(argument)) .with_position(state.span()), ) }), just(Token::Keyword(Keyword::ReadLine)).map_with(|_, state| { - ValueExpression::BuiltInFunctionCall( + Expression::BuiltInFunctionCall( Box::new(BuiltInFunctionCall::ReadLine).with_position(state.span()), ) }), just(Token::Keyword(Keyword::Sleep)) .ignore_then(expression.clone()) .map_with(|argument, state| { - ValueExpression::BuiltInFunctionCall( + Expression::BuiltInFunctionCall( Box::new(BuiltInFunctionCall::Sleep(argument)) .with_position(state.span()), ) @@ -296,17 +267,17 @@ pub fn parser<'src>( just(Token::Keyword(Keyword::WriteLine)) .ignore_then(expression.clone()) .map_with(|argument, state| { - ValueExpression::BuiltInFunctionCall( + Expression::BuiltInFunctionCall( Box::new(BuiltInFunctionCall::WriteLine(argument)) .with_position(state.span()), ) }), just(Token::Keyword(Keyword::JsonParse)) - .ignore_then(r#type.clone()) + .ignore_then(type_constructor.clone()) .then(expression.clone()) - .map_with(|(r#type, argument), state| { - ValueExpression::BuiltInFunctionCall( - Box::new(BuiltInFunctionCall::JsonParse(r#type, argument)) + .map_with(|(constructor, argument), state| { + Expression::BuiltInFunctionCall( + Box::new(BuiltInFunctionCall::JsonParse(constructor, argument)) .with_position(state.span()), ) }), @@ -322,30 +293,7 @@ pub fn parser<'src>( } }); - let structure_field = identifier - .clone() - .then_ignore(just(Token::Operator(Operator::Assign))) - .then(expression.clone()); - - let structure_instance = positioned_identifier - .clone() - .then( - structure_field - .separated_by(just(Token::Control(Control::Comma))) - .allow_trailing() - .collect() - .delimited_by( - just(Token::Control(Control::CurlyOpen)), - just(Token::Control(Control::CurlyClose)), - ), - ) - .map_with(|(name, fields), state| { - ValueExpression::Value( - ValueNode::Structure { name, fields }.with_position(state.span()), - ) - }); - - let turbofish = r#type + let turbofish = positioned_type_constructor .clone() .separated_by(just(Token::Control(Control::Comma))) .at_least(1) @@ -364,8 +312,6 @@ pub fn parser<'src>( parsed_function.clone(), list.clone(), basic_value.clone(), - map.clone(), - structure_instance.clone(), identifier_expression.clone(), expression.clone().delimited_by( just(Token::Control(Control::ParenOpen)), @@ -378,7 +324,7 @@ pub fn parser<'src>( 2, just(Token::Operator(Operator::Not)), |_, expression, span| { - ValueExpression::Logic(Box::new(Logic::Not(expression)).with_position(span)) + Expression::Logic(Box::new(Logic::Not(expression)).with_position(span)) }, ), postfix( @@ -388,7 +334,7 @@ pub fn parser<'src>( just(Token::Control(Control::SquareClose)), ), |left, right, span| { - ValueExpression::ListIndex( + Expression::ListIndex( Box::new(ListIndex::new(left, right)).with_position(span), ) }, @@ -396,8 +342,8 @@ pub fn parser<'src>( infix( left(4), just(Token::Control(Control::Dot)), - |left: ValueExpression, _: Token, right: ValueExpression, span| { - ValueExpression::MapIndex( + |left: Expression, _: Token, right: Expression, span| { + Expression::MapIndex( Box::new(MapIndex::new(left, right)).with_position(span), ) }, @@ -414,17 +360,12 @@ pub fn parser<'src>( just(Token::Control(Control::ParenClose)), ), ), - |function_expression, - (type_arguments, arguments): ( - Option>>, - Vec, - ), - span| { - ValueExpression::FunctionCall( + |function_expression, (type_parameters, value_parameters), span| { + Expression::FunctionCall( FunctionCall::new( function_expression, - type_arguments.unwrap_or_else(|| Vec::with_capacity(0)), - arguments, + type_parameters, + value_parameters, ) .with_position(span), ) @@ -434,16 +375,14 @@ pub fn parser<'src>( left(1), just(Token::Operator(Operator::Equal)), |left, _, right, span| { - ValueExpression::Logic( - Box::new(Logic::Equal(left, right)).with_position(span), - ) + Expression::Logic(Box::new(Logic::Equal(left, right)).with_position(span)) }, ), infix( left(1), just(Token::Operator(Operator::NotEqual)), |left, _, right, span| { - ValueExpression::Logic( + Expression::Logic( Box::new(Logic::NotEqual(left, right)).with_position(span), ) }, @@ -452,25 +391,21 @@ pub fn parser<'src>( left(1), just(Token::Operator(Operator::Greater)), |left, _, right, span| { - ValueExpression::Logic( - Box::new(Logic::Greater(left, right)).with_position(span), - ) + Expression::Logic(Box::new(Logic::Greater(left, right)).with_position(span)) }, ), infix( left(1), just(Token::Operator(Operator::Less)), |left, _, right, span| { - ValueExpression::Logic( - Box::new(Logic::Less(left, right)).with_position(span), - ) + Expression::Logic(Box::new(Logic::Less(left, right)).with_position(span)) }, ), infix( left(1), just(Token::Operator(Operator::GreaterOrEqual)), |left, _, right, span| { - ValueExpression::Logic( + Expression::Logic( Box::new(Logic::GreaterOrEqual(left, right)).with_position(span), ) }, @@ -479,7 +414,7 @@ pub fn parser<'src>( left(1), just(Token::Operator(Operator::LessOrEqual)), |left, _, right, span| { - ValueExpression::Logic( + Expression::Logic( Box::new(Logic::LessOrEqual(left, right)).with_position(span), ) }, @@ -488,67 +423,58 @@ pub fn parser<'src>( left(1), just(Token::Operator(Operator::And)), |left, _, right, span| { - ValueExpression::Logic( - Box::new(Logic::And(left, right)).with_position(span), - ) + Expression::Logic(Box::new(Logic::And(left, right)).with_position(span)) }, ), infix( left(1), just(Token::Operator(Operator::Or)), |left, _, right, span| { - ValueExpression::Logic(Box::new(Logic::Or(left, right)).with_position(span)) + Expression::Logic(Box::new(Logic::Or(left, right)).with_position(span)) }, ), infix( left(1), just(Token::Operator(Operator::Add)), |left, _, right, span| { - ValueExpression::Math(Box::new(Math::Add(left, right)).with_position(span)) + Expression::Math(Box::new(Math::Add(left, right)).with_position(span)) }, ), infix( left(1), just(Token::Operator(Operator::Subtract)), |left, _, right, span| { - ValueExpression::Math( - Box::new(Math::Subtract(left, right)).with_position(span), - ) + Expression::Math(Box::new(Math::Subtract(left, right)).with_position(span)) }, ), infix( left(2), just(Token::Operator(Operator::Multiply)), |left, _, right, span| { - ValueExpression::Math( - Box::new(Math::Multiply(left, right)).with_position(span), - ) + Expression::Math(Box::new(Math::Multiply(left, right)).with_position(span)) }, ), infix( left(2), just(Token::Operator(Operator::Divide)), |left, _, right, span| { - ValueExpression::Math( - Box::new(Math::Divide(left, right)).with_position(span), - ) + Expression::Math(Box::new(Math::Divide(left, right)).with_position(span)) }, ), infix( left(1), just(Token::Operator(Operator::Modulo)), |left, _, right, span| { - ValueExpression::Math( - Box::new(Math::Modulo(left, right)).with_position(span), - ) + Expression::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| { - ValueExpression::As( - Box::new(As::new(expression, r#type)).with_position(span), + just(Token::Keyword(Keyword::As)) + .ignore_then(positioned_type_constructor.clone()), + |expression, constructor, span| { + Expression::As( + Box::new(As::new(expression, constructor)).with_position(span), ) }, ), @@ -558,10 +484,8 @@ pub fn parser<'src>( logic_math_indexes_as_and_function_calls, built_in_function_call, range, - structure_instance, parsed_function, list, - map, basic_value, identifier_expression, )) @@ -649,19 +573,18 @@ pub fn parser<'src>( }, ); - let type_alias = just(Token::Keyword(Keyword::Type)) + let type_assignment = just(Token::Keyword(Keyword::Type)) .ignore_then(positioned_identifier.clone()) .then_ignore(just(Token::Operator(Operator::Assign))) - .then(r#type.clone()) - .map_with(|(identifier, r#type), state| { + .then(positioned_type_constructor.clone()) + .map_with(|(identifier, constructor), state| { Statement::TypeAssignment( - TypeAssignment::new(identifier, r#type).with_position(state.span()), + TypeAssignment::new(identifier, constructor).with_position(state.span()), ) }); choice(( async_block, - structure_definition, if_else, assignment, expression_statement, @@ -669,7 +592,7 @@ pub fn parser<'src>( block_statement, r#loop, r#while, - type_alias, + type_assignment, )) .then_ignore(just(Token::Control(Control::Semicolon)).or_not()) }); @@ -696,7 +619,7 @@ mod tests { Statement::TypeAssignment( TypeAssignment::new( Identifier::new("MyType").with_position((5, 11)), - Type::String.with_position((14, 17)) + TypeConstructor::Type(Type::String).with_position((14, 17)) ) .with_position((0, 17)) ) @@ -707,10 +630,10 @@ mod tests { fn r#as() { assert_eq!( parse(&lex("1 as str").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::As( + Statement::ValueExpression(Expression::As( Box::new(As::new( - ValueExpression::Value(ValueNode::Integer(1).with_position((0, 1))), - Type::String.with_position((5, 8)) + Expression::Value(ValueNode::Integer(1).with_position((0, 1))), + TypeConstructor::Type(Type::String).with_position((5, 8)) )) .with_position((0, 8)) )) @@ -733,7 +656,7 @@ mod tests { assert_eq!( statements[0], - Statement::ValueExpression(ValueExpression::BuiltInFunctionCall( + Statement::ValueExpression(Expression::BuiltInFunctionCall( Box::new(BuiltInFunctionCall::ReadLine).with_position((0, 9)) )) ); @@ -752,8 +675,8 @@ mod tests { assert_eq!( statements[0], - Statement::ValueExpression(ValueExpression::BuiltInFunctionCall( - Box::new(BuiltInFunctionCall::WriteLine(ValueExpression::Value( + Statement::ValueExpression(Expression::BuiltInFunctionCall( + Box::new(BuiltInFunctionCall::WriteLine(Expression::Value( ValueNode::String("hiya".to_string()).with_position((11, 17)) ))) .with_position((0, 17)) @@ -777,13 +700,13 @@ mod tests { .unwrap()[0], Statement::AsyncBlock( AsyncBlock::new(vec![ - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Integer(1).with_position((53, 54)) )), - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Integer(2).with_position((79, 80)) )), - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Integer(3).with_position((105, 106)) )), ]) @@ -805,17 +728,17 @@ mod tests { .unwrap() ) .unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Structure { name: Identifier::new("Foo").with_position((21, 24)), fields: vec![ ( - Identifier::new("bar"), - ValueExpression::Value(ValueNode::Integer(42).with_position((57, 59))) + Identifier::new("bar").with_position((0, 0)), + Expression::Value(ValueNode::Integer(42).with_position((57, 59))) ), ( - Identifier::new("baz"), - ValueExpression::Value( + Identifier::new("baz").with_position((0, 0)), + Expression::Value( ValueNode::String("hiya".to_string()).with_position((91, 97)) ) ), @@ -845,11 +768,11 @@ mod tests { vec![ ( Identifier::new("bar"), - Type::Integer.with_position((64, 67)) + TypeConstructor::Type(Type::Integer).with_position((64, 67)) ), ( Identifier::new("baz"), - Type::String.with_position((99, 102)) + TypeConstructor::Type(Type::String).with_position((99, 102)) ), ] ) @@ -862,27 +785,27 @@ mod tests { fn map_index() { assert_eq!( parse(&lex("{ x = 42 }.x").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::MapIndex( + Statement::ValueExpression(Expression::MapIndex( Box::new(MapIndex::new( - ValueExpression::Value( + Expression::Value( ValueNode::Map(vec![( Identifier::new("x"), None, - ValueExpression::Value(ValueNode::Integer(42).with_position((6, 8))) + Expression::Value(ValueNode::Integer(42).with_position((6, 8))) )]) .with_position((0, 10)) ), - ValueExpression::Identifier(Identifier::new("x").with_position((11, 12))) + Expression::Identifier(Identifier::new("x").with_position((11, 12))) )) .with_position((0, 12)) )) ); assert_eq!( parse(&lex("foo.x").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::MapIndex( + Statement::ValueExpression(Expression::MapIndex( Box::new(MapIndex::new( - ValueExpression::Identifier(Identifier::new("foo").with_position((0, 3))), - ValueExpression::Identifier(Identifier::new("x").with_position((4, 5))) + Expression::Identifier(Identifier::new("foo").with_position((0, 3))), + Expression::Identifier(Identifier::new("x").with_position((4, 5))) )) .with_position((0, 5)) )) @@ -895,14 +818,14 @@ mod tests { parse(&lex("while true { output('hi') }").unwrap()).unwrap()[0], Statement::While( While::new( - ValueExpression::Value(ValueNode::Boolean(true).with_position((6, 10))), - vec![Statement::ValueExpression(ValueExpression::FunctionCall( + Expression::Value(ValueNode::Boolean(true).with_position((6, 10))), + vec![Statement::ValueExpression(Expression::FunctionCall( FunctionCall::new( - ValueExpression::Identifier( + Expression::Identifier( Identifier::new("output").with_position((13, 19)) ), - Vec::with_capacity(0), - vec![ValueExpression::Value( + Some(Vec::with_capacity(0)), + vec![Expression::Value( ValueNode::String("hi".to_string()).with_position((20, 24)) )] ) @@ -921,9 +844,9 @@ mod tests { Statement::Assignment( Assignment::new( Identifier::new("foobar").with_position((0, 6)), - Some(Type::Boolean.with_position((9, 13))), + Some(TypeConstructor::Type(Type::Boolean).with_position((0, 0))), AssignmentOperator::Assign, - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Boolean(true).with_position((16, 20)) )) ) @@ -935,13 +858,21 @@ mod tests { #[test] fn list_type() { assert_eq!( - parse(&lex("foobar: list = []").unwrap()).unwrap()[0], + parse(&lex("foobar: [int; 2] = []").unwrap()).unwrap()[0], Statement::Assignment( Assignment::new( Identifier::new("foobar").with_position((0, 6)), - Some(Type::List.with_position((8, 12))), + Some( + TypeConstructor::List { + length: 2, + item_type: Box::new( + TypeConstructor::Type(Type::Integer).with_position((0, 0)) + ) + } + .with_position((8, 12)) + ), AssignmentOperator::Assign, - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::List(vec![]).with_position((15, 17)) )) ) @@ -957,13 +888,10 @@ mod tests { Statement::Assignment( Assignment::new( Identifier::new("foobar").with_position((0, 6)), - Some( - Type::ListOf(Box::new(Type::Boolean.with_position((14, 18)))) - .with_position((9, 19)) - ), + Some(TypeConstructor::ListOf(Box::new(Type::Boolean)).with_position((9, 19))), AssignmentOperator::Assign, - Statement::ValueExpression(ValueExpression::Value( - ValueNode::List(vec![ValueExpression::Value( + Statement::ValueExpression(Expression::Value( + ValueNode::List(vec![Expression::Value( ValueNode::Boolean(true).with_position((23, 27)) )]) .with_position((22, 28)) @@ -974,38 +902,6 @@ mod tests { ); } - #[test] - fn list_exact_type() { - assert_eq!( - parse(&lex("foobar : [bool, str] = [true, '42']").unwrap()).unwrap()[0], - Statement::Assignment( - Assignment::new( - Identifier::new("foobar").with_position((0, 6)), - Some( - Type::ListExact(vec![ - Type::Boolean.with_position((10, 14)), - Type::String.with_position((16, 19)) - ]) - .with_position((9, 20)) - ), - AssignmentOperator::Assign, - Statement::ValueExpression(ValueExpression::Value( - ValueNode::List(vec![ - ValueExpression::Value( - ValueNode::Boolean(true).with_position((24, 28)) - ), - ValueExpression::Value( - ValueNode::String("42".to_string()).with_position((30, 34)) - ) - ]) - .with_position((23, 35)) - )) - ) - .with_position((0, 35)) - ) - ); - } - #[test] fn function_type() { assert_eq!( @@ -1014,14 +910,15 @@ mod tests { Assignment::new( Identifier::new("foobar").with_position((0, 6)), Some( - Type::Function { - parameter_types: vec![], - return_type: Box::new(Type::Any.with_position((17, 20))) + TypeConstructor::Function { + type_parameters: None, + value_parameters: vec![], + return_type: Box::new(Type::Any), } .with_position((9, 20)) ), AssignmentOperator::Assign, - Statement::ValueExpression(ValueExpression::Identifier( + Statement::ValueExpression(Expression::Identifier( Identifier::new("some_function").with_position((23, 36)) )) ) @@ -1034,10 +931,10 @@ mod tests { fn function_call() { assert_eq!( parse(&lex("foobar()").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::FunctionCall( + Statement::ValueExpression(Expression::FunctionCall( FunctionCall::new( - ValueExpression::Identifier(Identifier::new("foobar").with_position((0, 6))), - Vec::with_capacity(0), + Expression::Identifier(Identifier::new("foobar").with_position((0, 6))), + Some(Vec::with_capacity(0)), Vec::with_capacity(0), ) .with_position((0, 8)) @@ -1049,11 +946,13 @@ mod tests { fn function_call_with_type_arguments() { assert_eq!( parse(&lex("foobar::(str)::('hi')").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::FunctionCall( + Statement::ValueExpression(Expression::FunctionCall( FunctionCall::new( - ValueExpression::Identifier(Identifier::new("foobar").with_position((0, 6))), - vec![Type::String.with_position((9, 12))], - vec![ValueExpression::Value( + Expression::Identifier(Identifier::new("foobar").with_position((0, 6))), + Some(vec![ + TypeConstructor::Type(Type::String).with_position((9, 12)) + ]), + vec![Expression::Value( ValueNode::String("hi".to_string()).with_position((16, 20)) )], ) @@ -1066,7 +965,7 @@ mod tests { fn range() { assert_eq!( parse(&lex("1..10").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Range(1..10).with_position((0, 5)) )) ) @@ -1076,14 +975,17 @@ mod tests { fn function() { assert_eq!( parse(&lex("fn (x: int) int { x }").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::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::ValueExpression( - ValueExpression::Identifier(Identifier::new("x").with_position((18, 19))) - )]) + type_parameters: None, + value_parameters: vec![( + Identifier::new("x"), + TypeConstructor::Integer.with_position((7, 10)) + )], + return_type: TypeConstructor::Integer.with_position((12, 15)), + body: Block::new(vec![Statement::ValueExpression(Expression::Identifier( + Identifier::new("x").with_position((18, 19)) + ))]) .with_position((16, 21)), } .with_position((0, 21)) @@ -1095,26 +997,27 @@ mod tests { fn function_with_type_arguments() { assert_eq!( parse(&lex("fn (T, U)(x: T, y: U) T { x }").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::ParsedFunction { - type_arguments: vec![ - Type::Argument(Identifier::new("T")).with_position((4, 5)), - Type::Argument(Identifier::new("U")).with_position((7, 8)), - ], - parameters: vec![ + type_parameters: Some(vec![ + TypeConstructor::Argument(Identifier::new("T")).with_position((4, 5)), + TypeConstructor::Argument(Identifier::new("U")).with_position((7, 8)), + ]), + value_parameters: vec![ ( Identifier::new("x"), - Type::Argument(Identifier::new("T")).with_position((13, 14)) + TypeConstructor::Argument(Identifier::new("T")).with_position((13, 14)) ), ( Identifier::new("y"), - Type::Argument(Identifier::new("U")).with_position((19, 20)) + TypeConstructor::Argument(Identifier::new("U")).with_position((19, 20)) ) ], - return_type: Type::Argument(Identifier::new("T")).with_position((22, 23)), - body: Block::new(vec![Statement::ValueExpression( - ValueExpression::Identifier(Identifier::new("x").with_position((26, 27))) - )]) + return_type: TypeConstructor::Argument(Identifier::new("T")) + .with_position((22, 23)), + body: Block::new(vec![Statement::ValueExpression(Expression::Identifier( + Identifier::new("x").with_position((26, 27)) + ))]) .with_position((24, 29)), } .with_position((0, 29)) @@ -1128,8 +1031,8 @@ mod tests { parse(&lex("if true { 'foo' }").unwrap()).unwrap()[0], Statement::IfElse( IfElse::new( - ValueExpression::Value(ValueNode::Boolean(true).with_position((3, 7))), - Block::new(vec![Statement::ValueExpression(ValueExpression::Value( + Expression::Value(ValueNode::Boolean(true).with_position((3, 7))), + Block::new(vec![Statement::ValueExpression(Expression::Value( ValueNode::String("foo".to_string()).with_position((10, 15)) ))]) .with_position((8, 17)), @@ -1147,14 +1050,14 @@ mod tests { parse(&lex("if true {'foo' } else { 'bar' }").unwrap()).unwrap()[0], Statement::IfElse( IfElse::new( - ValueExpression::Value(ValueNode::Boolean(true).with_position((3, 7))), - Block::new(vec![Statement::ValueExpression(ValueExpression::Value( + Expression::Value(ValueNode::Boolean(true).with_position((3, 7))), + Block::new(vec![Statement::ValueExpression(Expression::Value( ValueNode::String("foo".to_string()).with_position((9, 14)) ))]) .with_position((8, 16)), Vec::with_capacity(0), Some( - Block::new(vec![Statement::ValueExpression(ValueExpression::Value( + Block::new(vec![Statement::ValueExpression(Expression::Value( ValueNode::String("bar".to_string()).with_position((24, 29)) ))]) .with_position((22, 31)) @@ -1169,30 +1072,28 @@ mod tests { fn map() { assert_eq!( parse(&lex("{ foo = 'bar' }").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Map(vec![( Identifier::new("foo"), None, - ValueExpression::Value( - ValueNode::String("bar".to_string()).with_position((8, 13)) - ) + Expression::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::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Map(vec![ ( Identifier::new("x"), None, - ValueExpression::Value(ValueNode::Integer(1).with_position((6, 7))) + Expression::Value(ValueNode::Integer(1).with_position((6, 7))) ), ( Identifier::new("y"), None, - ValueExpression::Value(ValueNode::Integer(2).with_position((13, 14))) + Expression::Value(ValueNode::Integer(2).with_position((13, 14))) ), ]) .with_position((0, 17)) @@ -1200,17 +1101,17 @@ mod tests { ); assert_eq!( parse(&lex("{ x = 1 y = 2 }").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Map(vec![ ( Identifier::new("x"), None, - ValueExpression::Value(ValueNode::Integer(1).with_position((6, 7))) + Expression::Value(ValueNode::Integer(1).with_position((6, 7))) ), ( Identifier::new("y"), None, - ValueExpression::Value(ValueNode::Integer(2).with_position((12, 13))) + Expression::Value(ValueNode::Integer(2).with_position((12, 13))) ), ]) .with_position((0, 15)) @@ -1222,10 +1123,10 @@ mod tests { fn math() { assert_eq!( parse(&lex("1 + 1").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Math( + Statement::ValueExpression(Expression::Math( Box::new(Math::Add( - ValueExpression::Value(ValueNode::Integer(1).with_position((0, 1))), - ValueExpression::Value(ValueNode::Integer(1).with_position((4, 5))) + Expression::Value(ValueNode::Integer(1).with_position((0, 1))), + Expression::Value(ValueNode::Integer(1).with_position((4, 5))) )) .with_position((0, 5)) )) @@ -1237,7 +1138,7 @@ mod tests { assert_eq!( parse(&lex("loop { 42 }").unwrap()).unwrap()[0], Statement::Loop( - Loop::new(vec![Statement::ValueExpression(ValueExpression::Value( + Loop::new(vec![Statement::ValueExpression(Expression::Value( ValueNode::Integer(42).with_position((7, 9)) ))]) .with_position((0, 11)) @@ -1248,14 +1149,12 @@ mod tests { Statement::Loop( Loop::new(vec![Statement::IfElse( IfElse::new( - ValueExpression::Logic( + Expression::Logic( Box::new(Logic::Greater( - ValueExpression::Identifier( + Expression::Identifier( Identifier::new("i").with_position((10, 11)) ), - ValueExpression::Value( - ValueNode::Integer(2).with_position((14, 15)) - ) + Expression::Value(ValueNode::Integer(2).with_position((14, 15))) )) .with_position((10, 15)) ), @@ -1268,7 +1167,7 @@ mod tests { Identifier::new("i").with_position((33, 34)), None, AssignmentOperator::AddAssign, - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Integer(1).with_position((38, 39)) )) ) @@ -1289,9 +1188,9 @@ mod tests { assert_eq!( parse(&lex("{ x }").unwrap()).unwrap()[0], Statement::Block( - Block::new(vec![Statement::ValueExpression( - ValueExpression::Identifier(Identifier::new("x").with_position((2, 3))), - )]) + Block::new(vec![Statement::ValueExpression(Expression::Identifier( + Identifier::new("x").with_position((2, 3)) + ),)]) .with_position((0, 5)) ) ); @@ -1310,13 +1209,13 @@ mod tests { .unwrap()[0], Statement::Block( Block::new(vec![ - Statement::ValueExpression(ValueExpression::Identifier( + Statement::ValueExpression(Expression::Identifier( Identifier::new("x").with_position((39, 40)) )), - Statement::ValueExpression(ValueExpression::Identifier( + Statement::ValueExpression(Expression::Identifier( Identifier::new("y").with_position((62, 63)) )), - Statement::ValueExpression(ValueExpression::Identifier( + Statement::ValueExpression(Expression::Identifier( Identifier::new("z").with_position((85, 86)) )), ]) @@ -1337,14 +1236,14 @@ mod tests { .unwrap()[0], Statement::Block( Block::new(vec![ - Statement::ValueExpression(ValueExpression::Logic( + Statement::ValueExpression(Expression::Logic( Box::new(Logic::Equal( - ValueExpression::Value(ValueNode::Integer(1).with_position((39, 40))), - ValueExpression::Value(ValueNode::Integer(1).with_position((44, 45))) + Expression::Value(ValueNode::Integer(1).with_position((39, 40))), + Expression::Value(ValueNode::Integer(1).with_position((44, 45))) )) .with_position((39, 45)) )), - Statement::ValueExpression(ValueExpression::Identifier( + Statement::ValueExpression(Expression::Identifier( Identifier::new("z").with_position((66, 67)) )), ]) @@ -1357,19 +1256,19 @@ mod tests { fn identifier() { assert_eq!( parse(&lex("x").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Identifier( + Statement::ValueExpression(Expression::Identifier( Identifier::new("x").with_position((0, 1)) )) ); assert_eq!( parse(&lex("foobar").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Identifier( + Statement::ValueExpression(Expression::Identifier( Identifier::new("foobar").with_position((0, 6)) )) ); assert_eq!( parse(&lex("HELLO").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Identifier( + Statement::ValueExpression(Expression::Identifier( Identifier::new("HELLO").with_position((0, 5)) )) ); @@ -1384,7 +1283,7 @@ mod tests { Identifier::new("foobar").with_position((0, 6)), None, AssignmentOperator::Assign, - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Integer(1).with_position((9, 10)) )) ) @@ -1400,9 +1299,9 @@ mod tests { Statement::Assignment( Assignment::new( Identifier::new("foobar").with_position((0, 6)), - Some(Type::Integer.with_position((8, 11))), + Some(TypeConstructor::Integer.with_position((8, 11))), AssignmentOperator::Assign, - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Integer(1).with_position((14, 15)) )) ) @@ -1415,10 +1314,10 @@ mod tests { fn logic() { assert_eq!( parse(&lex("x == 1").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Logic( + Statement::ValueExpression(Expression::Logic( Box::new(Logic::Equal( - ValueExpression::Identifier(Identifier::new("x").with_position((0, 1))), - ValueExpression::Value(ValueNode::Integer(1).with_position((5, 6))), + Expression::Identifier(Identifier::new("x").with_position((0, 1))), + Expression::Value(ValueNode::Integer(1).with_position((5, 6))), )) .with_position((0, 6)) )) @@ -1426,21 +1325,19 @@ mod tests { assert_eq!( parse(&lex("(x == 1) && (y == 2)").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Logic( + Statement::ValueExpression(Expression::Logic( Box::new(Logic::And( - ValueExpression::Logic( + Expression::Logic( Box::new(Logic::Equal( - ValueExpression::Identifier(Identifier::new("x").with_position((1, 2))), - ValueExpression::Value(ValueNode::Integer(1).with_position((6, 7))), + Expression::Identifier(Identifier::new("x").with_position((1, 2))), + Expression::Value(ValueNode::Integer(1).with_position((6, 7))), )) .with_position((1, 7)) ), - ValueExpression::Logic( + Expression::Logic( Box::new(Logic::Equal( - ValueExpression::Identifier( - Identifier::new("y").with_position((13, 14)) - ), - ValueExpression::Value(ValueNode::Integer(2).with_position((18, 19))), + Expression::Identifier(Identifier::new("y").with_position((13, 14))), + Expression::Value(ValueNode::Integer(2).with_position((18, 19))), )) .with_position((13, 19)) ) @@ -1451,27 +1348,25 @@ mod tests { assert_eq!( parse(&lex("(x == 1) && (y == 2) && true").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Logic( + Statement::ValueExpression(Expression::Logic( Box::new(Logic::And( - ValueExpression::Logic( + Expression::Logic( Box::new(Logic::And( - ValueExpression::Logic( + Expression::Logic( Box::new(Logic::Equal( - ValueExpression::Identifier( + Expression::Identifier( Identifier::new("x").with_position((1, 2)) ), - ValueExpression::Value( - ValueNode::Integer(1).with_position((6, 7)) - ) + Expression::Value(ValueNode::Integer(1).with_position((6, 7))) )) .with_position((1, 7)) ), - ValueExpression::Logic( + Expression::Logic( Box::new(Logic::Equal( - ValueExpression::Identifier( + Expression::Identifier( Identifier::new("y").with_position((13, 14)) ), - ValueExpression::Value( + Expression::Value( ValueNode::Integer(2).with_position((18, 19)) ) )) @@ -1480,7 +1375,7 @@ mod tests { )) .with_position((0, 20)) ), - ValueExpression::Value(ValueNode::Boolean(true).with_position((24, 28))) + Expression::Value(ValueNode::Boolean(true).with_position((24, 28))) )) .with_position((0, 28)) )) @@ -1491,14 +1386,14 @@ mod tests { fn list() { assert_eq!( parse(&lex("[]").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::List(Vec::with_capacity(0)).with_position((0, 2)) ),) ); assert_eq!( parse(&lex("[42]").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( - ValueNode::List(vec![ValueExpression::Value( + Statement::ValueExpression(Expression::Value( + ValueNode::List(vec![Expression::Value( ValueNode::Integer(42).with_position((1, 3)) )]) .with_position((0, 4)) @@ -1506,20 +1401,16 @@ mod tests { ); assert_eq!( parse(&lex("[42, 'foo', 'bar', [1, 2, 3,]]").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::List(vec![ - 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( + 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( ValueNode::List(vec![ - 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))), + 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))), ]) .with_position((19, 29)) ) @@ -1533,7 +1424,7 @@ mod tests { fn r#true() { assert_eq!( parse(&lex("true").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Boolean(true).with_position((0, 4)) )) ); @@ -1543,7 +1434,7 @@ mod tests { fn r#false() { assert_eq!( parse(&lex("false").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Boolean(false).with_position((0, 5)) )) ); @@ -1553,13 +1444,13 @@ mod tests { fn positive_float() { assert_eq!( parse(&lex("0.0").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Float(0.0).with_position((0, 3)) )) ); assert_eq!( parse(&lex("42.0").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Float(42.0).with_position((0, 4)) )) ); @@ -1568,7 +1459,7 @@ mod tests { assert_eq!( parse(&lex(&max_float).unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Float(f64::MAX).with_position((0, 311)) )) ); @@ -1577,7 +1468,7 @@ mod tests { assert_eq!( parse(&lex(&min_positive_float).unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Float(f64::MIN_POSITIVE).with_position((0, 326)) ),) ); @@ -1587,13 +1478,13 @@ mod tests { fn negative_float() { assert_eq!( parse(&lex("-0.0").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Float(-0.0).with_position((0, 4)) )) ); assert_eq!( parse(&lex("-42.0").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Float(-42.0).with_position((0, 5)) )) ); @@ -1602,7 +1493,7 @@ mod tests { assert_eq!( parse(&lex(&min_float).unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Float(f64::MIN).with_position((0, 312)) )) ); @@ -1611,7 +1502,7 @@ mod tests { assert_eq!( parse(&lex(&max_negative_float).unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Float(-f64::MIN_POSITIVE).with_position((0, 327)) ),) ); @@ -1621,18 +1512,18 @@ mod tests { fn other_float() { assert_eq!( parse(&lex("Infinity").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Float(f64::INFINITY).with_position((0, 8)) )) ); assert_eq!( parse(&lex("-Infinity").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Float(f64::NEG_INFINITY).with_position((0, 9)) )) ); - if let Statement::ValueExpression(ValueExpression::Value(WithPosition { + if let Statement::ValueExpression(Expression::Value(WithPosition { node: ValueNode::Float(float), .. })) = &parse(&lex("NaN").unwrap()).unwrap()[0] @@ -1652,7 +1543,7 @@ mod tests { assert_eq!( statements[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Integer(i).with_position((0, 1)) )) ) @@ -1660,7 +1551,7 @@ mod tests { assert_eq!( parse(&lex("42").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Integer(42).with_position((0, 2)) )) ); @@ -1669,7 +1560,7 @@ mod tests { assert_eq!( parse(&lex(&maximum_integer).unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Integer(i64::MAX).with_position((0, 19)) )) ); @@ -1684,7 +1575,7 @@ mod tests { assert_eq!( statements[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Integer(i).with_position((0, 2)) )) ) @@ -1692,7 +1583,7 @@ mod tests { assert_eq!( parse(&lex("-42").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Integer(-42).with_position((0, 3)) )) ); @@ -1701,7 +1592,7 @@ mod tests { assert_eq!( parse(&lex(&minimum_integer).unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::Integer(i64::MIN).with_position((0, 20)) )) ); @@ -1711,19 +1602,19 @@ mod tests { fn double_quoted_string() { assert_eq!( parse(&lex("\"\"").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::String("".to_string()).with_position((0, 2)) )) ); assert_eq!( parse(&lex("\"42\"").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::String("42".to_string()).with_position((0, 4)) ),) ); assert_eq!( parse(&lex("\"foobar\"").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::String("foobar".to_string()).with_position((0, 8)) ),) ); @@ -1733,19 +1624,19 @@ mod tests { fn single_quoted_string() { assert_eq!( parse(&lex("''").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::String("".to_string()).with_position((0, 2)) )) ); assert_eq!( parse(&lex("'42'").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::String("42".to_string()).with_position((0, 4)) ),) ); assert_eq!( parse(&lex("'foobar'").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::String("foobar".to_string()).with_position((0, 8)) ),) ); @@ -1755,19 +1646,19 @@ mod tests { fn grave_quoted_string() { assert_eq!( parse(&lex("``").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::String("".to_string()).with_position((0, 2)) )) ); assert_eq!( parse(&lex("`42`").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::Value( ValueNode::String("42".to_string()).with_position((0, 4)) ),) ); assert_eq!( parse(&lex("`foobar`").unwrap()).unwrap()[0], - Statement::ValueExpression(ValueExpression::Value( + Statement::ValueExpression(Expression::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 f381625..5bb713f 100644 --- a/dust-lang/src/value.rs +++ b/dust-lang/src/value.rs @@ -9,7 +9,7 @@ use std::{ use serde::{Deserialize, Serialize}; use crate::{ - abstract_tree::{AbstractNode, Action, Block, Type, WithPos, WithPosition}, + abstract_tree::{AbstractNode, Block, Evaluation, Type, WithPosition}, context::Context, error::{RuntimeError, ValidationError}, identifier::Identifier, @@ -52,14 +52,14 @@ impl Value { } pub fn function( - type_arguments: Vec>, - parameters: Vec<(Identifier, WithPosition)>, - return_type: WithPosition, - body: WithPosition, + type_parameters: Option>, + value_parameters: Vec<(Identifier, Type)>, + return_type: Type, + body: Block, ) -> Self { Value(Arc::new(ValueInner::Function(Function { - type_parameters: type_arguments, - parameters, + type_parameters, + value_parameters, return_type, body, }))) @@ -129,19 +129,19 @@ impl Display for Value { ValueInner::Range(_) => todo!(), ValueInner::String(string) => write!(f, "{string}"), ValueInner::Function(Function { - type_parameters: type_arguments, - parameters, + type_parameters, + value_parameters: parameters, return_type, body, }) => { - if !type_arguments.is_empty() { + if let Some(type_parameters) = type_parameters { write!(f, "(")?; - for (index, r#type) in type_arguments.into_iter().enumerate() { - if index == type_arguments.len() - 1 { - write!(f, "{}", r#type.node)?; + for (index, r#type) in type_parameters.into_iter().enumerate() { + if index == type_parameters.len() - 1 { + write!(f, "{}", r#type)?; } else { - write!(f, "{} ", r#type.node)?; + write!(f, "{} ", r#type)?; } } @@ -151,10 +151,10 @@ impl Display for Value { write!(f, "(")?; for (identifier, r#type) in parameters { - write!(f, "{identifier}: {}", r#type.node)?; + write!(f, "{identifier}: {}", r#type)?; } - write!(f, "): {} {:?}", return_type.node, body.node) + write!(f, "): {} {:?}", return_type, body) } ValueInner::Structure { name, fields } => { write!(f, "{}\n{{", name.node)?; @@ -224,23 +224,19 @@ impl ValueInner { ValueInner::Float(_) => Type::Float, ValueInner::Integer(_) => Type::Integer, ValueInner::List(values) => { - let mut types = Vec::with_capacity(values.len()); + let item_type = values.first().unwrap().node.r#type(context)?; - for value in values { - types.push(value.node.r#type(context)?.with_position(value.position)); + Type::List { + length: values.len(), + item_type: Box::new(item_type), } - - Type::ListExact(types) } ValueInner::Map(_) => Type::Map, ValueInner::Range(_) => Type::Range, ValueInner::String(_) => Type::String, ValueInner::Function(function) => Type::Function { - parameter_types: function - .parameters - .iter() - .map(|(_, r#type)| r#type.clone()) - .collect(), + type_parameters: None, + value_parameters: function.value_parameters.clone(), return_type: Box::new(function.return_type.clone()), }, ValueInner::Structure { name, .. } => { @@ -321,14 +317,14 @@ impl Ord for ValueInner { #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct Function { - type_parameters: Vec>, - parameters: Vec<(Identifier, WithPosition)>, - return_type: WithPosition, - body: WithPosition, + type_parameters: Option>, + value_parameters: Vec<(Identifier, Type)>, + return_type: Type, + body: Block, } impl Function { - pub fn type_parameters(&self) -> &Vec> { + pub fn type_parameters(&self) -> &Option> { &self.type_parameters } @@ -337,11 +333,12 @@ impl Function { arguments: Vec, context: &mut Context, clear_variables: bool, - ) -> Result { - for ((identifier, _), value) in self.parameters.into_iter().zip(arguments.into_iter()) { + ) -> Result { + for ((identifier, _), value) in self.value_parameters.into_iter().zip(arguments.into_iter()) + { context.set_value(identifier.clone(), value)?; } - self.body.node.run(context, clear_variables) + self.body.evaluate(context, clear_variables) } } diff --git a/dust-lang/tests/structs.rs b/dust-lang/tests/structs.rs index f0335a7..331a4e1 100644 --- a/dust-lang/tests/structs.rs +++ b/dust-lang/tests/structs.rs @@ -56,7 +56,7 @@ fn field_type_error() { expected: Type::Integer }, actual_position: (128, 134).into(), - expected_position: (56, 59).into() + expected_position: Some((56, 59).into()), }, position: (96, 153).into() }] diff --git a/dust-lang/tests/values.rs b/dust-lang/tests/values.rs index 22767a6..b9d7683 100644 --- a/dust-lang/tests/values.rs +++ b/dust-lang/tests/values.rs @@ -148,7 +148,7 @@ fn map_type_errors() { expected: Type::Boolean }, actual_position: (15, 20).into(), - expected_position: (8, 12).into(), + expected_position: Some((8, 12).into()), }, position: (0, 22).into() }] diff --git a/dust-lang/tests/variables.rs b/dust-lang/tests/variables.rs index b52ad46..d108d34 100644 --- a/dust-lang/tests/variables.rs +++ b/dust-lang/tests/variables.rs @@ -1,5 +1,5 @@ use dust_lang::{ - abstract_tree::{Block, Statement, Type, ValueExpression, WithPos}, + abstract_tree::{Block, Expression, Statement, Type, WithPos}, error::{Error, TypeConflict, ValidationError}, identifier::Identifier, *, @@ -34,7 +34,7 @@ fn set_variable_with_type_error() { expected: Type::String }, actual_position: (14, 18).into(), - expected_position: (8, 11).into() + expected_position: Some((8, 11).into()) }, position: (0, 18).into() }] @@ -46,13 +46,12 @@ fn function_variable() { assert_eq!( interpret("test", "foobar = fn (x: int) int { x }; foobar"), Ok(Some(Value::function( - Vec::with_capacity(0), - vec![(Identifier::new("x"), Type::Integer.with_position((16, 19)))], - Type::Integer.with_position((21, 24)), - Block::new(vec![Statement::ValueExpression( - ValueExpression::Identifier(Identifier::new("x").with_position((27, 28))) - )]) - .with_position((25, 30)) + Some(Vec::with_capacity(0)), + vec![(Identifier::new("x"), Type::Integer)], + Type::Integer, + Block::new(vec![Statement::ValueExpression(Expression::Identifier( + Identifier::new("x").with_position((27, 28)) + ))]) ))) ); }