mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 12:18:19 +00:00
Parse effectful arrow in function annotations
This commit is contained in:
parent
1a5776653c
commit
ef4eeb5c1a
30 changed files with 178 additions and 19 deletions
|
@ -448,7 +448,7 @@ pub fn find_type_def_symbols(
|
|||
stack.push(&t.value);
|
||||
}
|
||||
}
|
||||
Function(arguments, result) => {
|
||||
Function(arguments, _arrow, result) => {
|
||||
for t in arguments.iter() {
|
||||
stack.push(&t.value);
|
||||
}
|
||||
|
@ -554,7 +554,8 @@ fn can_annotation_help(
|
|||
use roc_parse::ast::TypeAnnotation::*;
|
||||
|
||||
match annotation {
|
||||
Function(argument_types, return_type) => {
|
||||
Function(argument_types, _arrow, return_type) => {
|
||||
// [purity-inference] TODO: arrow
|
||||
let mut args = Vec::new();
|
||||
|
||||
for arg in *argument_types {
|
||||
|
|
|
@ -149,7 +149,7 @@ impl<'a> Formattable for TypeAnnotation<'a> {
|
|||
}
|
||||
|
||||
Wildcard | Inferred | BoundVariable(_) | Malformed(_) => false,
|
||||
Function(args, result) => {
|
||||
Function(args, _arrow, result) => {
|
||||
result.value.is_multiline()
|
||||
|| args.iter().any(|loc_arg| loc_arg.value.is_multiline())
|
||||
}
|
||||
|
@ -195,7 +195,8 @@ impl<'a> Formattable for TypeAnnotation<'a> {
|
|||
let self_is_multiline = self.is_multiline();
|
||||
|
||||
match self {
|
||||
Function(args, ret) => {
|
||||
Function(args, _arrow, ret) => {
|
||||
// [purity-infrence] TODO: format arrow
|
||||
let needs_parens = parens != Parens::NotNeeded;
|
||||
|
||||
buf.indent(indent);
|
||||
|
|
|
@ -443,7 +443,8 @@ fn contains_unexposed_type(
|
|||
|
||||
Malformed(_) | Inferred | Wildcard | BoundVariable(_) => false,
|
||||
|
||||
Function(loc_args, loc_ret) => {
|
||||
Function(loc_args, _arrow, loc_ret) => {
|
||||
// [purity-inference] TODO: arrow
|
||||
let loc_args_contains_unexposed_type = loc_args.iter().any(|loc_arg| {
|
||||
contains_unexposed_type(&loc_arg.value, exposed_module_ids, module_ids)
|
||||
});
|
||||
|
@ -611,7 +612,8 @@ fn type_to_docs(in_func_type_ann: bool, type_annotation: ast::TypeAnnotation) ->
|
|||
ast::TypeAnnotation::SpaceAfter(&sub_type_ann, _) => {
|
||||
type_to_docs(in_func_type_ann, sub_type_ann)
|
||||
}
|
||||
ast::TypeAnnotation::Function(ast_arg_anns, output_ann) => {
|
||||
ast::TypeAnnotation::Function(ast_arg_anns, _arrow, output_ann) => {
|
||||
// [purity-inference] TODO: arrow
|
||||
let mut doc_arg_anns = Vec::new();
|
||||
|
||||
for ast_arg_ann in ast_arg_anns {
|
||||
|
|
|
@ -1530,10 +1530,22 @@ impl ImplementsAbilities<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub enum FunctionArrow {
|
||||
/// ->
|
||||
Pure,
|
||||
/// =>
|
||||
Effectful,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub enum TypeAnnotation<'a> {
|
||||
/// A function. The types of its arguments, then the type of its return value.
|
||||
Function(&'a [Loc<TypeAnnotation<'a>>], &'a Loc<TypeAnnotation<'a>>),
|
||||
/// A function. The types of its arguments, the type of arrow used, then the type of its return value.
|
||||
Function(
|
||||
&'a [Loc<TypeAnnotation<'a>>],
|
||||
FunctionArrow,
|
||||
&'a Loc<TypeAnnotation<'a>>,
|
||||
),
|
||||
|
||||
/// Applying a type to some arguments (e.g. Map.Map String Int)
|
||||
Apply(&'a str, &'a str, &'a [Loc<TypeAnnotation<'a>>]),
|
||||
|
@ -2755,7 +2767,7 @@ impl<'a> Malformed for ModuleImportParams<'a> {
|
|||
impl<'a> Malformed for TypeAnnotation<'a> {
|
||||
fn is_malformed(&self) -> bool {
|
||||
match self {
|
||||
TypeAnnotation::Function(args, ret) => {
|
||||
TypeAnnotation::Function(args, _arrow, ret) => {
|
||||
args.iter().any(|arg| arg.is_malformed()) || ret.is_malformed()
|
||||
}
|
||||
TypeAnnotation::Apply(_, _, args) => args.iter().any(|arg| arg.is_malformed()),
|
||||
|
|
|
@ -881,8 +881,9 @@ impl<'a> Normalize<'a> for Pattern<'a> {
|
|||
impl<'a> Normalize<'a> for TypeAnnotation<'a> {
|
||||
fn normalize(&self, arena: &'a Bump) -> Self {
|
||||
match *self {
|
||||
TypeAnnotation::Function(a, b) => TypeAnnotation::Function(
|
||||
TypeAnnotation::Function(a, arrow, b) => TypeAnnotation::Function(
|
||||
arena.alloc(a.normalize(arena)),
|
||||
arrow,
|
||||
arena.alloc(b.normalize(arena)),
|
||||
),
|
||||
TypeAnnotation::Apply(a, b, c) => TypeAnnotation::Apply(a, b, c.normalize(arena)),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::ast::{
|
||||
AbilityImpls, AssignedField, CommentOrNewline, Expr, ImplementsAbilities, ImplementsAbility,
|
||||
ImplementsClause, Pattern, Spaceable, Spaced, Tag, TypeAnnotation, TypeHeader,
|
||||
AbilityImpls, AssignedField, CommentOrNewline, Expr, FunctionArrow, ImplementsAbilities,
|
||||
ImplementsAbility, ImplementsClause, Pattern, Spaceable, Spaced, Tag, TypeAnnotation,
|
||||
TypeHeader,
|
||||
};
|
||||
use crate::blankspace::{
|
||||
space0_around_ee, space0_before_e, space0_before_optional_after, space0_e,
|
||||
|
@ -594,16 +595,23 @@ fn expression<'a>(
|
|||
],
|
||||
))
|
||||
.trace("type_annotation:expression:rest_args"),
|
||||
skip_second(
|
||||
and(
|
||||
space0_e(EType::TIndentStart),
|
||||
two_bytes(b'-', b'>', EType::TStart),
|
||||
one_of![
|
||||
map(two_bytes(b'-', b'>', EType::TStart), |_| {
|
||||
FunctionArrow::Pure
|
||||
}),
|
||||
map(two_bytes(b'=', b'>', EType::TStart), |_| {
|
||||
FunctionArrow::Effectful
|
||||
}),
|
||||
],
|
||||
)
|
||||
.trace("type_annotation:expression:arrow"),
|
||||
)
|
||||
.parse(arena, state.clone(), min_indent);
|
||||
|
||||
let (progress, annot, state) = match result {
|
||||
Ok((p2, (rest, space_before_arrow), state)) => {
|
||||
Ok((p2, (rest, (space_before_arrow, arrow)), state)) => {
|
||||
let (p3, return_type, state) =
|
||||
space0_before_e(term(stop_at_surface_has), EType::TIndentStart)
|
||||
.parse(arena, state, min_indent)?;
|
||||
|
@ -626,7 +634,7 @@ fn expression<'a>(
|
|||
|
||||
let result = Loc {
|
||||
region,
|
||||
value: TypeAnnotation::Function(output, arena.alloc(return_type)),
|
||||
value: TypeAnnotation::Function(output, arrow, arena.alloc(return_type)),
|
||||
};
|
||||
let progress = p1.or(p2).or(p3);
|
||||
(progress, result, state)
|
||||
|
|
|
@ -40,6 +40,7 @@ SpaceAfter(
|
|||
],
|
||||
),
|
||||
],
|
||||
Pure,
|
||||
@40-43 Apply(
|
||||
"",
|
||||
"U64",
|
||||
|
|
|
@ -35,6 +35,7 @@ SpaceAfter(
|
|||
"a",
|
||||
),
|
||||
],
|
||||
Pure,
|
||||
@30-33 Apply(
|
||||
"",
|
||||
"U64",
|
||||
|
@ -55,6 +56,7 @@ SpaceAfter(
|
|||
"a",
|
||||
),
|
||||
],
|
||||
Pure,
|
||||
@49-52 Apply(
|
||||
"",
|
||||
"U64",
|
||||
|
|
|
@ -31,6 +31,7 @@ SpaceAfter(
|
|||
"a",
|
||||
),
|
||||
],
|
||||
Pure,
|
||||
@28-31 Apply(
|
||||
"",
|
||||
"U64",
|
||||
|
|
|
@ -38,6 +38,7 @@ SpaceAfter(
|
|||
"a",
|
||||
),
|
||||
],
|
||||
Pure,
|
||||
@26-28 Record {
|
||||
fields: [],
|
||||
ext: None,
|
||||
|
@ -75,6 +76,7 @@ SpaceAfter(
|
|||
"a",
|
||||
),
|
||||
],
|
||||
Pure,
|
||||
@79-81 Record {
|
||||
fields: [],
|
||||
ext: None,
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
launchTheNukes : {} -> Result Bool LaunchNukeErr
|
||||
launchTheNukes = \{} ->
|
||||
crash "todo"
|
||||
|
||||
launchTheNukes
|
|
@ -0,0 +1,94 @@
|
|||
SpaceAfter(
|
||||
Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-89,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
value_defs: [
|
||||
AnnotatedBody {
|
||||
ann_pattern: @0-14 Identifier {
|
||||
ident: "launchTheNukes",
|
||||
},
|
||||
ann_type: @17-48 Function(
|
||||
[
|
||||
@17-19 Record {
|
||||
fields: [],
|
||||
ext: None,
|
||||
},
|
||||
],
|
||||
Effectful,
|
||||
@23-48 Apply(
|
||||
"",
|
||||
"Result",
|
||||
[
|
||||
@30-34 Apply(
|
||||
"",
|
||||
"Bool",
|
||||
[],
|
||||
),
|
||||
@35-48 Apply(
|
||||
"",
|
||||
"LaunchNukeErr",
|
||||
[],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
lines_between: [
|
||||
Newline,
|
||||
],
|
||||
body_pattern: @49-63 Identifier {
|
||||
ident: "launchTheNukes",
|
||||
},
|
||||
body_expr: @66-89 Closure(
|
||||
[
|
||||
@67-69 RecordDestructure(
|
||||
[],
|
||||
),
|
||||
],
|
||||
@77-89 SpaceBefore(
|
||||
Apply(
|
||||
@77-82 Crash,
|
||||
[
|
||||
@83-89 Str(
|
||||
PlainLine(
|
||||
"todo",
|
||||
),
|
||||
),
|
||||
],
|
||||
Space,
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
@91-105 SpaceBefore(
|
||||
Var {
|
||||
module_name: "",
|
||||
ident: "launchTheNukes",
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
)
|
|
@ -0,0 +1,5 @@
|
|||
launchTheNukes : {} => Result Bool LaunchNukeErr
|
||||
launchTheNukes = \{} ->
|
||||
crash "todo"
|
||||
|
||||
launchTheNukes
|
|
@ -46,6 +46,7 @@ Defs(
|
|||
ext: None,
|
||||
},
|
||||
],
|
||||
Pure,
|
||||
@39-44 Apply(
|
||||
"",
|
||||
"Table",
|
||||
|
|
|
@ -37,6 +37,7 @@ SpaceAfter(
|
|||
),
|
||||
},
|
||||
],
|
||||
Pure,
|
||||
@14-20 Tuple {
|
||||
elems: [
|
||||
@15-18 Apply(
|
||||
|
|
|
@ -28,6 +28,7 @@ SpaceAfter(
|
|||
[],
|
||||
),
|
||||
],
|
||||
Pure,
|
||||
@11-21 Tuple {
|
||||
elems: [
|
||||
@12-15 Apply(
|
||||
|
|
|
@ -51,6 +51,7 @@ Defs {
|
|||
"a",
|
||||
),
|
||||
],
|
||||
Pure,
|
||||
@34-38 Apply(
|
||||
"",
|
||||
"Bool",
|
||||
|
|
|
@ -55,6 +55,7 @@ SpaceAfter(
|
|||
[],
|
||||
),
|
||||
],
|
||||
Pure,
|
||||
@65-75 Apply(
|
||||
"",
|
||||
"Effect",
|
||||
|
|
|
@ -32,6 +32,7 @@ SpaceAfter(
|
|||
ext: None,
|
||||
},
|
||||
],
|
||||
Pure,
|
||||
@19-24 Apply(
|
||||
"",
|
||||
"Model",
|
||||
|
@ -55,6 +56,7 @@ SpaceAfter(
|
|||
[],
|
||||
),
|
||||
],
|
||||
Pure,
|
||||
@49-54 Apply(
|
||||
"",
|
||||
"Model",
|
||||
|
@ -73,6 +75,7 @@ SpaceAfter(
|
|||
[],
|
||||
),
|
||||
],
|
||||
Pure,
|
||||
@72-75 Apply(
|
||||
"",
|
||||
"Str",
|
||||
|
|
|
@ -37,6 +37,7 @@ Defs(
|
|||
ext: None,
|
||||
},
|
||||
],
|
||||
Pure,
|
||||
@17-27 Tuple {
|
||||
elems: [
|
||||
@18-21 Apply(
|
||||
|
|
|
@ -41,6 +41,7 @@ Defs(
|
|||
),
|
||||
},
|
||||
],
|
||||
Pure,
|
||||
@18-29 Tuple {
|
||||
elems: [
|
||||
@19-22 Apply(
|
||||
|
|
|
@ -27,6 +27,7 @@ Defs(
|
|||
[],
|
||||
),
|
||||
],
|
||||
Pure,
|
||||
@20-30 Apply(
|
||||
"",
|
||||
"Task",
|
||||
|
|
|
@ -32,6 +32,7 @@ Defs(
|
|||
[],
|
||||
),
|
||||
],
|
||||
Pure,
|
||||
@20-24 Apply(
|
||||
"",
|
||||
"Bool",
|
||||
|
|
|
@ -27,12 +27,14 @@ SpaceAfter(
|
|||
"a",
|
||||
),
|
||||
],
|
||||
Pure,
|
||||
@10-16 Function(
|
||||
[
|
||||
@10-11 BoundVariable(
|
||||
"b",
|
||||
),
|
||||
],
|
||||
Pure,
|
||||
@15-16 BoundVariable(
|
||||
"c",
|
||||
),
|
||||
|
|
|
@ -34,6 +34,7 @@ SpaceAfter(
|
|||
"a",
|
||||
),
|
||||
],
|
||||
Pure,
|
||||
@9-10 BoundVariable(
|
||||
"b",
|
||||
),
|
||||
|
@ -89,6 +90,7 @@ SpaceAfter(
|
|||
"a",
|
||||
),
|
||||
],
|
||||
Pure,
|
||||
@84-85 BoundVariable(
|
||||
"b",
|
||||
),
|
||||
|
|
|
@ -27,12 +27,14 @@ SpaceAfter(
|
|||
"a",
|
||||
),
|
||||
],
|
||||
Pure,
|
||||
@10-16 Function(
|
||||
[
|
||||
@10-11 BoundVariable(
|
||||
"b",
|
||||
),
|
||||
],
|
||||
Pure,
|
||||
@15-16 BoundVariable(
|
||||
"c",
|
||||
),
|
||||
|
|
|
@ -28,12 +28,14 @@ SpaceAfter(
|
|||
"a",
|
||||
),
|
||||
],
|
||||
Pure,
|
||||
@10-16 Function(
|
||||
[
|
||||
@10-11 BoundVariable(
|
||||
"b",
|
||||
),
|
||||
],
|
||||
Pure,
|
||||
@15-16 BoundVariable(
|
||||
"c",
|
||||
),
|
||||
|
|
|
@ -28,6 +28,7 @@ SpaceAfter(
|
|||
"a",
|
||||
),
|
||||
],
|
||||
Pure,
|
||||
@9-12 Apply(
|
||||
"",
|
||||
"U64",
|
||||
|
|
|
@ -275,6 +275,7 @@ mod test_snapshots {
|
|||
pass/add_var_with_spaces.expr,
|
||||
pass/add_with_spaces.expr,
|
||||
pass/ann_closed_union.expr,
|
||||
pass/ann_effectful_fn.expr,
|
||||
pass/ann_open_union.expr,
|
||||
pass/annotated_record_destructure.expr,
|
||||
pass/annotated_tag_destructure.expr,
|
||||
|
|
|
@ -386,9 +386,11 @@ impl IterTokens for PlatformRequires<'_> {
|
|||
impl IterTokens for Loc<TypeAnnotation<'_>> {
|
||||
fn iter_tokens<'a>(&self, arena: &'a Bump) -> BumpVec<'a, Loc<Token>> {
|
||||
match self.value {
|
||||
TypeAnnotation::Function(params, ret) => (params.iter_tokens(arena).into_iter())
|
||||
.chain(ret.iter_tokens(arena))
|
||||
.collect_in(arena),
|
||||
TypeAnnotation::Function(params, _arrow, ret) => {
|
||||
(params.iter_tokens(arena).into_iter())
|
||||
.chain(ret.iter_tokens(arena))
|
||||
.collect_in(arena)
|
||||
}
|
||||
TypeAnnotation::Apply(_mod, _type, args) => args.iter_tokens(arena),
|
||||
TypeAnnotation::BoundVariable(_) => onetoken(Token::Type, self.region, arena),
|
||||
TypeAnnotation::As(ty, _, as_ty) => (ty.iter_tokens(arena).into_iter())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue