Support parsing multiple abilities in a clause

This commit is contained in:
Ayaz Hafiz 2022-10-11 17:08:38 -05:00
parent bdc565762b
commit 548a235c25
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
14 changed files with 165 additions and 95 deletions

View file

@ -439,7 +439,7 @@ pub type AbilityName<'a> = Loc<TypeAnnotation<'a>>;
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct HasClause<'a> {
pub var: Loc<Spaced<'a, &'a str>>,
pub ability: AbilityName<'a>,
pub abilities: &'a [AbilityName<'a>],
}
#[derive(Debug, Copy, Clone, PartialEq)]

View file

@ -2,7 +2,9 @@ use crate::ast::{
AssignedField, CommentOrNewline, HasAbilities, HasAbility, HasClause, HasImpls, Pattern,
Spaced, Tag, TypeAnnotation, TypeHeader,
};
use crate::blankspace::{space0_around_ee, space0_before_e, space0_e};
use crate::blankspace::{
space0_around_ee, space0_before_e, space0_before_optional_after, space0_e,
};
use crate::expr::record_value_field;
use crate::ident::lowercase_ident;
use crate::keyword;
@ -410,6 +412,37 @@ fn loc_applied_args_e<'a>(
zero_or_more!(loc_applied_arg(min_indent, stop_at_surface_has))
}
// Hash & Eq & ...
fn ability_chain<'a>(
min_indent: u32,
) -> impl Parser<'a, Vec<'a, Loc<TypeAnnotation<'a>>>, EType<'a>> {
map!(
and!(
space0_before_optional_after(
specialize(EType::TApply, loc!(parse_concrete_type)),
min_indent,
EType::TIndentStart,
EType::TIndentEnd,
),
zero_or_more!(skip_first!(
word1(b'&', EType::THasClause),
space0_before_e(
specialize(EType::TApply, loc!(parse_concrete_type)),
min_indent,
EType::TIndentStart,
)
))
),
|(first_ability, mut other_abilities): (
Loc<TypeAnnotation<'a>>,
Vec<'a, Loc<TypeAnnotation<'a>>>
)| {
other_abilities.push(first_ability);
other_abilities
}
)
}
fn has_clause<'a>(min_indent: u32) -> impl Parser<'a, Loc<HasClause<'a>>, EType<'a>> {
map!(
// Suppose we are trying to parse "a has Hash"
@ -427,20 +460,22 @@ fn has_clause<'a>(min_indent: u32) -> impl Parser<'a, Loc<HasClause<'a>>, EType<
then(
// Parse "has"; we don't care about this keyword
word3(b'h', b'a', b's', EType::THasClause),
// Parse "Hash"; this may be qualified from another module like "Hash.Hash"
// Parse "Hash & ..."; this may be qualified from another module like "Hash.Hash"
|arena, state, _progress, _output| {
space0_before_e(
specialize(EType::TApply, loc!(parse_concrete_type)),
state.column() + 1,
EType::TIndentStart,
)
.parse(arena, state)
ability_chain(state.column() + 1).parse(arena, state)
}
)
),
|(var, ability): (Loc<Spaced<'a, &'a str>>, Loc<TypeAnnotation<'a>>)| {
let region = Region::span_across(&var.region, &ability.region);
let has_clause = HasClause { var, ability };
|(var, abilities): (Loc<Spaced<'a, &'a str>>, Vec<'a, Loc<TypeAnnotation<'a>>>)| {
let abilities_region = Region::span_across(
&abilities.first().unwrap().region,
&abilities.last().unwrap().region,
);
let region = Region::span_across(&var.region, &abilities_region);
let has_clause = HasClause {
var,
abilities: abilities.into_bump_slice(),
};
Loc::at(region, has_clause)
}
)

View file

@ -39,11 +39,13 @@ Defs(
[
@27-37 HasClause {
var: @27-28 "a",
ability: @33-37 Apply(
"",
"Hash",
[],
),
abilities: [
@33-37 Apply(
"",
"Hash",
[],
),
],
},
],
),

View file

@ -45,11 +45,13 @@ Defs(
[
@24-33 HasClause {
var: @24-25 "a",
ability: @30-33 Apply(
"",
"Ab1",
[],
),
abilities: [
@30-33 Apply(
"",
"Ab1",
[],
),
],
},
],
),
@ -80,11 +82,13 @@ Defs(
[
@59-68 HasClause {
var: @59-60 "a",
ability: @65-68 Apply(
"",
"Ab2",
[],
),
abilities: [
@65-68 Apply(
"",
"Ab2",
[],
),
],
},
],
),

View file

@ -114,11 +114,13 @@ Defs(
[
@33-44 HasClause {
var: @33-34 "a",
ability: @39-44 Apply(
"",
"Other",
[],
),
abilities: [
@39-44 Apply(
"",
"Other",
[],
),
],
},
],
),
@ -157,11 +159,13 @@ Defs(
[
@70-81 HasClause {
var: @70-71 "a",
ability: @76-81 Apply(
"",
"Other",
[],
),
abilities: [
@76-81 Apply(
"",
"Other",
[],
),
],
},
],
),
@ -394,11 +398,13 @@ Defs(
[
@260-271 HasClause {
var: @260-261 "a",
ability: @266-271 Apply(
"",
"Other",
[],
),
abilities: [
@266-271 Apply(
"",
"Other",
[],
),
],
},
],
),

View file

@ -40,11 +40,13 @@ Defs(
[
@20-27 HasClause {
var: @20-21 "a",
ability: @26-27 Apply(
"",
"A",
[],
),
abilities: [
@26-27 Apply(
"",
"A",
[],
),
],
},
],
),

View file

@ -40,27 +40,33 @@ Defs(
[
@20-27 HasClause {
var: @20-21 "a",
ability: @26-27 Apply(
"",
"A",
[],
),
abilities: [
@26-27 Apply(
"",
"A",
[],
),
],
},
@29-37 HasClause {
var: @29-30 "b",
ability: @35-37 Apply(
"",
"Eq",
[],
),
abilities: [
@35-37 Apply(
"",
"Eq",
[],
),
],
},
@39-48 HasClause {
var: @39-40 "c",
ability: @45-48 Apply(
"",
"Ord",
[],
),
abilities: [
@45-48 Apply(
"",
"Ord",
[],
),
],
},
],
),

View file

@ -45,11 +45,13 @@ Defs(
[
@24-34 HasClause {
var: @24-25 "a",
ability: @30-34 Apply(
"",
"Hash",
[],
),
abilities: [
@30-34 Apply(
"",
"Hash",
[],
),
],
},
@42-50 HasClause {
var: @42-43 SpaceBefore(
@ -58,11 +60,13 @@ Defs(
Newline,
],
),
ability: @48-50 Apply(
"",
"Eq",
[],
),
abilities: [
@48-50 Apply(
"",
"Eq",
[],
),
],
},
@58-67 HasClause {
var: @58-59 SpaceBefore(
@ -71,11 +75,13 @@ Defs(
Newline,
],
),
ability: @64-67 Apply(
"",
"Ord",
[],
),
abilities: [
@64-67 Apply(
"",
"Ord",
[],
),
],
},
],
),

View file

@ -26,11 +26,13 @@ Defs(
[
@8-15 HasClause {
var: @8-9 "a",
ability: @14-15 Apply(
"",
"A",
[],
),
abilities: [
@14-15 Apply(
"",
"A",
[],
),
],
},
],
),

View file

@ -40,11 +40,13 @@ Defs(
[
@19-29 HasClause {
var: @19-20 "a",
ability: @25-29 Apply(
"",
"Hash",
[],
),
abilities: [
@25-29 Apply(
"",
"Hash",
[],
),
],
},
],
),