mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-21 07:49:17 +03:00
Merge pull request #1960 from rtfeldman/joshuawarner32/refactor-extract-Collection
Introduce Collection as a general abstraction in the ast
This commit is contained in:
commit
35a74a1fe4
@ -395,7 +395,8 @@ pub fn to_type2<'a>(
|
||||
Type2::Variable(var)
|
||||
}
|
||||
Record { fields, ext, .. } => {
|
||||
let field_types_map = can_assigned_fields(env, scope, references, fields, region);
|
||||
let field_types_map =
|
||||
can_assigned_fields(env, scope, references, &fields.items, region);
|
||||
|
||||
let field_types = PoolVec::with_capacity(field_types_map.len() as u32, env.pool);
|
||||
|
||||
|
@ -389,7 +389,7 @@ fn can_annotation_help(
|
||||
Record { fields, ext, .. } => {
|
||||
let field_types = can_assigned_fields(
|
||||
env,
|
||||
fields,
|
||||
&fields.items,
|
||||
region,
|
||||
scope,
|
||||
var_store,
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::spaces::{fmt_comments_only, fmt_spaces, newline, NewlineAt, INDENT};
|
||||
use bumpalo::collections::String;
|
||||
use roc_parse::ast::{AssignedField, Expr, Tag, TypeAnnotation};
|
||||
use roc_parse::ast::{AssignedField, Collection, Expr, Tag, TypeAnnotation};
|
||||
use roc_region::all::Located;
|
||||
|
||||
/// Does an AST node need parens around it?
|
||||
@ -183,17 +183,13 @@ impl<'a> Formattable<'a> for TypeAnnotation<'a> {
|
||||
Apply(_, _, args) => args.iter().any(|loc_arg| loc_arg.value.is_multiline()),
|
||||
As(lhs, _, rhs) => lhs.value.is_multiline() || rhs.value.is_multiline(),
|
||||
|
||||
Record {
|
||||
fields,
|
||||
ext,
|
||||
final_comments: _,
|
||||
} => {
|
||||
Record { fields, ext } => {
|
||||
match ext {
|
||||
Some(ann) if ann.value.is_multiline() => return true,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
fields.iter().any(|field| field.value.is_multiline())
|
||||
fields.items.iter().any(|field| field.value.is_multiline())
|
||||
}
|
||||
|
||||
TagUnion {
|
||||
@ -296,16 +292,19 @@ impl<'a> Formattable<'a> for TypeAnnotation<'a> {
|
||||
}
|
||||
|
||||
Record {
|
||||
fields,
|
||||
fields:
|
||||
Collection {
|
||||
items,
|
||||
final_comments,
|
||||
},
|
||||
ext,
|
||||
final_comments,
|
||||
} => {
|
||||
format_sequence!(
|
||||
buf,
|
||||
indent,
|
||||
'{',
|
||||
'}',
|
||||
fields,
|
||||
items,
|
||||
final_comments,
|
||||
newlines,
|
||||
AssignedField
|
||||
|
@ -293,16 +293,12 @@ fn type_to_docs(in_func_type_ann: bool, type_annotation: ast::TypeAnnotation) ->
|
||||
|
||||
Apply { name, parts }
|
||||
}
|
||||
ast::TypeAnnotation::Record {
|
||||
fields,
|
||||
ext,
|
||||
final_comments: _,
|
||||
} => {
|
||||
ast::TypeAnnotation::Record { fields, ext } => {
|
||||
let mut doc_fields = Vec::new();
|
||||
|
||||
let mut any_fields_include_private_tags = false;
|
||||
|
||||
for field in fields {
|
||||
for field in fields.items {
|
||||
match record_field_to_doc(in_func_type_ann, field.value) {
|
||||
None => {
|
||||
any_fields_include_private_tags = true;
|
||||
|
@ -2630,7 +2630,7 @@ fn parse_header<'a>(
|
||||
std::str::from_utf8_unchecked(&src_bytes[..chomped])
|
||||
};
|
||||
|
||||
let packages = header.packages.into_bump_slice();
|
||||
let packages = header.packages.items;
|
||||
|
||||
let info = HeaderInfo {
|
||||
loc_name: Located {
|
||||
|
@ -5,6 +5,28 @@ 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: &[],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_items(items: &'a [T]) -> Collection<'a, T> {
|
||||
Collection {
|
||||
items,
|
||||
final_comments: &[],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Module<'a> {
|
||||
Interface { header: InterfaceHeader<'a> },
|
||||
@ -231,11 +253,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. `[
|
||||
|
@ -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))
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::ast::{CommentOrNewline, Spaceable, StrLiteral, TypeAnnotation};
|
||||
use crate::ast::{Collection, CommentOrNewline, Spaceable, StrLiteral, TypeAnnotation};
|
||||
use crate::blankspace::space0_e;
|
||||
use crate::ident::lowercase_ident;
|
||||
use crate::parser::Progress::{self, *};
|
||||
@ -81,7 +81,7 @@ pub enum To<'a> {
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct AppHeader<'a> {
|
||||
pub name: Loc<StrLiteral<'a>>,
|
||||
pub packages: Vec<'a, Loc<PackageEntry<'a>>>,
|
||||
pub packages: Collection<'a, Loc<PackageEntry<'a>>>,
|
||||
pub imports: Vec<'a, Loc<ImportsEntry<'a>>>,
|
||||
pub provides: Vec<'a, Loc<ExposesEntry<'a, &'a str>>>,
|
||||
pub to: Loc<To<'a>>,
|
||||
@ -146,7 +146,7 @@ pub struct PlatformHeader<'a> {
|
||||
pub name: Loc<PackageName<'a>>,
|
||||
pub requires: PlatformRequires<'a>,
|
||||
pub exposes: Vec<'a, Loc<ExposesEntry<'a, ModuleName<'a>>>>,
|
||||
pub packages: Vec<'a, Loc<PackageEntry<'a>>>,
|
||||
pub packages: Collection<'a, Loc<PackageEntry<'a>>>,
|
||||
pub imports: Vec<'a, Loc<ImportsEntry<'a>>>,
|
||||
pub provides: Vec<'a, Loc<ExposesEntry<'a, &'a str>>>,
|
||||
pub effects: Effects<'a>,
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::ast::{CommentOrNewline, Def, Module};
|
||||
use crate::ast::{Collection, CommentOrNewline, Def, Module};
|
||||
use crate::blankspace::{space0_around_ee, space0_before_e, space0_e};
|
||||
use crate::header::{
|
||||
package_entry, package_name, package_or_path, AppHeader, Effects, ExposesEntry, ImportsEntry,
|
||||
@ -203,7 +203,7 @@ fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>, EHeader<'a>> {
|
||||
let (_, provides, state) =
|
||||
specialize(EHeader::Provides, provides_to()).parse(arena, state)?;
|
||||
|
||||
let (before_packages, after_packages, package_entries) = match opt_pkgs {
|
||||
let (before_packages, after_packages, packages) = match opt_pkgs {
|
||||
Some(pkgs) => {
|
||||
let pkgs: Packages<'a> = pkgs; // rustc must be told the type here
|
||||
|
||||
@ -213,7 +213,7 @@ fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>, EHeader<'a>> {
|
||||
pkgs.entries,
|
||||
)
|
||||
}
|
||||
None => (&[] as _, &[] as _, Vec::new_in(arena)),
|
||||
None => (&[] as _, &[] as _, Collection::empty()),
|
||||
};
|
||||
|
||||
// rustc must be told the type here
|
||||
@ -229,7 +229,7 @@ fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>, EHeader<'a>> {
|
||||
|
||||
let header = AppHeader {
|
||||
name,
|
||||
packages: package_entries,
|
||||
packages,
|
||||
imports,
|
||||
provides: provides.entries,
|
||||
to: provides.to,
|
||||
@ -582,11 +582,9 @@ where
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Packages<'a> {
|
||||
entries: Vec<'a, Located<PackageEntry<'a>>>,
|
||||
|
||||
entries: Collection<'a, Located<PackageEntry<'a>>>,
|
||||
before_packages_keyword: &'a [CommentOrNewline<'a>],
|
||||
after_packages_keyword: &'a [CommentOrNewline<'a>],
|
||||
final_comments: &'a [CommentOrNewline<'a>],
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@ -615,12 +613,14 @@ fn packages<'a>() -> impl Parser<'a, Packages<'a>, EPackages<'a>> {
|
||||
PackageEntry::SpaceBefore
|
||||
)
|
||||
),
|
||||
|((before_packages_keyword, after_packages_keyword), (entries, final_comments))| {
|
||||
|((before_packages_keyword, after_packages_keyword), entries): (
|
||||
(_, _),
|
||||
Collection<'a, _>
|
||||
)| {
|
||||
Packages {
|
||||
entries,
|
||||
before_packages_keyword,
|
||||
after_packages_keyword,
|
||||
final_comments,
|
||||
}
|
||||
}
|
||||
)
|
||||
|
@ -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))
|
||||
}
|
||||
)
|
||||
};
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::ast::{AssignedField, Tag, TypeAnnotation};
|
||||
use crate::ast::{AssignedField, Collection, Tag, TypeAnnotation};
|
||||
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))
|
||||
|
@ -23,7 +23,9 @@ mod test_parse {
|
||||
use roc_parse::ast::Pattern::{self, *};
|
||||
use roc_parse::ast::StrLiteral::{self, *};
|
||||
use roc_parse::ast::StrSegment::*;
|
||||
use roc_parse::ast::{self, Def, EscapedChar, Spaceable, TypeAnnotation, WhenBranch};
|
||||
use roc_parse::ast::{
|
||||
self, Collection, Def, EscapedChar, Spaceable, TypeAnnotation, WhenBranch,
|
||||
};
|
||||
use roc_parse::header::{
|
||||
AppHeader, Effects, ExposesEntry, ImportsEntry, InterfaceHeader, ModuleName, PackageEntry,
|
||||
PackageName, PackageOrPath, PlatformHeader, PlatformRequires, PlatformRigid, To,
|
||||
@ -2281,9 +2283,8 @@ mod test_parse {
|
||||
6,
|
||||
TypeAnnotation::SpaceBefore(
|
||||
&TypeAnnotation::Record {
|
||||
fields: &[],
|
||||
fields: Collection::empty(),
|
||||
ext: None,
|
||||
final_comments: &[],
|
||||
},
|
||||
&[Newline],
|
||||
),
|
||||
@ -2320,9 +2321,8 @@ mod test_parse {
|
||||
6,
|
||||
TypeAnnotation::SpaceBefore(
|
||||
&TypeAnnotation::Record {
|
||||
fields: &[],
|
||||
fields: Collection::empty(),
|
||||
ext: None,
|
||||
final_comments: &[],
|
||||
},
|
||||
&[LineComment(" comment")],
|
||||
),
|
||||
@ -3091,7 +3091,7 @@ mod test_parse {
|
||||
#[test]
|
||||
fn empty_app_header() {
|
||||
let arena = Bump::new();
|
||||
let packages = Vec::new_in(&arena);
|
||||
let packages = Collection::empty();
|
||||
let imports = Vec::new_in(&arena);
|
||||
let provides = Vec::new_in(&arena);
|
||||
let module_name = StrLiteral::PlainLine("test-app");
|
||||
@ -3131,7 +3131,7 @@ mod test_parse {
|
||||
use PackageOrPath::Path;
|
||||
|
||||
let arena = Bump::new();
|
||||
let packages = Vec::new_in(&arena);
|
||||
let packages = Collection::empty();
|
||||
let imports = Vec::new_in(&arena);
|
||||
let provides = Vec::new_in(&arena);
|
||||
let module_name = StrLiteral::PlainLine("test-app");
|
||||
@ -3180,7 +3180,7 @@ mod test_parse {
|
||||
};
|
||||
let loc_pkg_entry = Located::new(1, 1, 15, 33, pkg_entry);
|
||||
let arena = Bump::new();
|
||||
let packages = bumpalo::vec![in &arena; loc_pkg_entry];
|
||||
let packages = Collection::with_items(arena.alloc([loc_pkg_entry]));
|
||||
let import = ImportsEntry::Package("foo", ModuleName::new("Bar.Baz"), Vec::new_in(&arena));
|
||||
let loc_import = Located::new(2, 2, 14, 25, import);
|
||||
let imports = bumpalo::vec![in &arena; loc_import];
|
||||
@ -3236,7 +3236,7 @@ mod test_parse {
|
||||
};
|
||||
let loc_pkg_entry = Located::new(1, 1, 15, 33, pkg_entry);
|
||||
let arena = Bump::new();
|
||||
let packages = bumpalo::vec![in &arena; loc_pkg_entry];
|
||||
let packages = Collection::with_items(arena.alloc([loc_pkg_entry]));
|
||||
let import = ImportsEntry::Package("foo", ModuleName::new("Bar.Baz"), Vec::new_in(&arena));
|
||||
let loc_import = Located::new(2, 2, 14, 25, import);
|
||||
let imports = bumpalo::vec![in &arena; loc_import];
|
||||
@ -3309,9 +3309,8 @@ mod test_parse {
|
||||
ann: Located::at(
|
||||
region2,
|
||||
TypeAnnotation::Record {
|
||||
fields: &[],
|
||||
fields: Collection::empty(),
|
||||
ext: None,
|
||||
final_comments: &[],
|
||||
},
|
||||
),
|
||||
},
|
||||
@ -3324,7 +3323,7 @@ mod test_parse {
|
||||
name: Located::new(0, 0, 9, 23, pkg_name),
|
||||
requires,
|
||||
exposes: Vec::new_in(&arena),
|
||||
packages: Vec::new_in(&arena),
|
||||
packages: Collection::empty(),
|
||||
imports: Vec::new_in(&arena),
|
||||
provides: Vec::new_in(&arena),
|
||||
effects,
|
||||
@ -3367,7 +3366,7 @@ mod test_parse {
|
||||
};
|
||||
let loc_pkg_entry = Located::new(3, 3, 15, 27, pkg_entry);
|
||||
let arena = Bump::new();
|
||||
let packages = bumpalo::vec![in &arena; loc_pkg_entry];
|
||||
let packages = Collection::with_items(arena.alloc([loc_pkg_entry]));
|
||||
let imports = Vec::new_in(&arena);
|
||||
let provide_entry = Located::new(5, 5, 15, 26, Exposed("mainForHost"));
|
||||
let provides = bumpalo::vec![in &arena; provide_entry];
|
||||
@ -3395,9 +3394,8 @@ mod test_parse {
|
||||
ann: Located::at(
|
||||
region2,
|
||||
TypeAnnotation::Record {
|
||||
fields: &[],
|
||||
fields: Collection::empty(),
|
||||
ext: None,
|
||||
final_comments: &[],
|
||||
},
|
||||
),
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user