diff --git a/src/abstract_tree/block.rs b/src/abstract_tree/block.rs index 473fff5..9104ad6 100644 --- a/src/abstract_tree/block.rs +++ b/src/abstract_tree/block.rs @@ -3,15 +3,15 @@ use crate::{ error::{RuntimeError, ValidationError}, }; -use super::{AbstractTree, Action, Statement, Type}; +use super::{AbstractTree, Action, Positioned, Statement, Type}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct Block { - statements: Vec, + statements: Vec>, } impl Block { - pub fn new(statements: Vec) -> Self { + pub fn new(statements: Vec>) -> Self { Self { statements } } } @@ -19,7 +19,7 @@ impl Block { impl AbstractTree for Block { fn expected_type(&self, _context: &Context) -> Result { if let Some(statement) = self.statements.last() { - statement.expected_type(_context) + statement.node.expected_type(_context) } else { Ok(Type::None) } @@ -27,7 +27,7 @@ impl AbstractTree for Block { fn validate(&self, _context: &Context) -> Result<(), ValidationError> { for statement in &self.statements { - statement.validate(_context)?; + statement.node.validate(_context)?; } Ok(()) @@ -37,7 +37,7 @@ impl AbstractTree for Block { let mut previous = Action::None; for statement in self.statements { - let action = statement.run(_context)?; + let action = statement.node.run(_context)?; previous = match action { Action::Return(value) => Action::Return(value), Action::None => Action::None, @@ -62,14 +62,17 @@ mod tests { fn run_returns_value_of_final_statement() { let block = Block::new(vec![ Statement::Expression( - Expression::Value(ValueNode::Integer(1)).positioned((0..1).into()), - ), + Expression::Value(ValueNode::Integer(1)).positioned((0..0).into()), + ) + .positioned((0..0).into()), Statement::Expression( - Expression::Value(ValueNode::Integer(2)).positioned((0..1).into()), - ), + Expression::Value(ValueNode::Integer(2)).positioned((0..0).into()), + ) + .positioned((0..0).into()), Statement::Expression( - Expression::Value(ValueNode::Integer(42)).positioned((0..1).into()), - ), + Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()), + ) + .positioned((0..0).into()), ]); assert_eq!( @@ -83,10 +86,12 @@ mod tests { let block = Block::new(vec![ Statement::Expression( Expression::Value(ValueNode::String("42".to_string())).positioned((0..0).into()), - ), + ) + .positioned((0..0).into()), Statement::Expression( - Expression::Value(ValueNode::Integer(42)).positioned((0..1).into()), - ), + Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()), + ) + .positioned((0..0).into()), ]); assert_eq!(block.expected_type(&Context::new()), Ok(Type::Integer)) diff --git a/src/abstract_tree/function_call.rs b/src/abstract_tree/function_call.rs index a1cb1a7..c74c3ce 100644 --- a/src/abstract_tree/function_call.rs +++ b/src/abstract_tree/function_call.rs @@ -3,16 +3,16 @@ use crate::{ error::{RuntimeError, ValidationError}, }; -use super::{AbstractTree, Action, Expression, Type}; +use super::{AbstractTree, Action, Expression, Positioned, Type}; #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)] pub struct FunctionCall { - function: Box, - arguments: Vec, + function: Box>, + arguments: Vec>, } impl FunctionCall { - pub fn new(function: Expression, arguments: Vec) -> Self { + pub fn new(function: Positioned, arguments: Vec>) -> Self { FunctionCall { function: Box::new(function), arguments, @@ -22,7 +22,7 @@ impl FunctionCall { impl AbstractTree for FunctionCall { fn expected_type(&self, _context: &Context) -> Result { - if let Type::Function { return_type, .. } = self.function.expected_type(_context)? { + if let Type::Function { return_type, .. } = self.function.node.expected_type(_context)? { Ok(*return_type) } else { Err(ValidationError::ExpectedFunction) @@ -30,7 +30,7 @@ impl AbstractTree for FunctionCall { } fn validate(&self, _context: &Context) -> Result<(), ValidationError> { - if let Type::Function { .. } = self.function.expected_type(_context)? { + if let Type::Function { .. } = self.function.node.expected_type(_context)? { Ok(()) } else { Err(ValidationError::ExpectedFunction) @@ -38,12 +38,12 @@ impl AbstractTree for FunctionCall { } fn run(self, context: &Context) -> Result { - let value = self.function.run(context)?.as_return_value()?; + let value = self.function.node.run(context)?.as_return_value()?; let function = value.as_function()?; let mut arguments = Vec::with_capacity(self.arguments.len()); for expression in self.arguments { - let value = expression.run(context)?.as_return_value()?; + let value = expression.node.run(context)?.as_return_value()?; arguments.push(value); } diff --git a/src/abstract_tree/if_else.rs b/src/abstract_tree/if_else.rs index 5cca1eb..00a2ba0 100644 --- a/src/abstract_tree/if_else.rs +++ b/src/abstract_tree/if_else.rs @@ -87,7 +87,8 @@ mod tests { Block::new(vec![Statement::Expression( Expression::Value(ValueNode::String("foo".to_string())) .positioned((0..0).into()) - )]) + ) + .positioned((0..0).into())]) .positioned((0..0).into()), None ) @@ -104,13 +105,15 @@ mod tests { Block::new(vec![Statement::Expression( Expression::Value(ValueNode::String("foo".to_string())) .positioned((0..0).into()) - )]) + ) + .positioned((0..0).into())]) .positioned((0..0).into()), Some( Block::new(vec![Statement::Expression( Expression::Value(ValueNode::String("bar".to_string())) .positioned((0..0).into()) - )]) + ) + .positioned((0..0).into())]) .positioned((0..0).into()) ) ) diff --git a/src/abstract_tree/index.rs b/src/abstract_tree/index.rs index 10dbb73..842df5d 100644 --- a/src/abstract_tree/index.rs +++ b/src/abstract_tree/index.rs @@ -3,28 +3,28 @@ use crate::{ error::{RuntimeError, ValidationError}, }; -use super::{AbstractTree, Action, Expression, Type, ValueNode}; +use super::{AbstractTree, Action, Expression, Positioned, Type, ValueNode}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct Index { - left: Expression, - right: Expression, + left: Positioned, + right: Positioned, } impl Index { - pub fn new(left: Expression, right: Expression) -> Self { + pub fn new(left: Positioned, right: Positioned) -> Self { Self { left, right } } } impl AbstractTree for Index { fn expected_type(&self, _context: &Context) -> Result { - let left_type = self.left.expected_type(_context)?; + let left_type = self.left.node.expected_type(_context)?; if let ( Expression::Value(ValueNode::List(expression_list)), Expression::Value(ValueNode::Integer(index)), - ) = (&self.left, &self.right) + ) = (&self.left.node, &self.right.node) { let expression = if let Some(expression) = expression_list.get(*index as usize) { expression @@ -32,20 +32,20 @@ impl AbstractTree for Index { return Ok(Type::None); }; - expression.expected_type(_context) + expression.node.expected_type(_context) } else { Err(ValidationError::CannotIndex(left_type)) } } fn validate(&self, context: &Context) -> Result<(), ValidationError> { - let left_type = self.left.expected_type(context)?; + let left_type = self.left.node.expected_type(context)?; match left_type { Type::List => todo!(), Type::ListOf(_) => todo!(), Type::ListExact(_) => { - let right_type = self.right.expected_type(context)?; + let right_type = self.right.node.expected_type(context)?; if let Type::Integer = right_type { Ok(()) @@ -58,8 +58,8 @@ impl AbstractTree for Index { } fn run(self, _context: &Context) -> Result { - let left_value = self.left.run(_context)?.as_return_value()?; - let right_value = self.right.run(_context)?.as_return_value()?; + let left_value = self.left.node.run(_context)?.as_return_value()?; + let right_value = self.right.node.run(_context)?.as_return_value()?; if let (Some(list), Some(index)) = (left_value.as_list(), right_value.as_integer()) { let found_item = list.get(index as usize); diff --git a/src/abstract_tree/loop.rs b/src/abstract_tree/loop.rs index f97e31f..06fb13a 100644 --- a/src/abstract_tree/loop.rs +++ b/src/abstract_tree/loop.rs @@ -3,15 +3,15 @@ use crate::{ error::{RuntimeError, ValidationError}, }; -use super::{AbstractTree, Action, Statement, Type}; +use super::{AbstractTree, Action, Positioned, Statement, Type}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct Loop { - statements: Vec, + statements: Vec>, } impl Loop { - pub fn new(statements: Vec) -> Self { + pub fn new(statements: Vec>) -> Self { Self { statements } } } @@ -23,7 +23,7 @@ impl AbstractTree for Loop { fn validate(&self, _context: &Context) -> Result<(), ValidationError> { for statement in &self.statements { - statement.validate(_context)?; + statement.node.validate(_context)?; } Ok(()) @@ -40,7 +40,7 @@ impl AbstractTree for Loop { } let statement = self.statements[index].clone(); - let action = statement.run(_context)?; + let action = statement.node.run(_context)?; match action { Action::Return(_) => {} @@ -58,7 +58,7 @@ mod tests { #[test] fn basic_loop() { let result = Loop { - statements: vec![Statement::Break], + statements: vec![Statement::Break.positioned((0..0).into())], } .run(&Context::new()); diff --git a/src/abstract_tree/math.rs b/src/abstract_tree/math.rs index c3ad396..b25bccd 100644 --- a/src/abstract_tree/math.rs +++ b/src/abstract_tree/math.rs @@ -5,15 +5,15 @@ use crate::{ Value, }; -use super::{AbstractTree, Action, Expression, Type}; +use super::{AbstractTree, Action, Expression, Positioned, Type}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub enum Math { - Add(Expression, Expression), - Subtract(Expression, Expression), - Multiply(Expression, Expression), - Divide(Expression, Expression), - Modulo(Expression, Expression), + Add(Positioned, Positioned), + Subtract(Positioned, Positioned), + Multiply(Positioned, Positioned), + Divide(Positioned, Positioned), + Modulo(Positioned, Positioned), } impl AbstractTree for Math { @@ -23,7 +23,7 @@ impl AbstractTree for Math { | Math::Subtract(left, _) | Math::Multiply(left, _) | Math::Divide(left, _) - | Math::Modulo(left, _) => left.expected_type(_context), + | Math::Modulo(left, _) => left.node.expected_type(_context), } } @@ -34,8 +34,8 @@ impl AbstractTree for Math { | Math::Multiply(left, right) | Math::Divide(left, right) | Math::Modulo(left, right) => { - let left_type = left.expected_type(context)?; - let right_type = right.expected_type(context)?; + let left_type = left.node.expected_type(context)?; + let right_type = right.node.expected_type(context)?; match (left_type, right_type) { (Type::Integer, Type::Integer) @@ -51,20 +51,20 @@ impl AbstractTree for Math { fn run(self, _context: &Context) -> Result { let value = match self { Math::Add(left, right) => { - let left_value = left.run(_context)?.as_return_value()?; - let right_value = right.run(_context)?.as_return_value()?; + let left_value = left.node.run(_context)?.as_return_value()?; + let right_value = right.node.run(_context)?.as_return_value()?; left_value.add(&right_value)? } Math::Subtract(left, right) => { - let left_value = left.run(_context)?.as_return_value()?; - let right_value = right.run(_context)?.as_return_value()?; + let left_value = left.node.run(_context)?.as_return_value()?; + let right_value = right.node.run(_context)?.as_return_value()?; left_value.subtract(&right_value)? } Math::Multiply(left, right) => { - let left_value = left.run(_context)?.as_return_value()?; - let right_value = right.run(_context)?.as_return_value()?; + let left_value = left.node.run(_context)?.as_return_value()?; + let right_value = right.node.run(_context)?.as_return_value()?; if let (ValueInner::Integer(left), ValueInner::Integer(right)) = (left_value.inner().as_ref(), right_value.inner().as_ref()) @@ -77,8 +77,8 @@ impl AbstractTree for Math { } } Math::Divide(left, right) => { - let left_value = left.run(_context)?.as_return_value()?; - let right_value = right.run(_context)?.as_return_value()?; + let left_value = left.node.run(_context)?.as_return_value()?; + let right_value = right.node.run(_context)?.as_return_value()?; if let (ValueInner::Integer(left), ValueInner::Integer(right)) = (left_value.inner().as_ref(), right_value.inner().as_ref()) @@ -91,8 +91,8 @@ impl AbstractTree for Math { } } Math::Modulo(left, right) => { - let left_value = left.run(_context)?.as_return_value()?; - let right_value = right.run(_context)?.as_return_value()?; + let left_value = left.node.run(_context)?.as_return_value()?; + let right_value = right.node.run(_context)?.as_return_value()?; if let (ValueInner::Integer(left), ValueInner::Integer(right)) = (left_value.inner().as_ref(), right_value.inner().as_ref()) diff --git a/src/abstract_tree/value_node.rs b/src/abstract_tree/value_node.rs index 16d7022..6b16a40 100644 --- a/src/abstract_tree/value_node.rs +++ b/src/abstract_tree/value_node.rs @@ -2,7 +2,7 @@ use std::{cmp::Ordering, collections::BTreeMap, ops::Range}; use crate::{ context::Context, - error::{RuntimeError, TypeConflict, ValidationError}, + error::{RuntimeError, ValidationError}, Value, }; @@ -13,12 +13,12 @@ pub enum ValueNode { Boolean(bool), Float(f64), Integer(i64), - List(Vec), + List(Vec>), Map(Vec<(Identifier, Option>, Positioned)>), Range(Range), String(String), Function { - parameters: Vec<(Identifier, Type)>, + parameters: Vec<(Identifier, Positioned)>, return_type: Positioned, body: Positioned, }, @@ -34,7 +34,7 @@ impl AbstractTree for ValueNode { let mut item_types = Vec::with_capacity(items.len()); for expression in items { - item_types.push(expression.expected_type(_context)?); + item_types.push(expression.node.expected_type(_context)?); } Type::ListExact(item_types) @@ -49,8 +49,7 @@ impl AbstractTree for ValueNode { } => Type::Function { parameter_types: parameters .into_iter() - .map(|(_, r#type)| r#type) - .cloned() + .map(|(_, r#type)| r#type.node.clone()) .collect(), return_type: Box::new(return_type.node.clone()), }, @@ -85,7 +84,7 @@ impl AbstractTree for ValueNode { let function_context = Context::inherit_types_from(context)?; for (identifier, r#type) in parameters { - function_context.set_type(identifier.clone(), r#type.clone())?; + function_context.set_type(identifier.clone(), r#type.node.clone())?; } body.node.validate(&function_context)?; @@ -114,7 +113,7 @@ impl AbstractTree for ValueNode { let mut value_list = Vec::with_capacity(expression_list.len()); for expression in expression_list { - let value = expression.run(_context)?.as_return_value()?; + let value = expression.node.run(_context)?.as_return_value()?; value_list.push(value); } diff --git a/src/abstract_tree/while.rs b/src/abstract_tree/while.rs index a73c386..76ca90f 100644 --- a/src/abstract_tree/while.rs +++ b/src/abstract_tree/while.rs @@ -3,16 +3,16 @@ use crate::{ error::{RuntimeError, ValidationError}, }; -use super::{AbstractTree, Action, Block, Expression, Type}; +use super::{AbstractTree, Action, Block, Expression, Positioned, Type}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct While { - expression: Expression, + expression: Positioned, block: Block, } impl While { - pub fn new(expression: Expression, block: Block) -> Self { + pub fn new(expression: Positioned, block: Block) -> Self { Self { expression, block } } } @@ -23,13 +23,14 @@ impl AbstractTree for While { } fn validate(&self, _context: &Context) -> Result<(), ValidationError> { - self.expression.validate(_context)?; + self.expression.node.validate(_context)?; self.block.validate(_context) } fn run(self, context: &Context) -> Result { while self .expression + .node .clone() .run(context)? .as_return_value()? diff --git a/src/parser.rs b/src/parser.rs index 6f6d3c2..7e288fc 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,6 +1,7 @@ use std::{cell::RefCell, collections::HashMap}; use chumsky::{input::SpannedInput, pratt::*, prelude::*}; +use clap::builder::TypedValueParser; use crate::{ abstract_tree::*, @@ -53,12 +54,12 @@ pub fn parser<'src>() -> DustParser<'src> { Token::Float(float) => ValueNode::Float(float), Token::String(string) => ValueNode::String(string.to_string()), } - .map(|value| Expression::Value(value)) + .map_with(|value, state| Expression::Value(value).positioned(state.span())) .boxed(); - let type_specification = recursive(|type_specification| { - let r#type = recursive(|r#type| { - let function_type = type_specification + let r#type = recursive(|r#type| { + let type_specification = recursive(|r#type| { + let function_type = r#type .clone() .separated_by(just(Token::Control(Control::Comma))) .collect() @@ -108,11 +109,9 @@ pub fn parser<'src>() -> DustParser<'src> { )) }); - just(Token::Control(Control::Colon)).ignore_then(r#type) - }); - - let positioned_type = - type_specification.map_with(|r#type, state| r#type.positioned(state.span())); + just(Token::Control(Control::Colon)).ignore_then(type_specification) + }) + .map_with(|r#type, state| r#type.positioned(state.span())); let statement = recursive(|statement| { let block = statement @@ -130,10 +129,9 @@ pub fn parser<'src>() -> DustParser<'src> { .map_with(|block, state| block.positioned(state.span())); let expression = recursive(|expression| { - let identifier_expression = identifier - .clone() - .map(|identifier| Expression::Identifier(identifier)) - .boxed(); + let identifier_expression = identifier.clone().map_with(|identifier, state| { + Expression::Identifier(identifier).positioned(state.span()) + }); let range = { let raw_integer = select! { @@ -144,7 +142,9 @@ pub fn parser<'src>() -> DustParser<'src> { .clone() .then_ignore(just(Token::Control(Control::DoubleDot))) .then(raw_integer) - .map(|(start, end)| Expression::Value(ValueNode::Range(start..end))) + .map_with(|(start, end), state| { + Expression::Value(ValueNode::Range(start..end)).positioned(state.span()) + }) }; let list = expression @@ -156,22 +156,16 @@ pub fn parser<'src>() -> DustParser<'src> { just(Token::Control(Control::SquareOpen)), just(Token::Control(Control::SquareClose)), ) - .map(|list| Expression::Value(ValueNode::List(list))) - .boxed(); + .map_with(|list, state| { + Expression::Value(ValueNode::List(list)).positioned(state.span()) + }); let map_assignment = identifier .clone() - .then( - type_specification - .map_with(|r#type, state| r#type.positioned(state.span())) - .clone() - .or_not(), - ) + .then(r#type.clone().or_not()) .then_ignore(just(Token::Operator(Operator::Assign))) .then(expression.clone()) - .map_with(|((identifier, r#type), expression), state| { - (identifier, r#type, expression.positioned(state.span())) - }); + .map(|((identifier, r#type), expression)| (identifier, r#type, expression)); let map = map_assignment .separated_by(just(Token::Control(Control::Comma)).or_not()) @@ -181,27 +175,29 @@ pub fn parser<'src>() -> DustParser<'src> { just(Token::Control(Control::CurlyOpen)), just(Token::Control(Control::CurlyClose)), ) - .map(|map_assigment_list| Expression::Value(ValueNode::Map(map_assigment_list))); + .map_with(|map_assigment_list, state| { + Expression::Value(ValueNode::Map(map_assigment_list)).positioned(state.span()) + }); let function = identifier .clone() - .then(type_specification.clone()) + .then(r#type.clone()) .separated_by(just(Token::Control(Control::Comma))) - .collect::>() + .collect() .delimited_by( just(Token::Control(Control::ParenOpen)), just(Token::Control(Control::ParenClose)), ) - .then(type_specification.clone()) + .then(r#type.clone()) .then(block.clone()) .map_with(|((parameters, return_type), body), state| { Expression::Value(ValueNode::Function { parameters, - return_type: return_type.positioned(state.span()), + return_type, body: body.positioned(state.span()), }) - }) - .boxed(); + .positioned(state.span()) + }); let function_expression = choice((identifier_expression.clone(), function.clone())); @@ -216,13 +212,13 @@ pub fn parser<'src>() -> DustParser<'src> { just(Token::Control(Control::ParenClose)), ), ) - .map(|(function, arguments)| { + .map_with(|(function, arguments), state| { Expression::FunctionCall(FunctionCall::new(function, arguments)) - }) - .boxed(); + .positioned(state.span()) + }); let atom = choice(( - function_call, + function_call.clone(), identifier_expression.clone(), basic_value.clone(), list.clone(), @@ -230,68 +226,115 @@ pub fn parser<'src>() -> DustParser<'src> { just(Token::Control(Control::ParenOpen)), just(Token::Control(Control::ParenClose)), ), - )) - .map_with(|expression, state| expression.positioned(state.span())); + )); use Operator::*; - let logic_math_and_index = atom - .pratt(( - prefix(2, just(Token::Operator(Not)), |expression| { - Expression::Logic(Box::new(Logic::Not(expression))) - }), - infix(left(1), just(Token::Operator(Equal)), |left, right| { - Expression::Logic(Box::new(Logic::Equal(left, right))) - }), - infix(left(1), just(Token::Operator(NotEqual)), |left, right| { - Expression::Logic(Box::new(Logic::NotEqual(left, right))) - }), - infix(left(1), just(Token::Operator(Greater)), |left, right| { - Expression::Logic(Box::new(Logic::Greater(left, right))) - }), - infix(left(1), just(Token::Operator(Less)), |left, right| { - Expression::Logic(Box::new(Logic::Less(left, right))) - }), - infix( - left(1), - just(Token::Operator(GreaterOrEqual)), - |left, right| { - Expression::Logic(Box::new(Logic::GreaterOrEqual(left, right))) - }, - ), - infix( - left(1), - just(Token::Operator(LessOrEqual)), - |left, right| Expression::Logic(Box::new(Logic::LessOrEqual(left, right))), - ), - infix(left(1), just(Token::Operator(And)), |left, right| { - Expression::Logic(Box::new(Logic::And(left, right))) - }), - infix(left(1), just(Token::Operator(Or)), |left, right| { - Expression::Logic(Box::new(Logic::Or(left, right))) - }), - infix(left(1), just(Token::Operator(Add)), |left, right| { - Expression::Math(Box::new(Math::Add(left, right))) - }), - infix(left(1), just(Token::Operator(Subtract)), |left, right| { - Expression::Math(Box::new(Math::Subtract(left, right))) - }), - infix(left(2), just(Token::Operator(Multiply)), |left, right| { - Expression::Math(Box::new(Math::Multiply(left, right))) - }), - infix(left(2), just(Token::Operator(Divide)), |left, right| { - Expression::Math(Box::new(Math::Divide(left, right))) - }), - infix(left(1), just(Token::Operator(Modulo)), |left, right| { - Expression::Math(Box::new(Math::Modulo(left, right))) - }), - infix( - left(3), - just(Token::Control(Control::Dot)), - |left, right| Expression::Index(Box::new(Index::new(left, right))), - ), - )) - .boxed(); + let logic_math_and_index = atom.pratt(( + prefix(2, just(Token::Operator(Not)), |_, expression, span| { + Expression::Logic(Box::new(Logic::Not(expression))).positioned(span) + }), + infix( + left(3), + just(Token::Control(Control::Dot)), + |left, _, right, span| { + Expression::Index(Box::new(Index::new(left, right))).positioned(span) + }, + ), + infix( + left(1), + just(Token::Operator(Equal)), + |left, _, right, span| { + Expression::Logic(Box::new(Logic::Equal(left, right))).positioned(span) + }, + ), + infix( + left(1), + just(Token::Operator(NotEqual)), + |left, _, right, span| { + Expression::Logic(Box::new(Logic::NotEqual(left, right))).positioned(span) + }, + ), + infix( + left(1), + just(Token::Operator(Greater)), + |left, _, right, span| { + Expression::Logic(Box::new(Logic::Greater(left, right))).positioned(span) + }, + ), + infix( + left(1), + just(Token::Operator(Less)), + |left, _, right, span| { + Expression::Logic(Box::new(Logic::Less(left, right))).positioned(span) + }, + ), + infix( + left(1), + just(Token::Operator(GreaterOrEqual)), + |left, _, right, span| { + Expression::Logic(Box::new(Logic::GreaterOrEqual(left, right))) + .positioned(span) + }, + ), + infix( + left(1), + just(Token::Operator(LessOrEqual)), + |left, _, right, span| { + Expression::Logic(Box::new(Logic::LessOrEqual(left, right))) + .positioned(span) + }, + ), + infix( + left(1), + just(Token::Operator(And)), + |left, _, right, span| { + Expression::Logic(Box::new(Logic::And(left, right))).positioned(span) + }, + ), + infix( + left(1), + just(Token::Operator(Or)), + |left, _, right, span| { + Expression::Logic(Box::new(Logic::Or(left, right))).positioned(span) + }, + ), + infix( + left(1), + just(Token::Operator(Add)), + |left, _, right, span| { + Expression::Math(Box::new(Math::Add(left, right))).positioned(span) + }, + ), + infix( + left(1), + just(Token::Operator(Subtract)), + |left, _, right, span| { + Expression::Math(Box::new(Math::Subtract(left, right))).positioned(span) + }, + ), + infix( + left(2), + just(Token::Operator(Multiply)), + |left, _, right, span| { + Expression::Math(Box::new(Math::Multiply(left, right))).positioned(span) + }, + ), + infix( + left(2), + just(Token::Operator(Divide)), + |left, _, right, span| { + Expression::Math(Box::new(Math::Divide(left, right))).positioned(span) + }, + ), + infix( + left(1), + just(Token::Operator(Modulo)), + |left, _, right, span| { + Expression::Math(Box::new(Math::Modulo(left, right))).positioned(span) + }, + ), + )); choice(( function, @@ -303,25 +346,18 @@ pub fn parser<'src>() -> DustParser<'src> { map, basic_value, )) - .boxed() }); - let positioned_expression = expression - .clone() - .map_with(|expression, state| expression.positioned(state.span())); + let expression_statement = expression.clone().map_with(|expression, state| { + Statement::Expression(expression).positioned(state.span()) + }); - let expression_statement = expression - .clone() - .map_with(|expression, state| { - Statement::Expression(expression.positioned(state.span())) - }) - .boxed(); - - let r#break = just(Token::Keyword("break")).to(Statement::Break); + let r#break = just(Token::Keyword("break")) + .map_with(|_, state| Statement::Break.positioned(state.span())); let assignment = identifier .clone() - .then(positioned_type.clone().or_not()) + .then(r#type.clone().or_not()) .then(choice(( just(Token::Operator(Operator::Assign)).to(AssignmentOperator::Assign), just(Token::Operator(Operator::AddAssign)).to(AssignmentOperator::AddAssign), @@ -329,18 +365,13 @@ pub fn parser<'src>() -> DustParser<'src> { ))) .then(statement.clone()) .map_with(|(((identifier, r#type), operator), statement), state| { - Statement::Assignment(Assignment::new( - identifier, - r#type, - operator, - statement.positioned(state.span()), - )) - }) - .boxed(); + Statement::Assignment(Assignment::new(identifier, r#type, operator, statement)) + .positioned(state.span()) + }); let block_statement = block .clone() - .map_with(|block, state| Statement::Block(block)); + .map_with(|block, state| Statement::Block(block).positioned(state.span())); let r#loop = statement .clone() @@ -351,16 +382,19 @@ pub fn parser<'src>() -> DustParser<'src> { just(Token::Keyword("loop")).then(just(Token::Control(Control::CurlyOpen))), just(Token::Control(Control::CurlyClose)), ) - .map_with(|statements, state| Statement::Loop(Loop::new(statements))) - .boxed(); + .map_with(|statements, state| { + Statement::Loop(Loop::new(statements)).positioned(state.span()) + }); let r#while = just(Token::Keyword("while")) .ignore_then(expression.clone()) .then(block.clone()) - .map_with(|(expression, block), state| Statement::While(While::new(expression, block))); + .map_with(|(expression, block), state| { + Statement::While(While::new(expression, block)).positioned(state.span()) + }); let if_else = just(Token::Keyword("if")) - .ignore_then(positioned_expression.clone()) + .ignore_then(expression.clone()) .then(positioned_block.clone()) .then( just(Token::Keyword("else")) @@ -369,8 +403,8 @@ pub fn parser<'src>() -> DustParser<'src> { ) .map_with(|((if_expression, if_block), else_block), state| { Statement::IfElse(IfElse::new(if_expression, if_block, else_block)) - }) - .boxed(); + .positioned(state.span()) + }); choice(( if_else, @@ -382,14 +416,9 @@ pub fn parser<'src>() -> DustParser<'src> { r#while, )) .then_ignore(just(Token::Control(Control::Semicolon)).or_not()) - .boxed() }); - statement - .map_with(|statement, state| statement.positioned(state.span())) - .repeated() - .collect() - .boxed() + statement.repeated().collect().boxed() } #[cfg(test)] @@ -402,19 +431,19 @@ mod tests { fn r#while() { assert_eq!( parse(&lex("while true { output('hi') }").unwrap()).unwrap()[0], - Statement::r#while( - While::new( - Expression::Value(ValueNode::Boolean(true)), - Block::new(vec![Statement::expression( - Expression::FunctionCall(FunctionCall::new( - Expression::Identifier(Identifier::new("output")), - vec![Expression::Value(ValueNode::String("hi".to_string()))] - )), - (0..0).into() - )]) - ), - (0..0).into() - ) + Statement::While(While::new( + Expression::Value(ValueNode::Boolean(true)).positioned((0..0).into()), + Block::new(vec![Statement::Expression( + Expression::FunctionCall(FunctionCall::new( + Expression::Identifier(Identifier::new("output")).positioned((0..0).into()), + vec![Expression::Value(ValueNode::String("hi".to_string())) + .positioned((0..0).into())] + )) + .positioned((0..0).into()) + ) + .positioned((0..0).into())]) + )) + .positioned((0..0).into()) ) } @@ -422,35 +451,33 @@ mod tests { fn types() { assert_eq!( parse(&lex("foobar : bool = true").unwrap()).unwrap()[0], - Statement::assignment( - Assignment::new( - Identifier::new("foobar"), - Some(Type::Boolean), - AssignmentOperator::Assign, - Statement::expression( - Expression::Value(ValueNode::Boolean(true)), - (0..0).into() - ) - ), - (0..0).into() - ) + Statement::Assignment(Assignment::new( + Identifier::new("foobar"), + Some(Type::Boolean.positioned((0..0).into())), + AssignmentOperator::Assign, + Statement::Expression( + Expression::Value(ValueNode::Boolean(true)).positioned((0..0).into()) + ) + .positioned((0..0).into()) + ),) + .positioned((0..0).into()) ); assert_eq!( parse(&lex("foobar : list(bool) = [true]").unwrap()).unwrap()[0], - Statement::assignment( - Assignment::new( - Identifier::new("foobar"), - Some(Type::ListOf(Box::new(Type::Boolean))), - AssignmentOperator::Assign, - Statement::expression( - Expression::Value(ValueNode::List(vec![Expression::Value( - ValueNode::Boolean(true) - )])), - (0..0).into() + Statement::Assignment(Assignment::new( + Identifier::new("foobar"), + Some(Type::ListOf(Box::new(Type::Boolean)).positioned((0..0).into())), + AssignmentOperator::Assign, + Statement::Expression( + Expression::Value(ValueNode::List(vec![Expression::Value( + ValueNode::Boolean(true) ) - ), - (0..0).into() - ) + .positioned((0..0).into())])) + .positioned((0..0).into()) + ) + .positioned((0..0).into()) + )) + .positioned((0..0).into()) ); assert_eq!( parse(&lex("foobar : [bool, str] = [true, '42']").unwrap()).unwrap()[0], diff --git a/src/value.rs b/src/value.rs index e53b7ce..d592a6d 100644 --- a/src/value.rs +++ b/src/value.rs @@ -55,7 +55,7 @@ impl Value { } pub fn function( - parameters: Vec<(Identifier, Type)>, + parameters: Vec<(Identifier, Positioned)>, return_type: Positioned, body: Positioned, ) -> Self { @@ -224,7 +224,7 @@ impl Display for Value { write!(f, "(")?; for (identifier, r#type) in parameters { - write!(f, "{identifier}: {}", r#type)?; + write!(f, "{identifier}: {}", r#type.node)?; } write!(f, "): {} {:?}", return_type.node, body.node) @@ -330,7 +330,7 @@ impl Function { #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct ParsedFunction { - parameters: Vec<(Identifier, Type)>, + parameters: Vec<(Identifier, Positioned)>, return_type: Positioned, body: Positioned, }