Parse impl blocks in abilities

This commit is contained in:
Ayaz Hafiz 2022-07-15 11:06:44 -04:00
parent d4d073d8c6
commit 85599e3a9a
No known key found for this signature in database
GPG Key ID: 0E2A37416A25EF58
4 changed files with 105 additions and 11 deletions

View File

@ -434,13 +434,23 @@ pub struct HasClause<'a> {
pub ability: AbilityName<'a>,
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum HasImpls<'a> {
// `{ eq: myEq }`
HasImpls(Collection<'a, Loc<AssignedField<'a, TypeAnnotation<'a>>>>),
// We preserve this for the formatter; canonicalization ignores it.
SpaceBefore(&'a HasImpls<'a>, &'a [CommentOrNewline<'a>]),
SpaceAfter(&'a HasImpls<'a>, &'a [CommentOrNewline<'a>]),
}
/// `Eq` or `Eq { eq: myEq }`
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum HasAbility<'a> {
HasAbility {
/// Should be a zero-argument `Apply` or an error; we'll check this in canonicalization
ability: Loc<TypeAnnotation<'a>>,
impls: Collection<'a, Loc<AssignedField<'a, TypeAnnotation<'a>>>>,
impls: Option<Loc<HasImpls<'a>>>,
},
// We preserve this for the formatter; canonicalization ignores it.
@ -987,6 +997,15 @@ impl<'a> Spaceable<'a> for Has<'a> {
}
}
impl<'a> Spaceable<'a> for HasImpls<'a> {
fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
HasImpls::SpaceBefore(self, spaces)
}
fn after(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
HasImpls::SpaceAfter(self, spaces)
}
}
impl<'a> Spaceable<'a> for HasAbility<'a> {
fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
HasAbility::SpaceBefore(self, spaces)
@ -1089,6 +1108,7 @@ impl_extract_spaces!(Tag);
impl_extract_spaces!(AssignedField<T>);
impl_extract_spaces!(TypeAnnotation);
impl_extract_spaces!(HasAbility);
impl_extract_spaces!(HasImpls);
impl<'a, T: Copy> ExtractSpaces<'a> for Spaced<'a, T> {
type Item = T;

View File

@ -103,6 +103,7 @@ impl_space_problem! {
ETypeRecord<'a>,
ETypeTagUnion<'a>,
ETypedIdent<'a>,
ETypeAbilityImpl<'a>,
EWhen<'a>,
EAbility<'a>,
PInParens<'a>,
@ -578,6 +579,7 @@ pub enum EType<'a> {
TFunctionArgument(Position),
TWhereBar(Position),
THasClause(Position),
TAbilityImpl(ETypeAbilityImpl<'a>, Position),
///
TIndentStart(Position),
TIndentEnd(Position),
@ -648,6 +650,42 @@ pub enum ETypeInlineAlias {
ArgumentNotLowercase(Position),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ETypeAbilityImpl<'a> {
End(Position),
Open(Position),
Field(Position),
Colon(Position),
Optional(Position),
Type(&'a EType<'a>, Position),
Space(BadInputError, Position),
IndentOpen(Position),
IndentColon(Position),
IndentOptional(Position),
IndentEnd(Position),
}
impl<'a> From<ETypeRecord<'a>> for ETypeAbilityImpl<'a> {
fn from(e: ETypeRecord<'a>) -> Self {
match e {
ETypeRecord::End(p) => ETypeAbilityImpl::End(p),
ETypeRecord::Open(p) => ETypeAbilityImpl::Open(p),
ETypeRecord::Field(p) => ETypeAbilityImpl::Field(p),
ETypeRecord::Colon(p) => ETypeAbilityImpl::Colon(p),
ETypeRecord::Optional(p) => ETypeAbilityImpl::Optional(p),
ETypeRecord::Type(t, p) => ETypeAbilityImpl::Type(t, p),
ETypeRecord::Space(s, p) => ETypeAbilityImpl::Space(s, p),
ETypeRecord::IndentOpen(p) => ETypeAbilityImpl::IndentOpen(p),
ETypeRecord::IndentColon(p) => ETypeAbilityImpl::IndentColon(p),
ETypeRecord::IndentOptional(p) => ETypeAbilityImpl::IndentOptional(p),
ETypeRecord::IndentEnd(p) => ETypeAbilityImpl::IndentEnd(p),
}
}
}
#[derive(Debug)]
pub struct SourceError<'a, T> {
pub problem: T,

View File

@ -1,16 +1,16 @@
use crate::ast::{
AssignedField, CommentOrNewline, HasAbilities, HasAbility, HasClause, Pattern, Spaced, Tag,
TypeAnnotation, TypeHeader,
AssignedField, CommentOrNewline, HasAbilities, HasAbility, HasClause, HasImpls, Pattern,
Spaced, Tag, TypeAnnotation, TypeHeader,
};
use crate::blankspace::{space0_around_ee, space0_before_e, space0_e};
use crate::ident::lowercase_ident;
use crate::keyword;
use crate::parser::then;
use crate::parser::{
allocated, backtrackable, optional, specialize, specialize_ref, word1, word2, word3, EType,
ETypeApply, ETypeInParens, ETypeInlineAlias, ETypeRecord, ETypeTagUnion, ParseResult, Parser,
Progress::{self, *},
};
use crate::parser::{then, ETypeAbilityImpl};
use crate::state::State;
use bumpalo::collections::vec::Vec;
use bumpalo::Bump;
@ -504,14 +504,37 @@ pub fn has_abilities<'a>(min_indent: u32) -> impl Parser<'a, Loc<HasAbilities<'a
)
}
fn parse_has_ability<'a>(_min_indent: u32) -> impl Parser<'a, HasAbility<'a>, EType<'a>> {
fn parse_has_ability<'a>(min_indent: u32) -> impl Parser<'a, HasAbility<'a>, EType<'a>> {
map!(
loc!(specialize(EType::TApply, parse_concrete_type)),
|ability| {
HasAbility::HasAbility {
ability,
impls: Default::default(),
}
and!(
loc!(specialize(EType::TApply, parse_concrete_type)),
optional(space0_before_e(
loc!(map!(
specialize(
EType::TAbilityImpl,
collection_trailing_sep_e!(
word1(b'{', ETypeAbilityImpl::Open),
specialize(
|e: ETypeRecord<'_>, _| e.into(),
loc!(record_type_field(min_indent + 1))
),
word1(b',', ETypeAbilityImpl::End),
word1(b'}', ETypeAbilityImpl::End),
min_indent,
ETypeAbilityImpl::Open,
ETypeAbilityImpl::IndentEnd,
AssignedField::SpaceBefore
)
),
HasImpls::HasImpls
)),
min_indent + 1,
EType::TIndentEnd
))
),
|(ability, impls): (_, Option<_>)| {
dbg!(1, &ability, &impls);
HasAbility::HasAbility { ability, impls }
}
)
}

View File

@ -5,4 +5,17 @@ A := a | a has Other has [Eq, Hash]
A := a | a has Other
has [Eq, Hash]
A := U8 has [Eq {eq}, Hash {hash}]
A := U8 has [Eq {eq, eq1}]
A := U8 has [Eq {eq, eq1}, Hash]
A := U8 has [Hash, Eq {eq, eq1}]
A := U8 has []
A := a | a has Other
has [Eq {eq}, Hash {hash}]
0