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`.
#[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<NonZeroUsize>)>,
Position,
),
Share(Box<crate::FnArgsVec<(crate::ImmutableString, Option<NonZeroUsize>, 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

View File

@ -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),

View File

@ -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::<crate::FnArgsVec<_>>()
.into(),
));
statements.push(Stmt::Expr(expr.into()));
Expr::Stmt(crate::ast::StmtBlock::new(statements, pos, Position::NONE).into())
}