Skip to content

Commit

Permalink
perf: Shrink the size of Pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
Marwes committed Mar 20, 2020
1 parent a37d8e6 commit 75fb884
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 64 deletions.
36 changes: 25 additions & 11 deletions base/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,10 +261,15 @@ pub enum Literal {
/// Pattern which contains a location
pub type SpannedPattern<'ast, Id> = Spanned<Pattern<'ast, Id>, BytePos>;

#[derive(Clone, Eq, PartialEq, Debug)]
pub struct PatternField<Id, P> {
pub name: Spanned<Id, BytePos>,
pub value: Option<P>,
#[derive(Eq, PartialEq, Debug)]
pub enum PatternField<'ast, Id> {
Type {
name: Spanned<Id, BytePos>,
},
Value {
name: Spanned<Id, BytePos>,
value: Option<SpannedPattern<'ast, Id>>,
},
}

#[derive(Eq, PartialEq, Debug)]
Expand All @@ -278,8 +283,7 @@ pub enum Pattern<'ast, Id> {
/// Record pattern, eg. `{ x, y = foo }`
Record {
typ: ArcType<Id>,
types: &'ast mut [PatternField<Id, Id>],
fields: &'ast mut [PatternField<Id, SpannedPattern<'ast, Id>>],
fields: &'ast mut [PatternField<'ast, Id>],
implicit_import: Option<Spanned<Id, BytePos>>,
},
/// Tuple pattern, eg: `(x, y)`
Expand All @@ -293,6 +297,10 @@ pub enum Pattern<'ast, Id> {
Error,
}

// Safeguard against growing Pattern
#[cfg(target_pointer_width = "64")]
const _: [u8; 48] = [0; std::mem::size_of::<Pattern<'static, Symbol>>()];

impl<Id> Default for Pattern<'_, Id> {
fn default() -> Self {
Pattern::Error
Expand Down Expand Up @@ -851,9 +859,16 @@ pub fn walk_pattern<'a, 'ast,V: ?Sized + $trait_name<'a, 'ast>>(v: &mut V, p: &'
} => {
v.visit_typ(typ);
for field in &$($mut)* **fields {
v.visit_spanned_ident(&$($mut)* field.name);
if let Some(ref $($mut)* pattern) = field.value {
v.visit_pattern(pattern);
match field {
PatternField::Value { name, value: ref $($mut)* pattern, } => {
v.visit_spanned_ident(name);
if let Some(pattern) = pattern {
v.visit_pattern(pattern);
}
}
PatternField::Type { name, .. } => {
v.visit_spanned_ident(name);
}
}
}
}
Expand Down Expand Up @@ -1198,8 +1213,7 @@ macro_rules! impl_ast_arena {
impl_ast_arena! {
SpannedExpr<'ast, Id> => exprs,
SpannedPattern<'ast, Id> => patterns,
PatternField<Id, Id> => pattern_field_types,
PatternField<Id, SpannedPattern<'ast, Id>> => pattern_field,
PatternField<'ast, Id> => pattern_field,
ExprField<Id, ArcType<Id>> => expr_field_types,
ExprField<Id, SpannedExpr<'ast, Id>> => expr_field_exprs,
TypeBinding<'ast, Id> => type_bindings,
Expand Down
53 changes: 11 additions & 42 deletions parser/src/grammar.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -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, TempVecStart, Slice};
use crate::{Error, ErrorEnv, FieldExpr, MutIdentEnv, TempVecs, TempVecStart, Slice};

grammar<'input, 'env, 'ast, Id>(
input: &'input dyn crate::ParserSource,
Expand Down Expand Up @@ -546,16 +546,16 @@ ArgType: (ArgType, AstType<'ast, Id>) = {

// Patterns

FieldPattern : FieldPattern<'ast, Id> = {
<id: Sp<Ident>> "=" <body: Sp<Pattern>> =>
FieldPattern::Value(id, Some(body)),
PatternField : PatternField<'ast, Id> = {
<name: Sp<Ident>> "=" <body: Sp<Pattern>> =>
PatternField::Value { name, value: Some(body) },

<Sp<IdentStr>> => {
let id = pos::spanned(<>.span, env.from_str(<>.value));
let name = pos::spanned(<>.span, env.from_str(<>.value));
if <>.value.starts_with(char::is_uppercase) {
FieldPattern::Type(id, None)
PatternField::Type { name }
} else {
FieldPattern::Value(id, None)
PatternField::Value { name, value: None }
}
},
};
Expand All @@ -581,47 +581,16 @@ AtomicPattern: Pattern<'ast, Id> = {
_ => Pattern::Tuple { typ: type_cache.hole(), elems },
},

"{" <fields: Comma<FieldPattern>> <implicit_import: Sp<"?"?>> "}" => {
let mut types_len = 0;
let mut values_len = 0;
for field in &fields {
match field {
FieldPattern::Type(..) => types_len += 1,
FieldPattern::Value(..) => values_len += 1,
}
}

let mut types = mem::take(temp_vecs.select());
types.reserve(types_len);
let mut values = mem::take(temp_vecs.select());
values.reserve(values_len);

for field in fields {
match field {
FieldPattern::Type(id, typ) => types.push(PatternField {
name: id,
value: typ
}),
FieldPattern::Value(id, field) => values.push(PatternField {
name: id,
value: field
}),
}
}

"{" <fields: CommaSlice<PatternField>> <implicit_import: Sp<"?"?>> "}" => {
let implicit_import_span = implicit_import.span;

let pattern = Pattern::Record {
Pattern::Record {
typ: type_cache.hole(),
types: arena.alloc_extend(types.drain(..)),
fields: arena.alloc_extend(values.drain(..)),
fields,
implicit_import: implicit_import
.value
.map(|_| pos::spanned(implicit_import_span, env.from_str(&format!("implicit?{}", implicit_import_span.start())))),
};
*temp_vecs.select() = types;
*temp_vecs.select() = values;
pattern
}
},
};

Expand Down
25 changes: 14 additions & 11 deletions parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ use itertools::Either;

use crate::base::{
ast::{
self, AstType, Do, Expr, IdentEnv, RootSpannedExpr, SpannedExpr, SpannedPattern,
TypedIdent, ValueBinding,
self, AstType, Do, Expr, IdentEnv, PatternField, RootSpannedExpr, SpannedExpr,
SpannedPattern, TypedIdent, ValueBinding,
},
error::{AsDiagnostic, Errors},
fnv::FnvMap,
Expand Down Expand Up @@ -232,11 +232,6 @@ impl Error {
}
}

pub enum FieldPattern<'ast, Id> {
Type(Spanned<Id, BytePos>, Option<Id>),
Value(Spanned<Id, BytePos>, Option<SpannedPattern<'ast, Id>>),
}

#[derive(Debug)]
pub enum FieldExpr<'ast, Id> {
Type(Metadata, Spanned<Id, BytePos>, Option<ArcType<Id>>),
Expand Down Expand Up @@ -317,8 +312,7 @@ macro_rules! impl_temp_vec {
impl_temp_vec! {
SpannedExpr<'ast, Id> => exprs,
SpannedPattern<'ast, Id> => patterns,
ast::PatternField<Id, Id> => pattern_field_types,
ast::PatternField<Id, SpannedPattern<'ast, Id>> => pattern_field,
ast::PatternField<'ast, Id> => pattern_field,
ast::ExprField<Id, ArcType<Id>> => expr_field_types,
ast::ExprField<Id, SpannedExpr<'ast, Id>> => expr_field_exprs,
ast::TypeBinding<'ast, Id> => type_bindings,
Expand Down Expand Up @@ -581,8 +575,17 @@ where
self.insert_infix(&id.name, pattern.span);
}
Pattern::Record { ref fields, .. } => {
for field in fields.iter().filter(|field| field.value.is_none()) {
self.insert_infix(&field.name.value, field.name.span);
for name in fields.iter().filter_map(|field| match field {
PatternField::Value { name, value } => {
if value.is_none() {
Some(name)
} else {
None
}
}
PatternField::Type { .. } => None,
}) {
self.insert_infix(&name.value, name.span);
}
}
_ => (),
Expand Down

0 comments on commit 75fb884

Please sign in to comment.