diff --git a/parser/src/grammar.lalrpop b/parser/src/grammar.lalrpop index ae580789a8..8f4530df84 100644 --- a/parser/src/grammar.lalrpop +++ b/parser/src/grammar.lalrpop @@ -15,7 +15,7 @@ use crate::{ReplLine, Variant, new_ident}; use crate::token::{Token, StringLiteral}; use crate::ordered_float::NotNan; -use crate::{Error, ErrorEnv, FieldExpr, FieldPattern, MutIdentEnv, TempVecs, Slice}; +use crate::{Error, ErrorEnv, FieldExpr, FieldPattern, MutIdentEnv, TempVecs, TempVecStart, Slice}; grammar<'input, 'env, 'ast, Id>( input: &'input dyn crate::ParserSource, @@ -102,11 +102,8 @@ Comma: Vec = { #[inline] SepSlice: &'ast mut Slice = - Separator)>> => { - rules.extend(last); - let slice = arena.alloc_extend(rules.drain(..)); - temp_vecs.push(rules); - slice + Separator)>> => { + arena.alloc_extend(temp_vecs.drain(start).chain(last)) }; #[inline] @@ -123,21 +120,21 @@ IdentStr: &'input str = { "(" <"operator"> ")" => <>, }; -Many1Vec: Vec = { +Many1Vec: TempVecStart = { T => { - let mut v = temp_vecs.pop(); - v.push(<>); - v + let start = temp_vecs.start(); + temp_vecs.select().push(<>); + start }, - > => { - xs.push(x); - xs + > => { + temp_vecs.select().push(x); + start } }; #[inline] -ManyVec: Vec = { - => Vec::new(), +ManyVec: TempVecStart = { + => temp_vecs.start(), Many1Vec, }; @@ -150,10 +147,8 @@ Many: &'ast mut Slice = { #[inline] Many1: &'ast mut Slice = { Many1Vec => { - let mut xs = <>; - let slice = arena.alloc_extend(xs.drain(..)); - temp_vecs.push(xs); - slice + let start = <>; + arena.alloc_extend(temp_vecs.drain(start)) } }; @@ -552,9 +547,9 @@ AtomicPattern: Pattern<'ast, Id> = { } } - let mut types = temp_vecs.pop(); + let mut types = mem::take(temp_vecs.select()); types.reserve(types_len); - let mut values = temp_vecs.pop(); + let mut values = mem::take(temp_vecs.select()); values.reserve(values_len); for field in fields { @@ -580,8 +575,8 @@ AtomicPattern: Pattern<'ast, Id> = { .value .map(|_| pos::spanned(implicit_import_span, env.from_str(&format!("implicit?{}", implicit_import_span.start())))), }; - temp_vecs.push(types); - temp_vecs.push(values); + *temp_vecs.select() = types; + *temp_vecs.select() = values; pattern }, }; @@ -767,9 +762,9 @@ AtomicExpr: Expr<'ast, Id> = { } } - let mut types = temp_vecs.pop(); + let mut types = mem::take(temp_vecs.select()); types.reserve(types_len); - let mut values = temp_vecs.pop(); + let mut values = mem::take(temp_vecs.select()); values.reserve(values_len); for field in fields { @@ -793,8 +788,8 @@ AtomicExpr: Expr<'ast, Id> = { exprs: arena.alloc_extend(values.drain(..)), base: base.map(|e| arena.alloc(e)), }; - temp_vecs.push(types); - temp_vecs.push(values); + *temp_vecs.select() = types; + *temp_vecs.select() = values; expr }, }; diff --git a/parser/src/lib.rs b/parser/src/lib.rs index b056a8d275..6bdecfefcc 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -21,7 +21,7 @@ extern crate quick_error; #[macro_use] extern crate pretty_assertions; -use std::{fmt, hash::Hash, sync::Arc}; +use std::{fmt, hash::Hash, marker::PhantomData, sync::Arc}; use crate::base::{ ast::{ @@ -253,7 +253,7 @@ type ErrorEnv<'err, 'input> = &'err mut Errors>; type Slice = [T]; trait TempVec<'ast, Id>: Sized { - fn select<'a>(vecs: &'a mut TempVecs<'ast, Id>) -> &'a mut Vec>; + fn select<'a>(vecs: &'a mut TempVecs<'ast, Id>) -> &'a mut Vec; } macro_rules! impl_temp_vec { @@ -261,10 +261,13 @@ macro_rules! impl_temp_vec { #[doc(hidden)] pub struct TempVecs<'ast, Id> { $( - $field: Vec>, + $field: Vec<$ty>, )* } + #[doc(hidden)] + pub struct TempVecStart(usize, PhantomData); + impl<'ast, Id> TempVecs<'ast, Id> { fn new() -> Self { TempVecs { @@ -274,24 +277,31 @@ macro_rules! impl_temp_vec { } } - fn push(&mut self, exprs: Vec) + fn start(&mut self) -> TempVecStart where T: TempVec<'ast, Id>, { - T::select(self).push(exprs); + TempVecStart(T::select(self).len(), PhantomData) } - fn pop(&mut self) -> Vec + fn select(&mut self) -> &mut Vec where T: TempVec<'ast, Id>, { - T::select(self).pop().unwrap_or_default() + T::select(self) + } + + fn drain<'a, T>(&'a mut self, start: TempVecStart) -> impl Iterator + 'a + where + T: TempVec<'ast, Id> + 'a, + { + T::select(self).drain(start.0..) } } $( impl<'ast, Id> TempVec<'ast, Id> for $ty { - fn select<'a>(vecs: &'a mut TempVecs<'ast, Id>) -> &'a mut Vec> { + fn select<'a>(vecs: &'a mut TempVecs<'ast, Id>) -> &'a mut Vec { &mut vecs.$field } }