Merge remote-tracking branch 'origin/trunk' into outdent-infix

This commit is contained in:
Richard Feldman 2022-07-16 16:08:36 -04:00
commit f575807834
No known key found for this signature in database
GPG key ID: 7E4127D1E4241798
116 changed files with 7901 additions and 5073 deletions

View file

@ -298,7 +298,7 @@ pub enum TypeDef<'a> {
Opaque {
header: TypeHeader<'a>,
typ: Loc<TypeAnnotation<'a>>,
derived: Option<Loc<Derived<'a>>>,
derived: Option<Loc<HasAbilities<'a>>>,
},
/// An ability definition. E.g.
@ -435,17 +435,41 @@ pub struct HasClause<'a> {
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Derived<'a> {
/// `has [Eq, Hash]`
Has(Collection<'a, AbilityName<'a>>),
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 Derived<'a>, &'a [CommentOrNewline<'a>]),
SpaceAfter(&'a Derived<'a>, &'a [CommentOrNewline<'a>]),
SpaceBefore(&'a HasImpls<'a>, &'a [CommentOrNewline<'a>]),
SpaceAfter(&'a HasImpls<'a>, &'a [CommentOrNewline<'a>]),
}
impl Derived<'_> {
pub fn collection(&self) -> &Collection<AbilityName> {
/// `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: Option<Loc<HasImpls<'a>>>,
},
// We preserve this for the formatter; canonicalization ignores it.
SpaceBefore(&'a HasAbility<'a>, &'a [CommentOrNewline<'a>]),
SpaceAfter(&'a HasAbility<'a>, &'a [CommentOrNewline<'a>]),
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum HasAbilities<'a> {
/// `has [Eq { eq: myEq }, Hash]`
Has(Collection<'a, Loc<HasAbility<'a>>>),
// We preserve this for the formatter; canonicalization ignores it.
SpaceBefore(&'a HasAbilities<'a>, &'a [CommentOrNewline<'a>]),
SpaceAfter(&'a HasAbilities<'a>, &'a [CommentOrNewline<'a>]),
}
impl HasAbilities<'_> {
pub fn collection(&self) -> &Collection<Loc<HasAbility>> {
let mut it = self;
loop {
match it {
@ -879,6 +903,12 @@ impl<'a, T: Debug> Debug for Collection<'a, T> {
}
}
impl<'a, T> Default for Collection<'a, T> {
fn default() -> Self {
Self::empty()
}
}
pub trait Spaceable<'a> {
fn before(&'a self, _: &'a [CommentOrNewline<'a>]) -> Self;
fn after(&'a self, _: &'a [CommentOrNewline<'a>]) -> Self;
@ -967,12 +997,30 @@ impl<'a> Spaceable<'a> for Has<'a> {
}
}
impl<'a> Spaceable<'a> for Derived<'a> {
impl<'a> Spaceable<'a> for HasImpls<'a> {
fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
Derived::SpaceBefore(self, spaces)
HasImpls::SpaceBefore(self, spaces)
}
fn after(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
Derived::SpaceAfter(self, spaces)
HasImpls::SpaceAfter(self, spaces)
}
}
impl<'a> Spaceable<'a> for HasAbility<'a> {
fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
HasAbility::SpaceBefore(self, spaces)
}
fn after(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
HasAbility::SpaceAfter(self, spaces)
}
}
impl<'a> Spaceable<'a> for HasAbilities<'a> {
fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
HasAbilities::SpaceBefore(self, spaces)
}
fn after(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
HasAbilities::SpaceAfter(self, spaces)
}
}
@ -1059,6 +1107,8 @@ impl_extract_spaces!(Pattern);
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

@ -1,6 +1,6 @@
use crate::ast::{
AssignedField, Collection, CommentOrNewline, Defs, Derived, Expr, ExtractSpaces, Has, Pattern,
Spaceable, TypeAnnotation, TypeDef, TypeHeader, ValueDef,
AssignedField, Collection, CommentOrNewline, Defs, Expr, ExtractSpaces, Has, HasAbilities,
Pattern, Spaceable, TypeAnnotation, TypeDef, TypeHeader, ValueDef,
};
use crate::blankspace::{
space0_after_e, space0_around_ee, space0_before_e, space0_before_optional_after, space0_e,
@ -953,7 +953,7 @@ fn alias_signature_with_space_before<'a>(
fn opaque_signature_with_space_before<'a>(
min_indent: u32,
) -> impl Parser<'a, (Loc<TypeAnnotation<'a>>, Option<Loc<Derived<'a>>>), EExpr<'a>> {
) -> impl Parser<'a, (Loc<TypeAnnotation<'a>>, Option<Loc<HasAbilities<'a>>>), EExpr<'a>> {
and!(
specialize(
EExpr::Type,
@ -966,7 +966,7 @@ fn opaque_signature_with_space_before<'a>(
optional(specialize(
EExpr::Type,
space0_before_e(
type_annotation::has_derived(min_indent),
type_annotation::has_abilities(min_indent),
min_indent,
EType::TIndentStart,
),

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, Derived, 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;
@ -478,8 +478,8 @@ fn has_clause_chain<'a>(
}
}
/// Parse a has-derived clause, e.g. `has [Eq, Hash]`.
pub fn has_derived<'a>(min_indent: u32) -> impl Parser<'a, Loc<Derived<'a>>, EType<'a>> {
/// Parse a has-abilities clause, e.g. `has [Eq, Hash]`.
pub fn has_abilities<'a>(min_indent: u32) -> impl Parser<'a, Loc<HasAbilities<'a>>, EType<'a>> {
skip_first!(
// Parse "has"; we don't care about this keyword
word3(b'h', b'a', b's', EType::THasClause),
@ -488,22 +488,54 @@ pub fn has_derived<'a>(min_indent: u32) -> impl Parser<'a, Loc<Derived<'a>>, ETy
loc!(map!(
collection_trailing_sep_e!(
word1(b'[', EType::TStart),
specialize(EType::TApply, loc!(parse_concrete_type)),
loc!(parse_has_ability(min_indent)),
word1(b',', EType::TEnd),
word1(b']', EType::TEnd),
min_indent + 1,
EType::TStart,
EType::TIndentEnd,
TypeAnnotation::SpaceBefore
HasAbility::SpaceBefore
),
Derived::Has
HasAbilities::Has
)),
min_indent + 1,
EType::TIndentEnd
EType::TIndentEnd,
)
)
}
fn parse_has_ability<'a>(min_indent: u32) -> impl Parser<'a, HasAbility<'a>, EType<'a>> {
map!(
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<_>)| { HasAbility::HasAbility { ability, impls } }
)
}
fn expression<'a>(
min_indent: u32,
is_trailing_comma_valid: bool,

View file

@ -4,27 +4,69 @@ Defs(
Index(0),
Index(1),
Index(2),
Index(3),
Index(4),
Index(5),
Index(6),
Index(7),
Index(8),
Index(9),
],
regions: [
@0-7,
@24-44,
@61-81,
@103-110,
@139-146,
@167-174,
@201-208,
@235-242,
@251-271,
@305-312,
],
space_before: [
Slice(start = 0, length = 0),
Slice(start = 0, length = 2),
Slice(start = 2, length = 2),
Slice(start = 4, length = 2),
Slice(start = 6, length = 2),
Slice(start = 8, length = 2),
Slice(start = 10, length = 2),
Slice(start = 12, length = 2),
Slice(start = 14, length = 2),
Slice(start = 16, length = 2),
],
space_after: [
Slice(start = 0, length = 0),
Slice(start = 2, length = 0),
Slice(start = 4, length = 0),
Slice(start = 6, length = 0),
Slice(start = 8, length = 0),
Slice(start = 10, length = 0),
Slice(start = 12, length = 0),
Slice(start = 14, length = 0),
Slice(start = 16, length = 0),
Slice(start = 18, length = 0),
],
spaces: [
Newline,
Newline,
Newline,
Newline,
Newline,
Newline,
Newline,
Newline,
Newline,
Newline,
Newline,
Newline,
Newline,
Newline,
Newline,
Newline,
Newline,
Newline,
],
type_defs: [
Opaque {
@ -40,16 +82,22 @@ Defs(
derived: Some(
@12-22 Has(
[
@13-15 Apply(
"",
"Eq",
[],
),
@17-21 Apply(
"",
"Hash",
[],
),
@13-15 HasAbility {
ability: @13-15 Apply(
"",
"Eq",
[],
),
impls: None,
},
@17-21 HasAbility {
ability: @17-21 Apply(
"",
"Hash",
[],
),
impls: None,
},
],
),
),
@ -77,16 +125,22 @@ Defs(
derived: Some(
@49-59 Has(
[
@50-52 Apply(
"",
"Eq",
[],
),
@54-58 Apply(
"",
"Hash",
[],
),
@50-52 HasAbility {
ability: @50-52 Apply(
"",
"Eq",
[],
),
impls: None,
},
@54-58 HasAbility {
ability: @54-58 Apply(
"",
"Hash",
[],
),
impls: None,
},
],
),
),
@ -115,16 +169,22 @@ Defs(
@91-101 SpaceBefore(
Has(
[
@92-94 Apply(
"",
"Eq",
[],
),
@96-100 Apply(
"",
"Hash",
[],
),
@92-94 HasAbility {
ability: @92-94 Apply(
"",
"Eq",
[],
),
impls: None,
},
@96-100 HasAbility {
ability: @96-100 Apply(
"",
"Hash",
[],
),
impls: None,
},
],
),
[
@ -133,10 +193,292 @@ Defs(
),
),
},
Opaque {
header: TypeHeader {
name: @103-104 "A",
vars: [],
},
typ: @108-110 Apply(
"",
"U8",
[],
),
derived: Some(
@115-137 Has(
[
@116-123 HasAbility {
ability: @116-118 Apply(
"",
"Eq",
[],
),
impls: Some(
@119-123 HasImpls(
[
@120-122 LabelOnly(
@120-122 "eq",
),
],
),
),
},
@125-136 HasAbility {
ability: @125-129 Apply(
"",
"Hash",
[],
),
impls: Some(
@130-136 HasImpls(
[
@131-135 LabelOnly(
@131-135 "hash",
),
],
),
),
},
],
),
),
},
Opaque {
header: TypeHeader {
name: @139-140 "A",
vars: [],
},
typ: @144-146 Apply(
"",
"U8",
[],
),
derived: Some(
@151-165 Has(
[
@152-164 HasAbility {
ability: @152-154 Apply(
"",
"Eq",
[],
),
impls: Some(
@155-164 HasImpls(
[
@156-158 LabelOnly(
@156-158 "eq",
),
@160-163 LabelOnly(
@160-163 "eq1",
),
],
),
),
},
],
),
),
},
Opaque {
header: TypeHeader {
name: @167-168 "A",
vars: [],
},
typ: @172-174 Apply(
"",
"U8",
[],
),
derived: Some(
@179-199 Has(
[
@180-192 HasAbility {
ability: @180-182 Apply(
"",
"Eq",
[],
),
impls: Some(
@183-192 HasImpls(
[
@184-186 LabelOnly(
@184-186 "eq",
),
@188-191 LabelOnly(
@188-191 "eq1",
),
],
),
),
},
@194-198 HasAbility {
ability: @194-198 Apply(
"",
"Hash",
[],
),
impls: None,
},
],
),
),
},
Opaque {
header: TypeHeader {
name: @201-202 "A",
vars: [],
},
typ: @206-208 Apply(
"",
"U8",
[],
),
derived: Some(
@213-233 Has(
[
@214-218 HasAbility {
ability: @214-218 Apply(
"",
"Hash",
[],
),
impls: None,
},
@220-232 HasAbility {
ability: @220-222 Apply(
"",
"Eq",
[],
),
impls: Some(
@223-232 HasImpls(
[
@224-226 LabelOnly(
@224-226 "eq",
),
@228-231 LabelOnly(
@228-231 "eq1",
),
],
),
),
},
],
),
),
},
Opaque {
header: TypeHeader {
name: @235-236 "A",
vars: [],
},
typ: @240-242 Apply(
"",
"U8",
[],
),
derived: Some(
@247-249 Has(
[],
),
),
},
Opaque {
header: TypeHeader {
name: @251-252 "A",
vars: [],
},
typ: @256-271 Where(
@256-257 BoundVariable(
"a",
),
[
@260-271 HasClause {
var: @260-261 "a",
ability: @266-271 Apply(
"",
"Other",
[],
),
},
],
),
derived: Some(
@281-303 SpaceBefore(
Has(
[
@282-289 HasAbility {
ability: @282-284 Apply(
"",
"Eq",
[],
),
impls: Some(
@285-289 HasImpls(
[
@286-288 LabelOnly(
@286-288 "eq",
),
],
),
),
},
@291-302 HasAbility {
ability: @291-295 Apply(
"",
"Hash",
[],
),
impls: Some(
@296-302 HasImpls(
[
@297-301 LabelOnly(
@297-301 "hash",
),
],
),
),
},
],
),
[
Newline,
],
),
),
},
Opaque {
header: TypeHeader {
name: @305-306 "A",
vars: [],
},
typ: @310-312 Apply(
"",
"U8",
[],
),
derived: Some(
@317-324 Has(
[
@318-323 HasAbility {
ability: @318-320 Apply(
"",
"Eq",
[],
),
impls: Some(
@321-323 HasImpls(
[],
),
),
},
],
),
),
},
],
value_defs: [],
},
@103-104 SpaceBefore(
@326-327 SpaceBefore(
Num(
"0",
),

View file

@ -5,4 +5,19 @@ 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}]
A := U8 has [Eq {}]
0