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::{
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<Identifier>,
index: Expression,
}
impl MapIndex {
pub fn new(left: Expression, right: WithPosition<Identifier>) -> Self {
pub fn new(left: Expression, right: Expression) -> Self {
Self {
collection: left,
index: right,
@ -24,16 +23,15 @@ impl MapIndex {
impl AbstractNode for MapIndex {
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)
{
let collection =
if let Some(collection) = context.get_value(&collection_identifier.item)? {
let collection = if let Some(collection) = context.get_value(&collection.item)? {
collection
} else {
return Err(ValidationError::VariableNotFound {
identifier: collection_identifier.item.clone(),
position: collection_identifier.position,
identifier: collection.item.clone(),
position: collection.position,
});
};
@ -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);

View File

@ -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},

View File

@ -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;

View File

@ -231,9 +231,9 @@ pub fn parser<'src>(
just(Token::Control(Control::ParenClose)),
);
let parsed_function = type_arguments
.or_not()
.then(
let parsed_function = just(Token::Keyword(Keyword::Fn))
.ignore_then(
type_arguments.or_not().then(
identifier
.clone()
.then(type_specification.clone())
@ -245,6 +245,7 @@ pub fn parser<'src>(
)
.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))
))
)
}

View File

@ -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 {

View File

@ -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))
)))
);
}

View File

@ -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)
}
}

View File

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