From 9eb047a913813cd34790fa4e9364719ae4324ceb Mon Sep 17 00:00:00 2001 From: Jeff Date: Sat, 18 May 2024 16:21:46 -0400 Subject: [PATCH] Revert to pratt parsing for all indexes --- dust-lang/src/abstract_tree/map_index.rs | 34 +++---- dust-lang/src/error.rs | 2 +- dust-lang/src/lib.rs | 2 +- dust-lang/src/parser.rs | 117 +++++++++++------------ dust-lang/tests/functions.rs | 24 ++--- dust-lang/tests/variables.rs | 10 +- std/io.ds | 4 +- std/thread.ds | 2 +- 8 files changed, 94 insertions(+), 101 deletions(-) diff --git a/dust-lang/src/abstract_tree/map_index.rs b/dust-lang/src/abstract_tree/map_index.rs index aadd398..ce933a3 100644 --- a/dust-lang/src/abstract_tree/map_index.rs +++ b/dust-lang/src/abstract_tree/map_index.rs @@ -1,7 +1,6 @@ use crate::{ context::Context, error::{RuntimeError, ValidationError}, - identifier::Identifier, value::ValueInner, }; @@ -10,11 +9,11 @@ use super::{AbstractNode, Action, Expression, Type, ValueNode, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct MapIndex { collection: Expression, - index: WithPosition, + index: Expression, } impl MapIndex { - pub fn new(left: Expression, right: WithPosition) -> Self { + pub fn new(left: Expression, right: Expression) -> Self { Self { collection: left, index: right, @@ -24,18 +23,17 @@ impl MapIndex { impl AbstractNode for MapIndex { fn expected_type(&self, context: &mut Context) -> Result { - if let (Expression::Identifier(collection_identifier), index) = + if let (Expression::Identifier(collection), Expression::Identifier(index)) = (&self.collection, &self.index) { - let collection = - if let Some(collection) = context.get_value(&collection_identifier.item)? { - collection - } else { - return Err(ValidationError::VariableNotFound { - identifier: collection_identifier.item.clone(), - position: collection_identifier.position, - }); - }; + let collection = if let Some(collection) = context.get_value(&collection.item)? { + collection + } else { + return Err(ValidationError::VariableNotFound { + identifier: collection.item.clone(), + position: collection.position, + }); + }; if let ValueInner::Map(map) = collection.inner().as_ref() { return if let Some(value) = map.get(&index.item) { @@ -54,7 +52,7 @@ impl AbstractNode for MapIndex { item: ValueNode::Map(properties), .. }), - index, + Expression::Identifier(index), ) = (&self.collection, &self.index) { return if let Some(type_result) = @@ -83,7 +81,7 @@ impl AbstractNode for MapIndex { item: ValueNode::Structure { fields, .. }, .. }), - index, + Expression::Identifier(index), ) = (&self.collection, &self.index) { return if let Some(type_result) = fields.iter().find_map(|(property, expression)| { @@ -124,9 +122,11 @@ impl AbstractNode for MapIndex { )); }; - if let ValueInner::Map(map) = collection.inner().as_ref() { + if let (ValueInner::Map(map), Expression::Identifier(index)) = + (collection.inner().as_ref(), self.index) + { let action = map - .get(&self.index.item) + .get(&index.item) .map(|value| Action::Return(value.clone())) .unwrap_or(Action::None); diff --git a/dust-lang/src/error.rs b/dust-lang/src/error.rs index 5804faa..649944d 100644 --- a/dust-lang/src/error.rs +++ b/dust-lang/src/error.rs @@ -1,6 +1,6 @@ use std::{io, sync::PoisonError}; -use chumsky::{container::Container, prelude::Rich, span::Span}; +use chumsky::{prelude::Rich, span::Span}; use crate::{ abstract_tree::{SourcePosition, Type}, diff --git a/dust-lang/src/lib.rs b/dust-lang/src/lib.rs index 96abe86..fc7d6c7 100644 --- a/dust-lang/src/lib.rs +++ b/dust-lang/src/lib.rs @@ -14,7 +14,7 @@ use std::{ use abstract_tree::{AbstractTree, Type}; use ariadne::{Color, Fmt, Label, Report, ReportKind}; -use chumsky::{container::Container, prelude::*}; +use chumsky::prelude::*; use context::Context; use error::{Error, RuntimeError, TypeConflict, ValidationError}; use lexer::lex; diff --git a/dust-lang/src/parser.rs b/dust-lang/src/parser.rs index 18596f7..9d58067 100644 --- a/dust-lang/src/parser.rs +++ b/dust-lang/src/parser.rs @@ -231,20 +231,21 @@ pub fn parser<'src>( just(Token::Control(Control::ParenClose)), ); - let parsed_function = 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()), + 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()), + ), ) .map_with( |(type_arguments, ((parameters, return_type), body)), state| { @@ -325,33 +326,7 @@ pub fn parser<'src>( just(Token::Control(Control::DoubleColon)), ); - let map_index = choice(( - map.clone(), - structure_instance.clone(), - identifier_expression.clone(), - )) - .then_ignore(just(Token::Control(Control::Dot))) - .then(positioned_identifier.clone()) - .map_with(|(expression, identifier), state| { - Expression::MapIndex( - Box::new(MapIndex::new(expression, identifier)).with_position(state.span()), - ) - }); - - let list_index = choice((list.clone(), identifier_expression.clone())) - .then(expression.clone().delimited_by( - just(Token::Control(Control::SquareOpen)), - just(Token::Control(Control::SquareClose)), - )) - .map_with(|(left, right), state| { - Expression::ListIndex( - Box::new(ListIndex::new(left, right)).with_position(state.span()), - ) - }); - let atom = choice(( - map_index.clone(), - list_index.clone(), range.clone(), parsed_function.clone(), list.clone(), @@ -365,7 +340,7 @@ pub fn parser<'src>( ), )); - let logic_math_and_function_calls = atom.pratt(( + let logic_math_indexes_and_function_calls = atom.pratt(( prefix( 2, just(Token::Operator(Operator::Not)), @@ -373,6 +348,27 @@ pub fn parser<'src>( Expression::Logic(Box::new(Logic::Not(expression)).with_position(span)) }, ), + postfix( + 3, + expression.clone().delimited_by( + just(Token::Control(Control::SquareOpen)), + just(Token::Control(Control::SquareClose)), + ), + |left, right, span| { + Expression::ListIndex( + Box::new(ListIndex::new(left, right)).with_position(span), + ) + }, + ), + infix( + left(4), + just(Token::Control(Control::Dot)), + |left: Expression, _: Token, right: Expression, span| { + Expression::MapIndex( + Box::new(MapIndex::new(left, right)).with_position(span), + ) + }, + ), postfix( 3, turbofish.clone().or_not().then( @@ -499,11 +495,8 @@ pub fn parser<'src>( }, ), )); - choice(( - logic_math_and_function_calls, - list_index, - map_index, + logic_math_indexes_and_function_calls, built_in_function_call, range, structure_instance, @@ -775,7 +768,7 @@ mod tests { )]) .with_position((0, 10)) ), - Identifier::new("x").with_position((11, 12)) + Expression::Identifier(Identifier::new("x").with_position((11, 12))) )) .with_position((0, 12)) )) @@ -785,7 +778,7 @@ mod tests { Statement::Expression(Expression::MapIndex( Box::new(MapIndex::new( Expression::Identifier(Identifier::new("foo").with_position((0, 3))), - Identifier::new("x").with_position((4, 5)) + Expression::Identifier(Identifier::new("x").with_position((4, 5))) )) .with_position((0, 5)) )) @@ -976,18 +969,18 @@ mod tests { #[test] fn function() { assert_eq!( - parse(&lex("(x: int) int { x }").unwrap()).unwrap()[0], + parse(&lex("fn (x: int) int { x }").unwrap()).unwrap()[0], Statement::Expression(Expression::Value( ValueNode::ParsedFunction { type_arguments: Vec::with_capacity(0), - parameters: vec![(Identifier::new("x"), Type::Integer.with_position((4, 7)))], - return_type: Type::Integer.with_position((9, 12)), + parameters: vec![(Identifier::new("x"), Type::Integer.with_position((7, 10)))], + return_type: Type::Integer.with_position((12, 15)), body: Block::new(vec![Statement::Expression(Expression::Identifier( - Identifier::new("x").with_position((15, 16)) + Identifier::new("x").with_position((18, 19)) ))]) - .with_position((13, 18)), + .with_position((16, 21)), } - .with_position((0, 18)) + .with_position((0, 21)) ),) ) } @@ -995,30 +988,30 @@ mod tests { #[test] fn function_with_type_arguments() { assert_eq!( - parse(&lex("(T, U)(x: T, y: U) T { x }").unwrap()).unwrap()[0], + parse(&lex("fn (T, U)(x: T, y: U) T { x }").unwrap()).unwrap()[0], Statement::Expression(Expression::Value( ValueNode::ParsedFunction { type_arguments: vec![ - Type::Argument(Identifier::new("T")).with_position((1, 2)), - Type::Argument(Identifier::new("U")).with_position((4, 5)), + Type::Argument(Identifier::new("T")).with_position((4, 5)), + Type::Argument(Identifier::new("U")).with_position((7, 8)), ], parameters: vec![ ( Identifier::new("x"), - Type::Argument(Identifier::new("T")).with_position((10, 11)) + Type::Argument(Identifier::new("T")).with_position((13, 14)) ), ( Identifier::new("y"), - Type::Argument(Identifier::new("U")).with_position((16, 17)) + Type::Argument(Identifier::new("U")).with_position((19, 20)) ) ], - return_type: Type::Argument(Identifier::new("T")).with_position((19, 20)), + return_type: Type::Argument(Identifier::new("T")).with_position((22, 23)), body: Block::new(vec![Statement::Expression(Expression::Identifier( - Identifier::new("x").with_position((23, 24)) + Identifier::new("x").with_position((26, 27)) ))]) - .with_position((21, 26)), + .with_position((24, 29)), } - .with_position((0, 26)) + .with_position((0, 29)) )) ) } diff --git a/dust-lang/tests/functions.rs b/dust-lang/tests/functions.rs index 23586fd..5324bb1 100644 --- a/dust-lang/tests/functions.rs +++ b/dust-lang/tests/functions.rs @@ -10,7 +10,7 @@ fn function_call_with_type_argument() { interpret( "test", " - foobar = (T)(x : T) T { x } + foobar = fn (T)(x : T) T { x } foobar::(int)::(42) ", ), @@ -24,7 +24,7 @@ fn function_call() { interpret( "test", " - foobar = (message : str) str { message } + foobar = fn (message : str) str { message } foobar('Hiya') ", ), @@ -38,7 +38,7 @@ fn call_empty_function() { interpret( "test", " - foobar = (message : str) none {} + foobar = fn (message : str) none {} foobar('Hiya') ", ), @@ -52,10 +52,10 @@ fn callback() { interpret( "test", " - foobar = (cb: fn() -> str) str { + foobar = fn (cb: fn() -> str) str { cb() } - foobar(() str { 'Hiya' }) + foobar(fn () str { 'Hiya' }) ", ), Ok(Some(Value::string("Hiya".to_string()))) @@ -75,7 +75,7 @@ fn function_context_does_not_capture_values() { " x = 1 - foo = () any { x } + foo = fn () any { x } " ) .unwrap_err() @@ -83,9 +83,9 @@ fn function_context_does_not_capture_values() { &vec![Error::Validation { error: ValidationError::VariableNotFound { identifier: Identifier::new("x"), - position: (47, 48).into() + position: (50, 51).into() }, - position: (32, 50).into() + position: (32, 53).into() }] ); @@ -94,7 +94,7 @@ fn function_context_does_not_capture_values() { "test", " x = 1 - foo = (x: int) int { x } + foo = fn (x: int) int { x } foo(2) " ), @@ -108,8 +108,8 @@ fn function_context_captures_functions() { interpret( "test", " - bar = () int { 2 } - foo = () int { bar() } + bar = fn () int { 2 } + foo = fn () int { bar() } foo() " ), @@ -123,7 +123,7 @@ fn recursion() { interpret( "test", " - fib = (i: int) int { + fib = fn (i: int) int { if i <= 1 { 1 } else { diff --git a/dust-lang/tests/variables.rs b/dust-lang/tests/variables.rs index 51210d3..50ab1ae 100644 --- a/dust-lang/tests/variables.rs +++ b/dust-lang/tests/variables.rs @@ -44,15 +44,15 @@ fn set_variable_with_type_error() { #[test] fn function_variable() { assert_eq!( - interpret("test", "foobar = (x: int) int { x }; foobar"), + 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((13, 16)))], - Type::Integer.with_position((18, 21)), + vec![(Identifier::new("x"), Type::Integer.with_position((16, 19)))], + Type::Integer.with_position((21, 24)), Block::new(vec![Statement::Expression(Expression::Identifier( - Identifier::new("x").with_position((24, 25)) + Identifier::new("x").with_position((27, 28)) ))]) - .with_position((22, 27)) + .with_position((25, 30)) ))) ); } diff --git a/std/io.ds b/std/io.ds index 3d7a986..4f21e2f 100644 --- a/std/io.ds +++ b/std/io.ds @@ -1,9 +1,9 @@ io = { - read_line = () str { + read_line = fn () str { READ_LINE() } - write_line = (output: any) none { + write_line = fn (output: any) none { WRITE_LINE(output) } } diff --git a/std/thread.ds b/std/thread.ds index 4d69122..95d439b 100644 --- a/std/thread.ds +++ b/std/thread.ds @@ -1,5 +1,5 @@ thread = { - sleep = (milliseconds: int) none { + sleep = fn (milliseconds: int) none { SLEEP(milliseconds) } }