Merge variables in Stmt::Share.

This commit is contained in:
Stephen Chung 2022-10-29 15:17:12 +08:00
parent 91415b9750
commit d97f3f7ec4
3 changed files with 30 additions and 29 deletions

View File

@ -605,19 +605,16 @@ pub enum Stmt {
/// Not available under `no_module`. /// Not available under `no_module`.
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
Export(Box<(Ident, Ident)>, Position), Export(Box<(Ident, Ident)>, Position),
/// Convert a variable to shared. /// Convert a list of variables to shared.
/// ///
/// Not available under `no_closure`. /// Not available under `no_closure`.
/// ///
/// # Notes /// # Notes
/// ///
/// This variant does not map to any language structure. It is currently only used only to /// 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"))] #[cfg(not(feature = "no_closure"))]
Share( Share(Box<crate::FnArgsVec<(crate::ImmutableString, Option<NonZeroUsize>, Position)>>),
Box<(crate::ImmutableString, Option<NonZeroUsize>)>,
Position,
),
} }
impl Default for Stmt { impl Default for Stmt {
@ -684,7 +681,7 @@ impl Stmt {
Self::Export(.., pos) => *pos, Self::Export(.., pos) => *pos,
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Self::Share(.., pos) => *pos, Self::Share(x) => x[0].2,
} }
} }
/// Override the [position][Position] of this statement. /// Override the [position][Position] of this statement.
@ -716,7 +713,7 @@ impl Stmt {
Self::Export(.., pos) => *pos = new_pos, Self::Export(.., pos) => *pos = new_pos,
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Self::Share(.., pos) => *pos = new_pos, Self::Share(x) => x.iter_mut().for_each(|(_, _, pos)| *pos = new_pos),
} }
self self

View File

@ -977,23 +977,25 @@ impl Engine {
// Share statement // Share statement
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Stmt::Share(x, pos) => { Stmt::Share(x) => {
let (name, index) = &**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 if !val.is_shared() {
.map(|n| scope.len() - n.get()) // Replace the variable with a shared value.
.or_else(|| scope.search(name)) *val = std::mem::take(val).into_shared();
{ }
let val = scope.get_mut_by_index(index); Ok(())
} else {
if !val.is_shared() { Err(ERR::ErrorVariableNotFound(name.to_string(), *pos).into())
// Replace the variable with a shared value. }
*val = std::mem::take(val).into_shared(); })
} .map(|_| Dynamic::UNIT)
Ok(Dynamic::UNIT)
} else {
Err(ERR::ErrorVariableNotFound(name.to_string(), *pos).into())
}
} }
_ => unreachable!("statement cannot be evaluated: {:?}", stmt), _ => unreachable!("statement cannot be evaluated: {:?}", stmt),

View File

@ -3739,15 +3739,17 @@ impl Engine {
// Convert the entire expression into a statement block, then insert the relevant // Convert the entire expression into a statement block, then insert the relevant
// [`Share`][Stmt::Share] statements. // [`Share`][Stmt::Share] statements.
let mut statements = StaticVec::with_capacity(externals.len() + 1); let mut statements = StaticVec::with_capacity(2);
statements.extend( statements.push(Stmt::Share(
externals externals
.into_iter() .into_iter()
.map(|crate::ast::Ident { name, pos }| { .map(|crate::ast::Ident { name, pos }| {
let (index, _) = parent.access_var(&name, lib, pos); let (index, _) = parent.access_var(&name, lib, pos);
Stmt::Share((name, index).into(), pos) (name, index, pos)
}), })
); .collect::<crate::FnArgsVec<_>>()
.into(),
));
statements.push(Stmt::Expr(expr.into())); statements.push(Stmt::Expr(expr.into()));
Expr::Stmt(crate::ast::StmtBlock::new(statements, pos, Position::NONE).into()) Expr::Stmt(crate::ast::StmtBlock::new(statements, pos, Position::NONE).into())
} }