1
0

Use rust-style turbofish

This commit is contained in:
Jeff 2024-06-24 13:48:31 -04:00
parent 2cbeb4b551
commit 37d54499da
6 changed files with 34 additions and 33 deletions

View File

@ -152,15 +152,15 @@ impl AbstractNode for FunctionCall {
let function_context = Context::new(Some(context.clone()));
if let Some(type_parameters) = function.type_parameters() {
for identifier in type_parameters {
function_context.set_type(
identifier.clone(),
Type::Generic {
identifier: identifier.clone(),
concrete_type: None,
},
)?;
if let (Some(type_parameters), Some(type_arguments)) =
(function.type_parameters(), self.type_arguments)
{
for (identifier, constructor) in
type_parameters.into_iter().zip(type_arguments.into_iter())
{
let r#type = constructor.construct(context)?;
function_context.set_type(identifier.clone(), r#type)?;
}
}

View File

@ -299,10 +299,7 @@ impl InterpreterError {
self.source_id.clone(),
position.1,
)
.with_message("An error occured that forced the program to exit.")
.with_help(
"There may be unexpected side-effects because the program could not finish.",
)
.with_message("An error occured that forced the program to exit. There may be unexpected side-effects because the program could not finish.")
.with_note(note)
.with_label(
Label::new((self.source_id.clone(), position.0..position.1)).with_message("Error occured here.")
@ -359,11 +356,17 @@ impl InterpreterError {
),
ValidationError::RwLockPoison(_) => todo!(),
ValidationError::TypeCheck {
conflict,
conflict: TypeConflict { actual, expected },
actual_position,
expected_position,
} => {
let TypeConflict { actual, expected } = conflict;
if let Type::Generic {
concrete_type: None,
..
} = actual
{
builder = builder.with_help("Try specifying the type using turbofish.");
}
if let Some(position) = expected_position {
builder.add_label(

View File

@ -414,18 +414,16 @@ pub fn parser<'src>(
expression
});
let turbofish = type_constructor
let turbofish = just(Token::Symbol(Symbol::DoubleColon)).ignore_then(
type_constructor
.clone()
.separated_by(just(Token::Symbol(Symbol::Comma)))
.at_least(1)
.collect()
.delimited_by(
just(Token::Symbol(Symbol::ParenOpen)),
just(Token::Symbol(Symbol::ParenClose)),
)
.delimited_by(
just(Token::Symbol(Symbol::DoubleColon)),
just(Token::Symbol(Symbol::DoubleColon)),
just(Token::Symbol(Symbol::Less)),
just(Token::Symbol(Symbol::Greater)),
),
);
let atom = choice((

View File

@ -539,7 +539,7 @@ fn function_call() {
#[test]
fn function_call_with_type_arguments() {
assert_eq!(
parse(&lex("foobar::(str)::('hi')").unwrap()).unwrap()[0],
parse(&lex("foobar::<str>('hi')").unwrap()).unwrap()[0],
Statement::Expression(Expression::FunctionCall(
FunctionCall::new(
Expression::Identifier(Identifier::new("foobar").with_position((0, 6))),
@ -547,10 +547,10 @@ fn function_call_with_type_arguments() {
RawTypeConstructor::String.with_position((9, 12))
)]),
Some(vec![Expression::Value(
ValueNode::String("hi".to_string()).with_position((16, 20))
ValueNode::String("hi".to_string()).with_position((14, 18))
)]),
)
.with_position((0, 21))
.with_position((0, 19))
))
)
}

View File

@ -7,7 +7,7 @@ fn function_call_with_type_argument() {
"test",
"
foobar = fn |T| (x: T) -> T { x }
foobar::(int)::(42)
foobar::<int>(42)
",
),
Ok(Some(Value::integer(42)))

View File

@ -1,5 +1,5 @@
json = {
parse = fn |T| (input: str) -> T {
__JSON_PARSE__::(T)::(input)
__JSON_PARSE__::<T>(input)
}
}