From dab771379b665ff3a0304371d750708e89801c32 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Sat, 22 Feb 2020 06:10:28 +0200 Subject: [PATCH] Remove HashMap from derive/generate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is a lot of value in outputs produced by compilers being reproducible. Rust makes it somewhat hard to get it right, but most of the time rustc’s outputs are also reproducible. This allows us to enjoy all the benefits as other more primitive toolchains. Most of the time. Pest was, sadly, one of those examples where reproducibility was not a concern and HashMap was used to implement some of the code generation portions. Replacing this `HashMap` with a `Vec` and a `O(nm)` loop is the easy solution. With the values that `n` and `m` get substituted with in practice, however, this loop should still be approximately as good as the previous `HashMap` implementation. --- generator/src/generator.rs | 18 +++++++++++------- generator/src/macros.rs | 4 ++-- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/generator/src/generator.rs b/generator/src/generator.rs index 24ad2775..c8c73b59 100644 --- a/generator/src/generator.rs +++ b/generator/src/generator.rs @@ -7,7 +7,6 @@ // option. All files in the project carrying such notice may not be copied, // modified, or distributed except according to those terms. -use std::collections::HashMap; use std::path::PathBuf; use proc_macro2::{Span, TokenStream}; @@ -43,7 +42,13 @@ pub fn generate( let skip = generate_skip(&rules); let mut rules: Vec<_> = rules.into_iter().map(generate_rule).collect(); - rules.extend(defaults.into_iter().map(|name| builtins[name].clone())); + rules.extend(builtins.into_iter().filter_map(|(builtin, tokens)| { + if defaults.contains(&builtin) { + Some(tokens) + } else { + None + } + })); let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); @@ -89,8 +94,8 @@ pub fn generate( // Note: All builtin rules should be validated as pest builtins in meta/src/validator.rs. // Some should also be keywords. -fn generate_builtin_rules() -> HashMap<&'static str, TokenStream> { - let mut builtins = HashMap::new(); +fn generate_builtin_rules() -> Vec<(&'static str, TokenStream)> { + let mut builtins = Vec::new(); insert_builtin!(builtins, ANY, state.skip(1)); insert_public_builtin!( @@ -147,15 +152,14 @@ fn generate_builtin_rules() -> HashMap<&'static str, TokenStream> { for property in UNICODE_PROPERTY_NAMES { let property_ident: Ident = syn::parse_str(property).unwrap(); // insert manually for #property substitution - builtins.insert(property, quote! { + builtins.push((property, quote! { #[inline] #[allow(dead_code, non_snake_case, unused_variables)] fn #property_ident(state: Box<::pest::ParserState>) -> ::pest::ParseResult>> { state.match_char_by(::pest::unicode::#property_ident) } - }); + })); } - builtins } diff --git a/generator/src/macros.rs b/generator/src/macros.rs index e424b322..9d02725d 100644 --- a/generator/src/macros.rs +++ b/generator/src/macros.rs @@ -9,13 +9,13 @@ macro_rules! insert_builtin { ($builtin: expr, $name: ident, $pattern: expr) => { - $builtin.insert(stringify!($name), generate_rule!($name, $pattern)); + $builtin.push((stringify!($name), generate_rule!($name, $pattern))); }; } macro_rules! insert_public_builtin { ($builtin: expr, $name: ident, $pattern: expr) => { - $builtin.insert(stringify!($name), generate_public_rule!($name, $pattern)); + $builtin.push((stringify!($name), generate_public_rule!($name, $pattern))); }; }