Parse "as" aliases into tag/args rather than arbitrary annotations

This commit is contained in:
ayazhafiz 2021-12-24 15:42:58 -06:00
parent 4ddb8e10fb
commit 2cd5bf8c03
8 changed files with 276 additions and 253 deletions

View file

@ -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 {

View file

@ -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,

View file

@ -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 }
}

View file

@ -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",
],
),
),