From 26ad454cb1036dc0f7baac12f1fb07cf5c0f0896 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Mon, 10 Apr 2023 18:47:53 +0800 Subject: [PATCH] Streamline data types. --- src/ast/stmt.rs | 6 +++--- src/eval/stmt.rs | 8 +++++--- src/module/mod.rs | 20 +++++++++++++++---- src/optimizer.rs | 50 ++++++++++++++++------------------------------ src/parser.rs | 6 +++--- tests/optimizer.rs | 2 -- 6 files changed, 44 insertions(+), 48 deletions(-) diff --git a/src/ast/stmt.rs b/src/ast/stmt.rs index 65634092..79db87b2 100644 --- a/src/ast/stmt.rs +++ b/src/ast/stmt.rs @@ -721,7 +721,7 @@ pub enum Stmt { /// This variant does not map to any language structure. It is currently only used only to /// convert normal variables into shared variables when they are _captured_ by a closure. #[cfg(not(feature = "no_closure"))] - Share(Box, Position)>>), + Share(Box)>>), } impl Default for Stmt { @@ -816,7 +816,7 @@ impl Stmt { Self::Export(.., pos) => *pos, #[cfg(not(feature = "no_closure"))] - Self::Share(x) => x[0].2, + Self::Share(x) => x[0].0.pos, } } /// Override the [position][Position] of this statement. @@ -848,7 +848,7 @@ impl Stmt { Self::Export(.., pos) => *pos = new_pos, #[cfg(not(feature = "no_closure"))] - Self::Share(x) => x.iter_mut().for_each(|(_, _, pos)| *pos = new_pos), + Self::Share(x) => x.iter_mut().for_each(|(x, _)| x.pos = new_pos), } self diff --git a/src/eval/stmt.rs b/src/eval/stmt.rs index 5d090b76..29ded4a1 100644 --- a/src/eval/stmt.rs +++ b/src/eval/stmt.rs @@ -927,10 +927,10 @@ impl Engine { // Share statement #[cfg(not(feature = "no_closure"))] Stmt::Share(x) => { - for (name, index, pos) in &**x { + for (var, index) in &**x { if let Some(index) = index .map(|n| scope.len() - n.get()) - .or_else(|| scope.search(name)) + .or_else(|| scope.search(&var.name)) { let val = scope.get_mut_by_index(index); @@ -939,7 +939,9 @@ impl Engine { *val = std::mem::take(val).into_shared(); } } else { - return Err(ERR::ErrorVariableNotFound(name.to_string(), *pos).into()); + return Err( + ERR::ErrorVariableNotFound(var.name.to_string(), var.pos).into() + ); } } diff --git a/src/module/mod.rs b/src/module/mod.rs index 26dbca16..6e7fe262 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -1986,23 +1986,35 @@ impl Module { } /// Get an iterator to the sub-modules in the [`Module`]. - #[inline] + #[inline(always)] pub fn iter_sub_modules(&self) -> impl Iterator { + self.iter_sub_modules_raw().map(|(k, m)| (k.as_str(), m)) + } + /// Get an iterator to the sub-modules in the [`Module`]. + #[inline] + pub(crate) fn iter_sub_modules_raw( + &self, + ) -> impl Iterator { self.modules .as_ref() .into_iter() .flatten() - .map(|(k, m)| (k.as_str(), m)) + .map(|(k, m)| (k, m)) } /// Get an iterator to the variables in the [`Module`]. - #[inline] + #[inline(always)] pub fn iter_var(&self) -> impl Iterator { + self.iter_var_raw().map(|(k, v)| (k.as_str(), v)) + } + /// Get an iterator to the variables in the [`Module`]. + #[inline] + pub(crate) fn iter_var_raw(&self) -> impl Iterator { self.variables .as_ref() .into_iter() .flatten() - .map(|(k, v)| (k.as_str(), v)) + .map(|(k, v)| (k, v)) } /// Get an iterator to the functions in the [`Module`]. diff --git a/src/optimizer.rs b/src/optimizer.rs index 80e9d5e0..5300fd0c 100644 --- a/src/optimizer.rs +++ b/src/optimizer.rs @@ -14,10 +14,9 @@ use crate::func::builtin::get_builtin_binary_op_fn; use crate::func::hashing::get_hasher; use crate::module::ModuleFlags; use crate::tokenizer::Token; -use crate::types::dynamic::AccessMode; use crate::{ - calc_fn_hash, calc_fn_hash_full, Dynamic, Engine, FnPtr, Identifier, ImmutableString, Position, - Scope, StaticVec, AST, + calc_fn_hash, calc_fn_hash_full, Dynamic, Engine, FnPtr, ImmutableString, Position, Scope, + StaticVec, AST, }; #[cfg(feature = "no_std")] use std::prelude::v1::*; @@ -54,8 +53,8 @@ impl Default for OptimizationLevel { struct OptimizerState<'a> { /// Has the [`AST`] been changed during this pass? changed: bool, - /// Collection of constants to use for eager function evaluations. - variables: StaticVec<(Identifier, AccessMode, Option)>, + /// Collection of variables/constants to use for eager function evaluations. + variables: StaticVec<(ImmutableString, Option)>, /// Activate constants propagation? propagate_constants: bool, /// An [`Engine`] instance for eager function evaluation. @@ -115,14 +114,11 @@ impl<'a> OptimizerState<'a> { self.variables.truncate(len); } /// Add a new variable to the list. + /// + /// `Some(value)` if constant, `None` or otherwise. #[inline(always)] - pub fn push_var( - &mut self, - name: impl Into, - access: AccessMode, - value: Option, - ) { - self.variables.push((name.into(), access, value)); + pub fn push_var(&mut self, name: ImmutableString, value: Option) { + self.variables.push((name, value)); } /// Look up a constant from the list. #[inline] @@ -131,12 +127,9 @@ impl<'a> OptimizerState<'a> { return None; } - for (n, access, value) in self.variables.iter().rev() { - if n == name { - return match access { - AccessMode::ReadWrite => None, - AccessMode::ReadOnly => value.as_ref(), - }; + for (n, value) in self.variables.iter().rev() { + if n.as_str() == name { + return value.as_ref(); } } @@ -237,16 +230,13 @@ fn optimize_stmt_block( optimize_expr(&mut x.1, state, false); if x.1.is_constant() { - state.push_var( - x.0.as_str(), - AccessMode::ReadOnly, - x.1.get_literal_value(), - ); + state + .push_var(x.0.name.clone(), Some(x.1.get_literal_value().unwrap())); } } else { // Add variables into the state optimize_expr(&mut x.1, state, false); - state.push_var(x.0.as_str(), AccessMode::ReadWrite, None); + state.push_var(x.0.name.clone(), None); } } // Optimize the statement @@ -858,7 +848,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b #[cfg(not(feature = "no_closure"))] Stmt::Share(x) => { let len = x.len(); - x.retain(|(v, _, _)| !state.find_constant(v).is_some()); + x.retain(|(v, _)| !state.find_constant(v).is_some()); if x.len() != len { state.set_dirty(); } @@ -1335,20 +1325,14 @@ impl Engine { .iter() .rev() .flat_map(|m| m.iter_var()) - .for_each(|(name, value)| { - state.push_var(name, AccessMode::ReadOnly, Some(value.clone())) - }); + .for_each(|(name, value)| state.push_var(name.into(), Some(value.clone()))); // Add constants and variables from the scope scope .into_iter() .flat_map(Scope::iter) .for_each(|(name, constant, value)| { - if constant { - state.push_var(name, AccessMode::ReadOnly, Some(value)); - } else { - state.push_var(name, AccessMode::ReadWrite, None); - } + state.push_var(name.into(), if constant { Some(value) } else { None }); }); optimize_stmt_block(statements, &mut state, true, false, true) diff --git a/src/parser.rs b/src/parser.rs index 2300b402..00fd7240 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -3781,9 +3781,9 @@ impl Engine { statements.push(Stmt::Share( externals .into_iter() - .map(|Ident { name, pos }| { - let (index, _) = parent.access_var(&name, lib, pos); - (name, index, pos) + .map(|var| { + let (index, _) = parent.access_var(&var.name, lib, var.pos); + (var, index) }) .collect::>() .into(), diff --git a/tests/optimizer.rs b/tests/optimizer.rs index 80b8ccf1..780eb771 100644 --- a/tests/optimizer.rs +++ b/tests/optimizer.rs @@ -182,8 +182,6 @@ fn test_optimizer_reoptimize() -> Result<(), Box> { let scope: Scope = ast.iter_literal_variables(true, false).collect(); let ast = engine.optimize_ast(&scope, ast, OptimizationLevel::Simple); - println!("{ast:#?}"); - assert_eq!(engine.eval_ast::(&ast)?, 84); Ok(())