mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 22:09:09 +00:00
Parse "as" aliases into tag/args rather than arbitrary annotations
This commit is contained in:
parent
4ddb8e10fb
commit
2cd5bf8c03
8 changed files with 276 additions and 253 deletions
|
@ -280,7 +280,7 @@ pub enum TypeAnnotation<'a> {
|
|||
As(
|
||||
&'a Loc<TypeAnnotation<'a>>,
|
||||
&'a [CommentOrNewline<'a>],
|
||||
&'a Loc<TypeAnnotation<'a>>,
|
||||
(&'a str, &'a [Loc<&'a str>]),
|
||||
),
|
||||
|
||||
Record {
|
||||
|
|
|
@ -482,6 +482,7 @@ pub enum EType<'a> {
|
|||
TTagUnion(ETypeTagUnion<'a>, Position),
|
||||
TInParens(ETypeInParens<'a>, Position),
|
||||
TApply(ETypeApply, Position),
|
||||
TInlineAlias(ETypeInlineAlias, Position),
|
||||
TBadTypeVariable(Position),
|
||||
TWildcard(Position),
|
||||
TInferred(Position),
|
||||
|
@ -553,6 +554,13 @@ pub enum ETypeApply {
|
|||
StartIsNumber(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ETypeInlineAlias {
|
||||
NotAnAlias(Position),
|
||||
Qualified(Position),
|
||||
ArgumentNotLowercase(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ParseProblem<'a, T> {
|
||||
pub pos: Position,
|
||||
|
|
|
@ -3,13 +3,13 @@ use crate::blankspace::{space0_around_ee, space0_before_e, space0_e};
|
|||
use crate::keyword;
|
||||
use crate::parser::{
|
||||
allocated, backtrackable, optional, specialize, specialize_ref, word1, word2, EType,
|
||||
ETypeApply, ETypeInParens, ETypeRecord, ETypeTagUnion, ParseResult, Parser,
|
||||
ETypeApply, ETypeInParens, ETypeInlineAlias, ETypeRecord, ETypeTagUnion, ParseResult, Parser,
|
||||
Progress::{self, *},
|
||||
};
|
||||
use crate::state::State;
|
||||
use bumpalo::collections::vec::Vec;
|
||||
use bumpalo::Bump;
|
||||
use roc_region::all::{Loc, Position, Region};
|
||||
use roc_region::all::{Loc, Position};
|
||||
|
||||
pub fn located_help<'a>(
|
||||
min_indent: u16,
|
||||
|
@ -47,6 +47,56 @@ fn tag_union_type<'a>(min_indent: u16) -> impl Parser<'a, TypeAnnotation<'a>, ET
|
|||
}
|
||||
}
|
||||
|
||||
fn check_type_alias<'a>(
|
||||
p: Progress,
|
||||
annot: Loc<TypeAnnotation<'a>>,
|
||||
) -> impl Parser<'a, Loc<(&'a str, &'a [Loc<&'a str>])>, ETypeInlineAlias> {
|
||||
move |arena, state| match annot.value {
|
||||
TypeAnnotation::Apply("", tag_name, args) => {
|
||||
let mut arg_names = Vec::new_in(arena);
|
||||
arg_names.reserve(args.len());
|
||||
for arg in args {
|
||||
if let TypeAnnotation::BoundVariable(v) = arg.value {
|
||||
arg_names.push(Loc::at(arg.region, v));
|
||||
} else {
|
||||
return Err((
|
||||
p,
|
||||
ETypeInlineAlias::ArgumentNotLowercase(arg.region.start()),
|
||||
state,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Ok((
|
||||
p,
|
||||
Loc::at(annot.region, (tag_name, arg_names.into_bump_slice())),
|
||||
state,
|
||||
))
|
||||
}
|
||||
TypeAnnotation::Apply(_, _, _) => {
|
||||
Err((p, ETypeInlineAlias::Qualified(annot.region.start()), state))
|
||||
}
|
||||
_ => Err((p, ETypeInlineAlias::NotAnAlias(annot.region.start()), state)),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_type_alias_after_as<'a>(
|
||||
min_indent: u16,
|
||||
) -> impl Parser<'a, Loc<(&'a str, &'a [Loc<&'a str>])>, EType<'a>> {
|
||||
move |arena, state| {
|
||||
space0_before_e(
|
||||
term(min_indent),
|
||||
min_indent,
|
||||
EType::TSpace,
|
||||
EType::TAsIndentStart,
|
||||
)
|
||||
.parse(arena, state)
|
||||
.and_then(|(p, annot, state)| {
|
||||
specialize(EType::TInlineAlias, check_type_alias(p, annot)).parse(arena, state)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn fail_type_start<'a, T: 'a>() -> impl Parser<'a, T, EType<'a>> {
|
||||
|_arena, state: State<'a>| Err((NoProgress, EType::TStart(state.pos), state))
|
||||
}
|
||||
|
@ -72,12 +122,7 @@ fn term<'a>(min_indent: u16) -> impl Parser<'a, Loc<TypeAnnotation<'a>>, EType<'
|
|||
backtrackable(space0_e(min_indent, EType::TSpace, EType::TIndentEnd)),
|
||||
crate::parser::keyword_e(keyword::AS, EType::TEnd)
|
||||
),
|
||||
space0_before_e(
|
||||
term(min_indent),
|
||||
min_indent,
|
||||
EType::TSpace,
|
||||
EType::TAsIndentStart
|
||||
)
|
||||
parse_type_alias_after_as(min_indent)
|
||||
),
|
||||
Some
|
||||
),
|
||||
|
@ -87,13 +132,17 @@ fn term<'a>(min_indent: u16) -> impl Parser<'a, Loc<TypeAnnotation<'a>>, EType<'
|
|||
|arena: &'a Bump,
|
||||
(loc_ann, opt_as): (
|
||||
Loc<TypeAnnotation<'a>>,
|
||||
Option<(&'a [_], Loc<TypeAnnotation<'a>>)>
|
||||
Option<(&'a [_], Loc<(&'a str, &'a [Loc<&'a str>])>)>
|
||||
)| {
|
||||
match opt_as {
|
||||
Some((spaces, loc_as)) => {
|
||||
let region = Region::span_across(&loc_ann.region, &loc_as.region);
|
||||
let value =
|
||||
TypeAnnotation::As(arena.alloc(loc_ann), spaces, arena.alloc(loc_as));
|
||||
Some((
|
||||
spaces,
|
||||
Loc {
|
||||
region,
|
||||
value: alias,
|
||||
},
|
||||
)) => {
|
||||
let value = TypeAnnotation::As(arena.alloc(loc_ann), spaces, alias);
|
||||
|
||||
Loc { region, value }
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ Defs(
|
|||
|L 0-0, C 0-3| Identifier(
|
||||
"foo",
|
||||
),
|
||||
|L 0-0, C 6-33| As(
|
||||
|L 0-0, C 25-33| As(
|
||||
|L 0-0, C 6-21| Apply(
|
||||
"Foo.Bar",
|
||||
"Baz",
|
||||
|
@ -18,16 +18,11 @@ Defs(
|
|||
],
|
||||
),
|
||||
[],
|
||||
|L 0-0, C 25-33| Apply(
|
||||
"",
|
||||
(
|
||||
"Blah",
|
||||
[
|
||||
|L 0-0, C 30-31| BoundVariable(
|
||||
"a",
|
||||
),
|
||||
|L 0-0, C 32-33| BoundVariable(
|
||||
"b",
|
||||
),
|
||||
|L 0-0, C 30-31| "a",
|
||||
|L 0-0, C 32-33| "b",
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue