1
0

Revert to pratt parsing for all indexes

This commit is contained in:
Jeff 2024-05-18 16:21:46 -04:00
parent 42f48e8d76
commit 9eb047a913
8 changed files with 94 additions and 101 deletions

View File

@ -1,7 +1,6 @@
use crate::{ use crate::{
context::Context, context::Context,
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
identifier::Identifier,
value::ValueInner, value::ValueInner,
}; };
@ -10,11 +9,11 @@ use super::{AbstractNode, Action, Expression, Type, ValueNode, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct MapIndex { pub struct MapIndex {
collection: Expression, collection: Expression,
index: WithPosition<Identifier>, index: Expression,
} }
impl MapIndex { impl MapIndex {
pub fn new(left: Expression, right: WithPosition<Identifier>) -> Self { pub fn new(left: Expression, right: Expression) -> Self {
Self { Self {
collection: left, collection: left,
index: right, index: right,
@ -24,16 +23,15 @@ impl MapIndex {
impl AbstractNode for MapIndex { impl AbstractNode for MapIndex {
fn expected_type(&self, context: &mut Context) -> Result<Type, ValidationError> { fn expected_type(&self, context: &mut Context) -> Result<Type, ValidationError> {
if let (Expression::Identifier(collection_identifier), index) = if let (Expression::Identifier(collection), Expression::Identifier(index)) =
(&self.collection, &self.index) (&self.collection, &self.index)
{ {
let collection = let collection = if let Some(collection) = context.get_value(&collection.item)? {
if let Some(collection) = context.get_value(&collection_identifier.item)? {
collection collection
} else { } else {
return Err(ValidationError::VariableNotFound { return Err(ValidationError::VariableNotFound {
identifier: collection_identifier.item.clone(), identifier: collection.item.clone(),
position: collection_identifier.position, position: collection.position,
}); });
}; };
@ -54,7 +52,7 @@ impl AbstractNode for MapIndex {
item: ValueNode::Map(properties), item: ValueNode::Map(properties),
.. ..
}), }),
index, Expression::Identifier(index),
) = (&self.collection, &self.index) ) = (&self.collection, &self.index)
{ {
return if let Some(type_result) = return if let Some(type_result) =
@ -83,7 +81,7 @@ impl AbstractNode for MapIndex {
item: ValueNode::Structure { fields, .. }, item: ValueNode::Structure { fields, .. },
.. ..
}), }),
index, Expression::Identifier(index),
) = (&self.collection, &self.index) ) = (&self.collection, &self.index)
{ {
return if let Some(type_result) = fields.iter().find_map(|(property, expression)| { 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 let action = map
.get(&self.index.item) .get(&index.item)
.map(|value| Action::Return(value.clone())) .map(|value| Action::Return(value.clone()))
.unwrap_or(Action::None); .unwrap_or(Action::None);

View File

@ -1,6 +1,6 @@
use std::{io, sync::PoisonError}; use std::{io, sync::PoisonError};
use chumsky::{container::Container, prelude::Rich, span::Span}; use chumsky::{prelude::Rich, span::Span};
use crate::{ use crate::{
abstract_tree::{SourcePosition, Type}, abstract_tree::{SourcePosition, Type},

View File

@ -14,7 +14,7 @@ use std::{
use abstract_tree::{AbstractTree, Type}; use abstract_tree::{AbstractTree, Type};
use ariadne::{Color, Fmt, Label, Report, ReportKind}; use ariadne::{Color, Fmt, Label, Report, ReportKind};
use chumsky::{container::Container, prelude::*}; use chumsky::prelude::*;
use context::Context; use context::Context;
use error::{Error, RuntimeError, TypeConflict, ValidationError}; use error::{Error, RuntimeError, TypeConflict, ValidationError};
use lexer::lex; use lexer::lex;

View File

@ -231,9 +231,9 @@ pub fn parser<'src>(
just(Token::Control(Control::ParenClose)), just(Token::Control(Control::ParenClose)),
); );
let parsed_function = type_arguments let parsed_function = just(Token::Keyword(Keyword::Fn))
.or_not() .ignore_then(
.then( type_arguments.or_not().then(
identifier identifier
.clone() .clone()
.then(type_specification.clone()) .then(type_specification.clone())
@ -245,6 +245,7 @@ pub fn parser<'src>(
) )
.then(r#type.clone()) .then(r#type.clone())
.then(block.clone()), .then(block.clone()),
),
) )
.map_with( .map_with(
|(type_arguments, ((parameters, return_type), body)), state| { |(type_arguments, ((parameters, return_type), body)), state| {
@ -325,33 +326,7 @@ pub fn parser<'src>(
just(Token::Control(Control::DoubleColon)), 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(( let atom = choice((
map_index.clone(),
list_index.clone(),
range.clone(), range.clone(),
parsed_function.clone(), parsed_function.clone(),
list.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( prefix(
2, 2,
just(Token::Operator(Operator::Not)), just(Token::Operator(Operator::Not)),
@ -373,6 +348,27 @@ pub fn parser<'src>(
Expression::Logic(Box::new(Logic::Not(expression)).with_position(span)) 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( postfix(
3, 3,
turbofish.clone().or_not().then( turbofish.clone().or_not().then(
@ -499,11 +495,8 @@ pub fn parser<'src>(
}, },
), ),
)); ));
choice(( choice((
logic_math_and_function_calls, logic_math_indexes_and_function_calls,
list_index,
map_index,
built_in_function_call, built_in_function_call,
range, range,
structure_instance, structure_instance,
@ -775,7 +768,7 @@ mod tests {
)]) )])
.with_position((0, 10)) .with_position((0, 10))
), ),
Identifier::new("x").with_position((11, 12)) Expression::Identifier(Identifier::new("x").with_position((11, 12)))
)) ))
.with_position((0, 12)) .with_position((0, 12))
)) ))
@ -785,7 +778,7 @@ mod tests {
Statement::Expression(Expression::MapIndex( Statement::Expression(Expression::MapIndex(
Box::new(MapIndex::new( Box::new(MapIndex::new(
Expression::Identifier(Identifier::new("foo").with_position((0, 3))), 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)) .with_position((0, 5))
)) ))
@ -976,18 +969,18 @@ mod tests {
#[test] #[test]
fn function() { fn function() {
assert_eq!( 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( Statement::Expression(Expression::Value(
ValueNode::ParsedFunction { ValueNode::ParsedFunction {
type_arguments: Vec::with_capacity(0), type_arguments: Vec::with_capacity(0),
parameters: vec![(Identifier::new("x"), Type::Integer.with_position((4, 7)))], parameters: vec![(Identifier::new("x"), Type::Integer.with_position((7, 10)))],
return_type: Type::Integer.with_position((9, 12)), return_type: Type::Integer.with_position((12, 15)),
body: Block::new(vec![Statement::Expression(Expression::Identifier( 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] #[test]
fn function_with_type_arguments() { fn function_with_type_arguments() {
assert_eq!( 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( Statement::Expression(Expression::Value(
ValueNode::ParsedFunction { ValueNode::ParsedFunction {
type_arguments: vec![ type_arguments: vec![
Type::Argument(Identifier::new("T")).with_position((1, 2)), Type::Argument(Identifier::new("T")).with_position((4, 5)),
Type::Argument(Identifier::new("U")).with_position((4, 5)), Type::Argument(Identifier::new("U")).with_position((7, 8)),
], ],
parameters: vec![ parameters: vec![
( (
Identifier::new("x"), Identifier::new("x"),
Type::Argument(Identifier::new("T")).with_position((10, 11)) Type::Argument(Identifier::new("T")).with_position((13, 14))
), ),
( (
Identifier::new("y"), 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( 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))
)) ))
) )
} }

View File

@ -10,7 +10,7 @@ fn function_call_with_type_argument() {
interpret( interpret(
"test", "test",
" "
foobar = (T)(x : T) T { x } foobar = fn (T)(x : T) T { x }
foobar::(int)::(42) foobar::(int)::(42)
", ",
), ),
@ -24,7 +24,7 @@ fn function_call() {
interpret( interpret(
"test", "test",
" "
foobar = (message : str) str { message } foobar = fn (message : str) str { message }
foobar('Hiya') foobar('Hiya')
", ",
), ),
@ -38,7 +38,7 @@ fn call_empty_function() {
interpret( interpret(
"test", "test",
" "
foobar = (message : str) none {} foobar = fn (message : str) none {}
foobar('Hiya') foobar('Hiya')
", ",
), ),
@ -52,10 +52,10 @@ fn callback() {
interpret( interpret(
"test", "test",
" "
foobar = (cb: fn() -> str) str { foobar = fn (cb: fn() -> str) str {
cb() cb()
} }
foobar(() str { 'Hiya' }) foobar(fn () str { 'Hiya' })
", ",
), ),
Ok(Some(Value::string("Hiya".to_string()))) Ok(Some(Value::string("Hiya".to_string())))
@ -75,7 +75,7 @@ fn function_context_does_not_capture_values() {
" "
x = 1 x = 1
foo = () any { x } foo = fn () any { x }
" "
) )
.unwrap_err() .unwrap_err()
@ -83,9 +83,9 @@ fn function_context_does_not_capture_values() {
&vec![Error::Validation { &vec![Error::Validation {
error: ValidationError::VariableNotFound { error: ValidationError::VariableNotFound {
identifier: Identifier::new("x"), 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", "test",
" "
x = 1 x = 1
foo = (x: int) int { x } foo = fn (x: int) int { x }
foo(2) foo(2)
" "
), ),
@ -108,8 +108,8 @@ fn function_context_captures_functions() {
interpret( interpret(
"test", "test",
" "
bar = () int { 2 } bar = fn () int { 2 }
foo = () int { bar() } foo = fn () int { bar() }
foo() foo()
" "
), ),
@ -123,7 +123,7 @@ fn recursion() {
interpret( interpret(
"test", "test",
" "
fib = (i: int) int { fib = fn (i: int) int {
if i <= 1 { if i <= 1 {
1 1
} else { } else {

View File

@ -44,15 +44,15 @@ fn set_variable_with_type_error() {
#[test] #[test]
fn function_variable() { fn function_variable() {
assert_eq!( assert_eq!(
interpret("test", "foobar = (x: int) int { x }; foobar"), interpret("test", "foobar = fn (x: int) int { x }; foobar"),
Ok(Some(Value::function( Ok(Some(Value::function(
Vec::with_capacity(0), Vec::with_capacity(0),
vec![(Identifier::new("x"), Type::Integer.with_position((13, 16)))], vec![(Identifier::new("x"), Type::Integer.with_position((16, 19)))],
Type::Integer.with_position((18, 21)), Type::Integer.with_position((21, 24)),
Block::new(vec![Statement::Expression(Expression::Identifier( 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))
))) )))
); );
} }

View File

@ -1,9 +1,9 @@
io = { io = {
read_line = () str { read_line = fn () str {
READ_LINE() READ_LINE()
} }
write_line = (output: any) none { write_line = fn (output: any) none {
WRITE_LINE(output) WRITE_LINE(output)
} }
} }

View File

@ -1,5 +1,5 @@
thread = { thread = {
sleep = (milliseconds: int) none { sleep = fn (milliseconds: int) none {
SLEEP(milliseconds) SLEEP(milliseconds)
} }
} }