From d97f3f7ec44b31b8321077de30d0ee00a6924f62 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sat, 29 Oct 2022 15:17:12 +0800 Subject: [PATCH] Merge variables in Stmt::Share. --- src/ast/stmt.rs | 13 +++++-------- src/eval/stmt.rs | 34 ++++++++++++++++++---------------- src/parser.rs | 12 +++++++----- 3 files changed, 30 insertions(+), 29 deletions(-) diff --git a/src/ast/stmt.rs b/src/ast/stmt.rs index ed6c51a3..e272e1e9 100644 --- a/src/ast/stmt.rs +++ b/src/ast/stmt.rs @@ -605,19 +605,16 @@ pub enum Stmt { /// Not available under `no_module`. #[cfg(not(feature = "no_module"))] Export(Box<(Ident, Ident)>, Position), - /// Convert a variable to shared. + /// Convert a list of variables to shared. /// /// Not available under `no_closure`. /// /// # Notes /// /// This variant does not map to any language structure. It is currently only used only to - /// convert a normal variable into a shared variable when the variable is _captured_ by a closure. + /// convert normal variables into shared variables when they are _captured_ by a closure. #[cfg(not(feature = "no_closure"))] - Share( - Box<(crate::ImmutableString, Option)>, - Position, - ), + Share(Box, Position)>>), } impl Default for Stmt { @@ -684,7 +681,7 @@ impl Stmt { Self::Export(.., pos) => *pos, #[cfg(not(feature = "no_closure"))] - Self::Share(.., pos) => *pos, + Self::Share(x) => x[0].2, } } /// Override the [position][Position] of this statement. @@ -716,7 +713,7 @@ impl Stmt { Self::Export(.., pos) => *pos = new_pos, #[cfg(not(feature = "no_closure"))] - Self::Share(.., pos) => *pos = new_pos, + Self::Share(x) => x.iter_mut().for_each(|(_, _, pos)| *pos = new_pos), } self diff --git a/src/eval/stmt.rs b/src/eval/stmt.rs index 4eecbf88..0a302ee6 100644 --- a/src/eval/stmt.rs +++ b/src/eval/stmt.rs @@ -977,23 +977,25 @@ impl Engine { // Share statement #[cfg(not(feature = "no_closure"))] - Stmt::Share(x, pos) => { - let (name, index) = &**x; + Stmt::Share(x) => { + x.iter() + .try_for_each(|(name, index, pos)| { + if let Some(index) = index + .map(|n| scope.len() - n.get()) + .or_else(|| scope.search(name)) + { + let val = scope.get_mut_by_index(index); - if let Some(index) = index - .map(|n| scope.len() - n.get()) - .or_else(|| scope.search(name)) - { - let val = scope.get_mut_by_index(index); - - if !val.is_shared() { - // Replace the variable with a shared value. - *val = std::mem::take(val).into_shared(); - } - Ok(Dynamic::UNIT) - } else { - Err(ERR::ErrorVariableNotFound(name.to_string(), *pos).into()) - } + if !val.is_shared() { + // Replace the variable with a shared value. + *val = std::mem::take(val).into_shared(); + } + Ok(()) + } else { + Err(ERR::ErrorVariableNotFound(name.to_string(), *pos).into()) + } + }) + .map(|_| Dynamic::UNIT) } _ => unreachable!("statement cannot be evaluated: {:?}", stmt), diff --git a/src/parser.rs b/src/parser.rs index 9ca3a8a0..c2e02aa7 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -3739,15 +3739,17 @@ impl Engine { // Convert the entire expression into a statement block, then insert the relevant // [`Share`][Stmt::Share] statements. - let mut statements = StaticVec::with_capacity(externals.len() + 1); - statements.extend( + let mut statements = StaticVec::with_capacity(2); + statements.push(Stmt::Share( externals .into_iter() .map(|crate::ast::Ident { name, pos }| { let (index, _) = parent.access_var(&name, lib, pos); - Stmt::Share((name, index).into(), pos) - }), - ); + (name, index, pos) + }) + .collect::>() + .into(), + )); statements.push(Stmt::Expr(expr.into())); Expr::Stmt(crate::ast::StmtBlock::new(statements, pos, Position::NONE).into()) }