Introduce Collection as a general abstraction in the ast

This commit is contained in:
Joshua Warner 2021-11-11 14:24:15 -08:00
parent ac733b1805
commit 04d4a8ca79
10 changed files with 49 additions and 37 deletions

View file

@ -5,6 +5,18 @@ use bumpalo::Bump;
use roc_module::operator::{BinOp, CalledVia, UnaryOp};
use roc_region::all::{Loc, Position, Region};
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Collection<'a, T> {
pub items: &'a [T],
pub final_comments: &'a [CommentOrNewline<'a>],
}
impl<'a, T> Collection<'a, T> {
pub fn empty() -> Collection<'a, T> {
Collection { items: &[], final_comments: &[] }
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Module<'a> {
Interface { header: InterfaceHeader<'a> },
@ -231,11 +243,11 @@ pub enum TypeAnnotation<'a> {
),
Record {
fields: &'a [Loc<AssignedField<'a, TypeAnnotation<'a>>>],
fields: Collection<'a, Loc<AssignedField<'a, TypeAnnotation<'a>>>>,
/// The row type variable in an open record, e.g. the `r` in `{ name: Str }r`.
/// This is None if it's a closed record annotation like `{ name: Str }`.
ext: Option<&'a Loc<TypeAnnotation<'a>>>,
final_comments: &'a [CommentOrNewline<'a>],
// final_comments: &'a [CommentOrNewline<'a>],
},
/// A tag union, e.g. `[

View file

@ -2149,7 +2149,7 @@ fn ident_to_expr<'a>(arena: &'a Bump, src: Ident<'a>) -> Expr<'a> {
fn list_literal_help<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>, List<'a>> {
move |arena, state| {
let (_, (parsed_elems, final_comments), state) = collection_trailing_sep_e!(
let (_, elements, state) = collection_trailing_sep_e!(
word1(b'[', List::Open),
specialize_ref(List::Expr, move |a, s| parse_loc_expr_no_multi_backpassing(
min_indent, a, s
@ -2164,15 +2164,15 @@ fn list_literal_help<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>, List<'a>>
)
.parse(arena, state)?;
let mut allocated = Vec::with_capacity_in(parsed_elems.len(), arena);
let mut allocated = Vec::with_capacity_in(elements.items.len(), arena);
for parsed_elem in parsed_elems {
allocated.push(&*arena.alloc(parsed_elem));
for parsed_elem in elements.items {
allocated.push(parsed_elem);
}
let expr = Expr::List {
items: allocated.into_bump_slice(),
final_comments,
final_comments: elements.final_comments,
};
Ok((MadeProgress, expr, state))

View file

@ -1300,7 +1300,12 @@ macro_rules! collection_trailing_sep_e {
}
}
Ok((MadeProgress, (parsed_elems, final_comments), state))
let collection = $crate::ast::Collection {
items: parsed_elems.into_bump_slice(),
final_comments,
};
Ok((MadeProgress, collection, state))
}
)
};

View file

@ -316,7 +316,7 @@ fn lowercase_ident_pattern<'a>(
#[inline(always)]
fn record_pattern_help<'a>(min_indent: u16) -> impl Parser<'a, Pattern<'a>, PRecord<'a>> {
move |arena, state| {
let (_, (fields, final_comments), state) = collection_trailing_sep_e!(
let (_, fields, state) = collection_trailing_sep_e!(
// word1_check_indent!(b'{', PRecord::Open, min_indent, PRecord::IndentOpen),
word1(b'{', PRecord::Open),
record_pattern_field(min_indent),
@ -332,9 +332,9 @@ fn record_pattern_help<'a>(min_indent: u16) -> impl Parser<'a, Pattern<'a>, PRec
.parse(arena, state)?;
// TODO
let _unused = final_comments;
let _unused = fields.final_comments;
let result = Pattern::RecordDestructure(fields.into_bump_slice());
let result = Pattern::RecordDestructure(fields.items);
Ok((MadeProgress, result, state))
}

View file

@ -1,4 +1,4 @@
use crate::ast::{AssignedField, Tag, TypeAnnotation};
use crate::ast::{AssignedField, Tag, TypeAnnotation, Collection};
use crate::blankspace::{space0_around_ee, space0_before_e, space0_e};
use crate::keyword;
use crate::parser::{
@ -18,7 +18,7 @@ pub fn located_help<'a>(min_indent: u16) -> impl Parser<'a, Located<TypeAnnotati
#[inline(always)]
fn tag_union_type<'a>(min_indent: u16) -> impl Parser<'a, TypeAnnotation<'a>, TTagUnion<'a>> {
move |arena, state| {
let (_, (tags, final_comments), state) = collection_trailing_sep_e!(
let (_, tags, state) = collection_trailing_sep_e!(
word1(b'[', TTagUnion::Open),
loc!(tag_type(min_indent)),
word1(b',', TTagUnion::End),
@ -37,9 +37,9 @@ fn tag_union_type<'a>(min_indent: u16) -> impl Parser<'a, TypeAnnotation<'a>, TT
.parse(arena, state)?;
let result = TypeAnnotation::TagUnion {
tags: tags.into_bump_slice(),
tags: tags.items,
ext,
final_comments,
final_comments: tags.final_comments,
};
Ok((MadeProgress, result, state))
@ -267,7 +267,7 @@ fn record_type<'a>(min_indent: u16) -> impl Parser<'a, TypeAnnotation<'a>, TReco
use crate::type_annotation::TypeAnnotation::*;
move |arena, state| {
let (_, (fields, final_comments), state) = collection_trailing_sep_e!(
let (_, fields, state) = collection_trailing_sep_e!(
// word1_check_indent!(b'{', TRecord::Open, min_indent, TRecord::IndentOpen),
word1(b'{', TRecord::Open),
loc!(record_type_field(min_indent)),
@ -286,9 +286,11 @@ fn record_type<'a>(min_indent: u16) -> impl Parser<'a, TypeAnnotation<'a>, TReco
let (_, ext, state) = optional(allocated(field_term)).parse(arena, state)?;
let result = Record {
fields: fields.into_bump_slice(),
fields: Collection {
items: fields.items,
final_comments: fields.final_comments,
},
ext,
final_comments,
};
Ok((MadeProgress, result, state))