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