mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-20 15:27:45 +03:00
Merge pull request #4567 from joshuawarner32/tuple-type-annotation
Implement tuple type parsing
This commit is contained in:
commit
848c18f996
@ -405,6 +405,9 @@ pub fn to_type2<'a>(
|
||||
|
||||
Type2::Variable(var)
|
||||
}
|
||||
Tuple { fields: _, ext: _ } => {
|
||||
todo!("tuple type");
|
||||
}
|
||||
Record { fields, ext, .. } => {
|
||||
let field_types_map =
|
||||
can_assigned_fields(env, scope, references, &fields.items, region);
|
||||
|
@ -448,6 +448,9 @@ pub fn find_type_def_symbols(
|
||||
As(actual, _, _) => {
|
||||
stack.push(&actual.value);
|
||||
}
|
||||
Tuple { fields: _, ext: _ } => {
|
||||
todo!("find_type_def_symbols: Tuple");
|
||||
}
|
||||
Record { fields, ext } => {
|
||||
let mut inner_stack = Vec::with_capacity(fields.items.len());
|
||||
|
||||
@ -869,6 +872,9 @@ fn can_annotation_help(
|
||||
}
|
||||
}
|
||||
|
||||
Tuple { fields: _, ext: _ } => {
|
||||
todo!("tuple");
|
||||
}
|
||||
Record { fields, ext } => {
|
||||
let ext_type = can_extension_type(
|
||||
env,
|
||||
|
@ -176,6 +176,15 @@ impl<'a> Formattable for TypeAnnotation<'a> {
|
||||
annot.is_multiline() || has_clauses.iter().any(|has| has.is_multiline())
|
||||
}
|
||||
|
||||
Tuple { fields, ext } => {
|
||||
match ext {
|
||||
Some(ann) if ann.value.is_multiline() => return true,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
fields.items.iter().any(|field| field.value.is_multiline())
|
||||
}
|
||||
|
||||
Record { fields, ext } => {
|
||||
match ext {
|
||||
Some(ann) if ann.value.is_multiline() => return true,
|
||||
@ -297,6 +306,14 @@ impl<'a> Formattable for TypeAnnotation<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
Tuple { fields, ext } => {
|
||||
fmt_collection(buf, indent, Braces::Round, *fields, newlines);
|
||||
|
||||
if let Some(loc_ext_ann) = *ext {
|
||||
loc_ext_ann.value.format(buf, indent);
|
||||
}
|
||||
}
|
||||
|
||||
Record { fields, ext } => {
|
||||
fmt_collection(buf, indent, Braces::Curly, *fields, newlines);
|
||||
|
||||
|
@ -787,6 +787,10 @@ impl<'a> RemoveSpaces<'a> for TypeAnnotation<'a> {
|
||||
vars: vars.remove_spaces(arena),
|
||||
},
|
||||
),
|
||||
TypeAnnotation::Tuple { fields, ext } => TypeAnnotation::Tuple {
|
||||
fields: fields.remove_spaces(arena),
|
||||
ext: ext.remove_spaces(arena),
|
||||
},
|
||||
TypeAnnotation::Record { fields, ext } => TypeAnnotation::Record {
|
||||
fields: fields.remove_spaces(arena),
|
||||
ext: ext.remove_spaces(arena),
|
||||
|
@ -533,6 +533,13 @@ pub enum TypeAnnotation<'a> {
|
||||
ext: Option<&'a Loc<TypeAnnotation<'a>>>,
|
||||
},
|
||||
|
||||
Tuple {
|
||||
fields: Collection<'a, Loc<TypeAnnotation<'a>>>,
|
||||
/// The row type variable in an open record, e.g. the `r` in `{ name: Str }r`.
|
||||
/// This is None if it's a closed record annotation like `{ name: Str }`.
|
||||
ext: Option<&'a Loc<TypeAnnotation<'a>>>,
|
||||
},
|
||||
|
||||
/// A tag union, e.g. `[
|
||||
TagUnion {
|
||||
/// The row type variable in an open tag union, e.g. the `a` in `[Foo, Bar]a`.
|
||||
|
@ -674,6 +674,9 @@ pub enum ETypeTagUnion<'a> {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ETypeInParens<'a> {
|
||||
/// e.g. (), which isn't a valid type
|
||||
Empty(Position),
|
||||
|
||||
End(Position),
|
||||
Open(Position),
|
||||
///
|
||||
|
@ -116,7 +116,7 @@ fn term<'a>(stop_at_surface_has: bool) -> impl Parser<'a, Loc<TypeAnnotation<'a>
|
||||
one_of!(
|
||||
loc_wildcard(),
|
||||
loc_inferred(),
|
||||
specialize(EType::TInParens, loc_type_in_parens()),
|
||||
specialize(EType::TInParens, loc_type_in_parens(stop_at_surface_has)),
|
||||
loc!(specialize(EType::TRecord, record_type(stop_at_surface_has))),
|
||||
loc!(specialize(
|
||||
EType::TTagUnion,
|
||||
@ -185,7 +185,7 @@ fn loc_applied_arg<'a>(
|
||||
one_of!(
|
||||
loc_wildcard(),
|
||||
loc_inferred(),
|
||||
specialize(EType::TInParens, loc_type_in_parens()),
|
||||
specialize(EType::TInParens, loc_type_in_parens(stop_at_surface_has)),
|
||||
loc!(specialize(EType::TRecord, record_type(stop_at_surface_has))),
|
||||
loc!(specialize(
|
||||
EType::TTagUnion,
|
||||
@ -206,16 +206,45 @@ fn loc_applied_arg<'a>(
|
||||
)
|
||||
}
|
||||
|
||||
fn loc_type_in_parens<'a>() -> impl Parser<'a, Loc<TypeAnnotation<'a>>, ETypeInParens<'a>> {
|
||||
between!(
|
||||
word1(b'(', ETypeInParens::Open),
|
||||
space0_around_ee(
|
||||
specialize_ref(ETypeInParens::Type, expression(true, false)),
|
||||
ETypeInParens::IndentOpen,
|
||||
ETypeInParens::IndentEnd,
|
||||
),
|
||||
word1(b')', ETypeInParens::IndentEnd)
|
||||
fn loc_type_in_parens<'a>(
|
||||
stop_at_surface_has: bool,
|
||||
) -> impl Parser<'a, Loc<TypeAnnotation<'a>>, ETypeInParens<'a>> {
|
||||
then(
|
||||
loc!(and!(
|
||||
collection_trailing_sep_e!(
|
||||
word1(b'(', ETypeInParens::Open),
|
||||
specialize_ref(ETypeInParens::Type, expression(true, false)),
|
||||
word1(b',', ETypeInParens::End),
|
||||
word1(b')', ETypeInParens::End),
|
||||
ETypeInParens::Open,
|
||||
ETypeInParens::IndentEnd,
|
||||
TypeAnnotation::SpaceBefore
|
||||
),
|
||||
optional(allocated(specialize_ref(
|
||||
ETypeInParens::Type,
|
||||
term(stop_at_surface_has)
|
||||
)))
|
||||
)),
|
||||
|_arena, state, progress, item| {
|
||||
let Loc {
|
||||
region,
|
||||
value: (fields, ext),
|
||||
} = item;
|
||||
if fields.len() > 1 || ext.is_some() {
|
||||
Ok((
|
||||
MadeProgress,
|
||||
Loc::at(region, TypeAnnotation::Tuple { fields, ext }),
|
||||
state,
|
||||
))
|
||||
} else if fields.len() == 1 {
|
||||
Ok((MadeProgress, fields.items[0], state))
|
||||
} else {
|
||||
debug_assert!(fields.is_empty());
|
||||
Err((progress, ETypeInParens::Empty(state.pos())))
|
||||
}
|
||||
},
|
||||
)
|
||||
.trace("type_annotation:type_in_parens")
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@ -322,29 +351,24 @@ fn record_type_field<'a>() -> impl Parser<'a, AssignedField<'a, TypeAnnotation<'
|
||||
fn record_type<'a>(
|
||||
stop_at_surface_has: bool,
|
||||
) -> impl Parser<'a, TypeAnnotation<'a>, ETypeRecord<'a>> {
|
||||
use crate::type_annotation::TypeAnnotation::*;
|
||||
|
||||
(move |arena, state, min_indent| {
|
||||
let (_, fields, state) = collection_trailing_sep_e!(
|
||||
// word1_check_indent!(b'{', TRecord::Open, min_indent, TRecord::IndentOpen),
|
||||
word1(b'{', ETypeRecord::Open),
|
||||
loc!(record_type_field()),
|
||||
word1(b',', ETypeRecord::End),
|
||||
// word1_check_indent!(b'}', TRecord::End, min_indent, TRecord::IndentEnd),
|
||||
word1(b'}', ETypeRecord::End),
|
||||
ETypeRecord::Open,
|
||||
ETypeRecord::IndentEnd,
|
||||
AssignedField::SpaceBefore
|
||||
)
|
||||
.parse(arena, state, min_indent)?;
|
||||
|
||||
let field_term = specialize_ref(ETypeRecord::Type, term(stop_at_surface_has));
|
||||
let (_, ext, state) = optional(allocated(field_term)).parse(arena, state, min_indent)?;
|
||||
|
||||
let result = Record { fields, ext };
|
||||
|
||||
Ok((MadeProgress, result, state))
|
||||
})
|
||||
map!(
|
||||
and!(
|
||||
collection_trailing_sep_e!(
|
||||
word1(b'{', ETypeRecord::Open),
|
||||
loc!(record_type_field()),
|
||||
word1(b',', ETypeRecord::End),
|
||||
word1(b'}', ETypeRecord::End),
|
||||
ETypeRecord::Open,
|
||||
ETypeRecord::IndentEnd,
|
||||
AssignedField::SpaceBefore
|
||||
),
|
||||
optional(allocated(specialize_ref(
|
||||
ETypeRecord::Type,
|
||||
term(stop_at_surface_has)
|
||||
)))
|
||||
),
|
||||
|(fields, ext)| { TypeAnnotation::Record { fields, ext } }
|
||||
)
|
||||
.trace("type_annotation:record_type")
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,4 @@
|
||||
f : (Str)a -> (Str)a
|
||||
f = \x -> x
|
||||
|
||||
f ("Str", 42)
|
@ -0,0 +1,136 @@
|
||||
Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483649),
|
||||
],
|
||||
regions: [
|
||||
@0-32,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
value_defs: [
|
||||
Annotation(
|
||||
@0-1 Identifier(
|
||||
"f",
|
||||
),
|
||||
@4-20 Function(
|
||||
[
|
||||
@4-10 Tuple {
|
||||
fields: [
|
||||
@5-8 Apply(
|
||||
"",
|
||||
"Str",
|
||||
[],
|
||||
),
|
||||
],
|
||||
ext: Some(
|
||||
@9-10 BoundVariable(
|
||||
"a",
|
||||
),
|
||||
),
|
||||
},
|
||||
],
|
||||
@14-20 Tuple {
|
||||
fields: [
|
||||
@15-18 Apply(
|
||||
"",
|
||||
"Str",
|
||||
[],
|
||||
),
|
||||
],
|
||||
ext: Some(
|
||||
@19-20 BoundVariable(
|
||||
"a",
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
AnnotatedBody {
|
||||
ann_pattern: @0-1 Identifier(
|
||||
"f",
|
||||
),
|
||||
ann_type: @4-20 Function(
|
||||
[
|
||||
@4-10 Tuple {
|
||||
fields: [
|
||||
@5-8 Apply(
|
||||
"",
|
||||
"Str",
|
||||
[],
|
||||
),
|
||||
],
|
||||
ext: Some(
|
||||
@9-10 BoundVariable(
|
||||
"a",
|
||||
),
|
||||
),
|
||||
},
|
||||
],
|
||||
@14-20 Tuple {
|
||||
fields: [
|
||||
@15-18 Apply(
|
||||
"",
|
||||
"Str",
|
||||
[],
|
||||
),
|
||||
],
|
||||
ext: Some(
|
||||
@19-20 BoundVariable(
|
||||
"a",
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
comment: None,
|
||||
body_pattern: @21-22 Identifier(
|
||||
"f",
|
||||
),
|
||||
body_expr: @25-32 Closure(
|
||||
[
|
||||
@26-27 Identifier(
|
||||
"x",
|
||||
),
|
||||
],
|
||||
@31-32 Var {
|
||||
module_name: "",
|
||||
ident: "x",
|
||||
},
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
@34-47 SpaceBefore(
|
||||
Apply(
|
||||
@34-35 Var {
|
||||
module_name: "",
|
||||
ident: "f",
|
||||
},
|
||||
[
|
||||
@36-47 Tuple(
|
||||
[
|
||||
@37-42 Str(
|
||||
PlainLine(
|
||||
"Str",
|
||||
),
|
||||
),
|
||||
@44-46 Num(
|
||||
"42",
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
Space,
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
)
|
@ -0,0 +1,4 @@
|
||||
f : (Str)a -> (Str)a
|
||||
f = \x -> x
|
||||
|
||||
f ("Str", 42)
|
@ -0,0 +1,4 @@
|
||||
f : I64 -> (I64, I64)
|
||||
f = \x -> (x, x + 1)
|
||||
|
||||
f 42
|
@ -0,0 +1,129 @@
|
||||
Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483649),
|
||||
],
|
||||
regions: [
|
||||
@0-42,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
value_defs: [
|
||||
Annotation(
|
||||
@0-1 Identifier(
|
||||
"f",
|
||||
),
|
||||
@4-21 Function(
|
||||
[
|
||||
@4-7 Apply(
|
||||
"",
|
||||
"I64",
|
||||
[],
|
||||
),
|
||||
],
|
||||
@11-21 Tuple {
|
||||
fields: [
|
||||
@12-15 Apply(
|
||||
"",
|
||||
"I64",
|
||||
[],
|
||||
),
|
||||
@17-20 Apply(
|
||||
"",
|
||||
"I64",
|
||||
[],
|
||||
),
|
||||
],
|
||||
ext: None,
|
||||
},
|
||||
),
|
||||
),
|
||||
AnnotatedBody {
|
||||
ann_pattern: @0-1 Identifier(
|
||||
"f",
|
||||
),
|
||||
ann_type: @4-21 Function(
|
||||
[
|
||||
@4-7 Apply(
|
||||
"",
|
||||
"I64",
|
||||
[],
|
||||
),
|
||||
],
|
||||
@11-21 Tuple {
|
||||
fields: [
|
||||
@12-15 Apply(
|
||||
"",
|
||||
"I64",
|
||||
[],
|
||||
),
|
||||
@17-20 Apply(
|
||||
"",
|
||||
"I64",
|
||||
[],
|
||||
),
|
||||
],
|
||||
ext: None,
|
||||
},
|
||||
),
|
||||
comment: None,
|
||||
body_pattern: @22-23 Identifier(
|
||||
"f",
|
||||
),
|
||||
body_expr: @26-42 Closure(
|
||||
[
|
||||
@27-28 Identifier(
|
||||
"x",
|
||||
),
|
||||
],
|
||||
@32-42 Tuple(
|
||||
[
|
||||
@33-34 Var {
|
||||
module_name: "",
|
||||
ident: "x",
|
||||
},
|
||||
@36-41 BinOps(
|
||||
[
|
||||
(
|
||||
@36-37 Var {
|
||||
module_name: "",
|
||||
ident: "x",
|
||||
},
|
||||
@38-39 Plus,
|
||||
),
|
||||
],
|
||||
@40-41 Num(
|
||||
"1",
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
@44-48 SpaceBefore(
|
||||
Apply(
|
||||
@44-45 Var {
|
||||
module_name: "",
|
||||
ident: "f",
|
||||
},
|
||||
[
|
||||
@46-48 Num(
|
||||
"42",
|
||||
),
|
||||
],
|
||||
Space,
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
)
|
@ -0,0 +1,4 @@
|
||||
f : I64 -> (I64, I64)
|
||||
f = \x -> (x, x + 1)
|
||||
|
||||
f 42
|
@ -0,0 +1,4 @@
|
||||
f : (Str, Str) -> (Str, Str)
|
||||
f = \x -> x
|
||||
|
||||
f (1, 2)
|
@ -0,0 +1,138 @@
|
||||
Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483649),
|
||||
],
|
||||
regions: [
|
||||
@0-39,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
value_defs: [
|
||||
Annotation(
|
||||
@0-1 Identifier(
|
||||
"f",
|
||||
),
|
||||
@3-27 Function(
|
||||
[
|
||||
@3-13 Tuple {
|
||||
fields: [
|
||||
@4-7 Apply(
|
||||
"",
|
||||
"Str",
|
||||
[],
|
||||
),
|
||||
@9-12 Apply(
|
||||
"",
|
||||
"Str",
|
||||
[],
|
||||
),
|
||||
],
|
||||
ext: None,
|
||||
},
|
||||
],
|
||||
@17-27 Tuple {
|
||||
fields: [
|
||||
@18-21 Apply(
|
||||
"",
|
||||
"Str",
|
||||
[],
|
||||
),
|
||||
@23-26 Apply(
|
||||
"",
|
||||
"Str",
|
||||
[],
|
||||
),
|
||||
],
|
||||
ext: None,
|
||||
},
|
||||
),
|
||||
),
|
||||
AnnotatedBody {
|
||||
ann_pattern: @0-1 Identifier(
|
||||
"f",
|
||||
),
|
||||
ann_type: @3-27 Function(
|
||||
[
|
||||
@3-13 Tuple {
|
||||
fields: [
|
||||
@4-7 Apply(
|
||||
"",
|
||||
"Str",
|
||||
[],
|
||||
),
|
||||
@9-12 Apply(
|
||||
"",
|
||||
"Str",
|
||||
[],
|
||||
),
|
||||
],
|
||||
ext: None,
|
||||
},
|
||||
],
|
||||
@17-27 Tuple {
|
||||
fields: [
|
||||
@18-21 Apply(
|
||||
"",
|
||||
"Str",
|
||||
[],
|
||||
),
|
||||
@23-26 Apply(
|
||||
"",
|
||||
"Str",
|
||||
[],
|
||||
),
|
||||
],
|
||||
ext: None,
|
||||
},
|
||||
),
|
||||
comment: None,
|
||||
body_pattern: @28-29 Identifier(
|
||||
"f",
|
||||
),
|
||||
body_expr: @32-39 Closure(
|
||||
[
|
||||
@33-34 Identifier(
|
||||
"x",
|
||||
),
|
||||
],
|
||||
@38-39 Var {
|
||||
module_name: "",
|
||||
ident: "x",
|
||||
},
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
@41-49 SpaceBefore(
|
||||
Apply(
|
||||
@41-42 Var {
|
||||
module_name: "",
|
||||
ident: "f",
|
||||
},
|
||||
[
|
||||
@43-49 Tuple(
|
||||
[
|
||||
@44-45 Num(
|
||||
"1",
|
||||
),
|
||||
@47-48 Num(
|
||||
"2",
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
Space,
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
)
|
@ -0,0 +1,4 @@
|
||||
f: (Str, Str) -> (Str, Str)
|
||||
f = \x -> x
|
||||
|
||||
f (1, 2)
|
@ -0,0 +1,4 @@
|
||||
f : (Str, Str)a -> (Str, Str)a
|
||||
f = \x -> x
|
||||
|
||||
f (1, 2)
|
@ -0,0 +1,154 @@
|
||||
Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483649),
|
||||
],
|
||||
regions: [
|
||||
@0-41,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
value_defs: [
|
||||
Annotation(
|
||||
@0-1 Identifier(
|
||||
"f",
|
||||
),
|
||||
@3-29 Function(
|
||||
[
|
||||
@3-14 Tuple {
|
||||
fields: [
|
||||
@4-7 Apply(
|
||||
"",
|
||||
"Str",
|
||||
[],
|
||||
),
|
||||
@9-12 Apply(
|
||||
"",
|
||||
"Str",
|
||||
[],
|
||||
),
|
||||
],
|
||||
ext: Some(
|
||||
@13-14 BoundVariable(
|
||||
"a",
|
||||
),
|
||||
),
|
||||
},
|
||||
],
|
||||
@18-29 Tuple {
|
||||
fields: [
|
||||
@19-22 Apply(
|
||||
"",
|
||||
"Str",
|
||||
[],
|
||||
),
|
||||
@24-27 Apply(
|
||||
"",
|
||||
"Str",
|
||||
[],
|
||||
),
|
||||
],
|
||||
ext: Some(
|
||||
@28-29 BoundVariable(
|
||||
"a",
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
AnnotatedBody {
|
||||
ann_pattern: @0-1 Identifier(
|
||||
"f",
|
||||
),
|
||||
ann_type: @3-29 Function(
|
||||
[
|
||||
@3-14 Tuple {
|
||||
fields: [
|
||||
@4-7 Apply(
|
||||
"",
|
||||
"Str",
|
||||
[],
|
||||
),
|
||||
@9-12 Apply(
|
||||
"",
|
||||
"Str",
|
||||
[],
|
||||
),
|
||||
],
|
||||
ext: Some(
|
||||
@13-14 BoundVariable(
|
||||
"a",
|
||||
),
|
||||
),
|
||||
},
|
||||
],
|
||||
@18-29 Tuple {
|
||||
fields: [
|
||||
@19-22 Apply(
|
||||
"",
|
||||
"Str",
|
||||
[],
|
||||
),
|
||||
@24-27 Apply(
|
||||
"",
|
||||
"Str",
|
||||
[],
|
||||
),
|
||||
],
|
||||
ext: Some(
|
||||
@28-29 BoundVariable(
|
||||
"a",
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
comment: None,
|
||||
body_pattern: @30-31 Identifier(
|
||||
"f",
|
||||
),
|
||||
body_expr: @34-41 Closure(
|
||||
[
|
||||
@35-36 Identifier(
|
||||
"x",
|
||||
),
|
||||
],
|
||||
@40-41 Var {
|
||||
module_name: "",
|
||||
ident: "x",
|
||||
},
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
@43-51 SpaceBefore(
|
||||
Apply(
|
||||
@43-44 Var {
|
||||
module_name: "",
|
||||
ident: "f",
|
||||
},
|
||||
[
|
||||
@45-51 Tuple(
|
||||
[
|
||||
@46-47 Num(
|
||||
"1",
|
||||
),
|
||||
@49-50 Num(
|
||||
"2",
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
Space,
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
)
|
@ -0,0 +1,4 @@
|
||||
f: (Str, Str)a -> (Str, Str)a
|
||||
f = \x -> x
|
||||
|
||||
f (1, 2)
|
@ -187,6 +187,8 @@ mod test_parse {
|
||||
pass/list_patterns.expr,
|
||||
pass/lowest_float.expr,
|
||||
pass/lowest_int.expr,
|
||||
pass/tuple_type.expr,
|
||||
pass/tuple_type_ext.expr,
|
||||
pass/malformed_ident_due_to_underscore.expr,
|
||||
pass/malformed_pattern_field_access.expr, // See https://github.com/roc-lang/roc/issues/399
|
||||
pass/malformed_pattern_module_name.expr, // See https://github.com/roc-lang/roc/issues/399
|
||||
@ -303,6 +305,8 @@ mod test_parse {
|
||||
pass/when_with_negative_numbers.expr,
|
||||
pass/when_with_numbers.expr,
|
||||
pass/when_with_records.expr,
|
||||
pass/function_with_tuple_type.expr,
|
||||
pass/function_with_tuple_ext_type.expr,
|
||||
pass/where_clause_function.expr,
|
||||
pass/where_clause_multiple_bound_abilities.expr,
|
||||
pass/where_clause_multiple_has_across_newlines.expr,
|
||||
|
@ -2907,6 +2907,27 @@ fn to_tinparens_report<'a>(
|
||||
}
|
||||
}
|
||||
|
||||
ETypeInParens::Empty(pos) => {
|
||||
let surroundings = Region::new(start, pos);
|
||||
let region = LineColumnRegion::from_pos(lines.convert_pos(pos));
|
||||
|
||||
let doc = alloc.stack([
|
||||
alloc.reflow("I am partway through parsing a parenthesized type:"),
|
||||
alloc.region_with_subregion(lines.convert_region(surroundings), region),
|
||||
alloc.concat([
|
||||
alloc.reflow(r"I was expecting to see an expression next."),
|
||||
alloc.reflow(r"Note, Roc doesn't use '()' as a null type."),
|
||||
]),
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename,
|
||||
doc,
|
||||
title: "EMPTY PARENTHESES".to_string(),
|
||||
severity: Severity::RuntimeError,
|
||||
}
|
||||
}
|
||||
|
||||
ETypeInParens::End(pos) => {
|
||||
let surroundings = Region::new(start, pos);
|
||||
let region = LineColumnRegion::from_pos(lines.convert_pos(pos));
|
||||
|
@ -4410,13 +4410,14 @@ mod test_reporting {
|
||||
@r###"
|
||||
── UNFINISHED PARENTHESES ────────────────── tmp/type_in_parens_start/Test.roc ─
|
||||
|
||||
I just started parsing a type in parentheses, but I got stuck here:
|
||||
I am partway through parsing a type in parentheses, but I got stuck
|
||||
here:
|
||||
|
||||
4│ f : (
|
||||
^
|
||||
|
||||
Tag unions look like [Many I64, None], so I was expecting to see a tag
|
||||
name next.
|
||||
I was expecting to see a parenthesis before this, so try adding a )
|
||||
and see if that helps?
|
||||
|
||||
Note: I may be confused by indentation
|
||||
"###
|
||||
@ -4436,12 +4437,12 @@ mod test_reporting {
|
||||
here:
|
||||
|
||||
4│ f : ( I64
|
||||
^
|
||||
5│
|
||||
6│
|
||||
^
|
||||
|
||||
I was expecting to see a parenthesis before this, so try adding a )
|
||||
and see if that helps?
|
||||
|
||||
Note: I may be confused by indentation
|
||||
I was expecting to see a closing parenthesis before this, so try
|
||||
adding a ) and see if that helps?
|
||||
"###
|
||||
);
|
||||
|
||||
@ -6049,33 +6050,6 @@ All branches in an `if` must have the same type!
|
||||
"###
|
||||
);
|
||||
|
||||
test_report!(
|
||||
outdented_in_parens,
|
||||
indoc!(
|
||||
r#"
|
||||
Box : (
|
||||
Str
|
||||
)
|
||||
|
||||
4
|
||||
"#
|
||||
),
|
||||
@r###"
|
||||
── NEED MORE INDENTATION ──────────────────── tmp/outdented_in_parens/Test.roc ─
|
||||
|
||||
I am partway through parsing a type in parentheses, but I got stuck
|
||||
here:
|
||||
|
||||
4│ Box : (
|
||||
5│ Str
|
||||
6│ )
|
||||
^
|
||||
|
||||
I need this parenthesis to be indented more. Try adding more spaces
|
||||
before it!
|
||||
"###
|
||||
);
|
||||
|
||||
test_report!(
|
||||
backpassing_type_error,
|
||||
indoc!(
|
||||
|
Loading…
Reference in New Issue
Block a user