Revert to pratt parsing for all indexes
This commit is contained in:
parent
42f48e8d76
commit
9eb047a913
@ -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,18 +23,17 @@ 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)? {
|
||||
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);
|
||||
|
||||
|
@ -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},
|
||||
|
@ -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;
|
||||
|
@ -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))
|
||||
))
|
||||
)
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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))
|
||||
)))
|
||||
);
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
thread = {
|
||||
sleep = (milliseconds: int) none {
|
||||
sleep = fn (milliseconds: int) none {
|
||||
SLEEP(milliseconds)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user