mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 23:31:12 +00:00
Shrink Collection to make parse_expr_size test pass
This commit is contained in:
parent
1fabc64fdf
commit
9bf1674946
8 changed files with 155 additions and 125 deletions
|
@ -1,44 +1,10 @@
|
|||
use crate::header::{AppHeader, ImportsEntry, InterfaceHeader, PlatformHeader, TypedIdent};
|
||||
use crate::ident::Ident;
|
||||
use bumpalo::collections::String;
|
||||
use bumpalo::collections::{String, Vec};
|
||||
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: &[],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = &'a T> {
|
||||
self.items.iter()
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.items.len()
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.items.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Module<'a> {
|
||||
Interface { header: InterfaceHeader<'a> },
|
||||
|
@ -523,6 +489,113 @@ impl<'a> Pattern<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Collection<'a, T> {
|
||||
pub items: &'a [T],
|
||||
// Use a pointer to a slice (rather than just a slice), in order to avoid bloating
|
||||
// Ast variants. The final_comments field is rarely accessed in the hot path, so
|
||||
// this shouldn't matter much for perf.
|
||||
// Use an Option, so it's possible to initialize without allocating.
|
||||
final_comments: Option<&'a &'a [CommentOrNewline<'a>]>,
|
||||
}
|
||||
|
||||
impl<'a, T> Collection<'a, T> {
|
||||
pub fn empty() -> Collection<'a, T> {
|
||||
Collection {
|
||||
items: &[],
|
||||
final_comments: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_items(items: &'a [T]) -> Collection<'a, T> {
|
||||
Collection {
|
||||
items,
|
||||
final_comments: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_items_and_comments(
|
||||
arena: &'a Bump,
|
||||
items: &'a [T],
|
||||
comments: &'a [CommentOrNewline<'a>],
|
||||
) -> Collection<'a, T> {
|
||||
Collection {
|
||||
items,
|
||||
final_comments: if comments.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(arena.alloc(comments))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn replace_items<V>(&self, new_items: &'a [V]) -> Collection<'a, V> {
|
||||
Collection {
|
||||
items: new_items,
|
||||
final_comments: self.final_comments,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ptrify_items(&self, arena: &'a Bump) -> Collection<'a, &'a T> {
|
||||
let mut allocated = Vec::with_capacity_in(self.len(), arena);
|
||||
|
||||
for parsed_elem in self.items {
|
||||
allocated.push(parsed_elem);
|
||||
}
|
||||
|
||||
self.replace_items(allocated.into_bump_slice())
|
||||
}
|
||||
|
||||
pub fn map_items<V: 'a>(&self, arena: &'a Bump, f: impl Fn(&'a T) -> V) -> Collection<'a, V> {
|
||||
let mut allocated = Vec::with_capacity_in(self.len(), arena);
|
||||
|
||||
for parsed_elem in self.items {
|
||||
allocated.push(f(parsed_elem));
|
||||
}
|
||||
|
||||
self.replace_items(allocated.into_bump_slice())
|
||||
}
|
||||
|
||||
pub fn map_items_result<V: 'a, E>(
|
||||
&self,
|
||||
arena: &'a Bump,
|
||||
f: impl Fn(&T) -> Result<V, E>,
|
||||
) -> Result<Collection<'a, V>, E> {
|
||||
let mut allocated = Vec::with_capacity_in(self.len(), arena);
|
||||
|
||||
for parsed_elem in self.items {
|
||||
allocated.push(f(parsed_elem)?);
|
||||
}
|
||||
|
||||
Ok(self.replace_items(allocated.into_bump_slice()))
|
||||
}
|
||||
|
||||
pub fn final_comments(&self) -> &'a [CommentOrNewline<'a>] {
|
||||
if let Some(final_comments) = self.final_comments {
|
||||
*final_comments
|
||||
} else {
|
||||
&[]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = &'a T> {
|
||||
self.items.iter()
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.items.len()
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.items.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: PartialEq> PartialEq for Collection<'a, T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.items == other.items && self.final_comments() == other.final_comments()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Spaceable<'a> {
|
||||
fn before(&'a self, _: &'a [CommentOrNewline<'a>]) -> Self;
|
||||
|
|
|
@ -1449,19 +1449,13 @@ fn expr_to_pattern_help<'a>(arena: &'a Bump, expr: &Expr<'a>) -> Result<Pattern<
|
|||
Expr::ParensAround(sub_expr) => expr_to_pattern_help(arena, sub_expr),
|
||||
|
||||
Expr::Record(fields) => {
|
||||
let mut loc_patterns = Vec::with_capacity_in(fields.len(), arena);
|
||||
|
||||
for loc_assigned_field in fields.iter() {
|
||||
let patterns = fields.map_items_result(arena, |loc_assigned_field| {
|
||||
let region = loc_assigned_field.region;
|
||||
let value = assigned_expr_field_to_pattern_help(arena, &loc_assigned_field.value)?;
|
||||
Ok(Located { region, value })
|
||||
})?;
|
||||
|
||||
loc_patterns.push(Located { region, value });
|
||||
}
|
||||
|
||||
Ok(Pattern::RecordDestructure(Collection {
|
||||
items: loc_patterns.into_bump_slice(),
|
||||
final_comments: fields.final_comments,
|
||||
}))
|
||||
Ok(Pattern::RecordDestructure(patterns))
|
||||
}
|
||||
|
||||
Expr::Float(string) => Ok(Pattern::FloatLiteral(string)),
|
||||
|
@ -2167,16 +2161,8 @@ fn list_literal_help<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>, EList<'a>
|
|||
)
|
||||
.parse(arena, state)?;
|
||||
|
||||
let mut allocated = Vec::with_capacity_in(elements.items.len(), arena);
|
||||
|
||||
for parsed_elem in elements.items {
|
||||
allocated.push(parsed_elem);
|
||||
}
|
||||
|
||||
let expr = Expr::List(Collection {
|
||||
items: allocated.into_bump_slice(),
|
||||
final_comments: elements.final_comments,
|
||||
});
|
||||
let elements = elements.ptrify_items(arena);
|
||||
let expr = Expr::List(elements);
|
||||
|
||||
Ok((MadeProgress, expr, state))
|
||||
}
|
||||
|
@ -2314,15 +2300,17 @@ fn record_literal_help<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>, EExpr<'
|
|||
let mut value = match opt_update {
|
||||
Some(update) => Expr::RecordUpdate {
|
||||
update: &*arena.alloc(update),
|
||||
fields: Collection {
|
||||
items: loc_assigned_fields_with_comments.value.0.into_bump_slice(),
|
||||
final_comments: arena.alloc(loc_assigned_fields_with_comments.value.1),
|
||||
},
|
||||
fields: Collection::with_items_and_comments(
|
||||
arena,
|
||||
loc_assigned_fields_with_comments.value.0.into_bump_slice(),
|
||||
arena.alloc(loc_assigned_fields_with_comments.value.1),
|
||||
),
|
||||
},
|
||||
None => Expr::Record(Collection {
|
||||
items: loc_assigned_fields_with_comments.value.0.into_bump_slice(),
|
||||
final_comments: loc_assigned_fields_with_comments.value.1,
|
||||
}),
|
||||
None => Expr::Record(Collection::with_items_and_comments(
|
||||
arena,
|
||||
loc_assigned_fields_with_comments.value.0.into_bump_slice(),
|
||||
loc_assigned_fields_with_comments.value.1,
|
||||
)),
|
||||
};
|
||||
|
||||
// there can be field access, e.g. `{ x : 4 }.x`
|
||||
|
|
|
@ -1300,10 +1300,10 @@ macro_rules! collection_trailing_sep_e {
|
|||
}
|
||||
}
|
||||
|
||||
let collection = $crate::ast::Collection {
|
||||
items: parsed_elems.into_bump_slice(),
|
||||
final_comments,
|
||||
};
|
||||
let collection = $crate::ast::Collection::with_items_and_comments(
|
||||
arena,
|
||||
parsed_elems.into_bump_slice(),
|
||||
final_comments);
|
||||
|
||||
Ok((MadeProgress, collection, state))
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::ast::{AssignedField, Collection, Tag, TypeAnnotation};
|
||||
use crate::ast::{AssignedField, Tag, TypeAnnotation};
|
||||
use crate::blankspace::{space0_around_ee, space0_before_e, space0_e};
|
||||
use crate::keyword;
|
||||
use crate::parser::{
|
||||
|
@ -291,13 +291,7 @@ fn record_type<'a>(min_indent: u16) -> impl Parser<'a, TypeAnnotation<'a>, EType
|
|||
let field_term = specialize_ref(ETypeRecord::Type, term(min_indent));
|
||||
let (_, ext, state) = optional(allocated(field_term)).parse(arena, state)?;
|
||||
|
||||
let result = Record {
|
||||
fields: Collection {
|
||||
items: fields.items,
|
||||
final_comments: fields.final_comments,
|
||||
},
|
||||
ext,
|
||||
};
|
||||
let result = Record { fields, ext };
|
||||
|
||||
Ok((MadeProgress, result, state))
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue