Add position info for closures.

This commit is contained in:
Stephen Chung 2022-02-09 13:40:51 +08:00
parent 340a047369
commit e5a673b3ae
4 changed files with 39 additions and 28 deletions

View File

@ -480,7 +480,7 @@ impl fmt::Debug for Expr {
f.write_str(")")
}
Self::Property(x, ..) => write!(f, "Property({})", x.2),
Self::Stack(x, ..) => write!(f, "ConstantArg#{}", x),
Self::Stack(x, ..) => write!(f, "ConstantArg[{}]", x),
Self::Stmt(x) => {
f.write_str("ExprStmtBlock")?;
f.debug_list().entries(x.iter()).finish()

View File

@ -376,7 +376,7 @@ pub enum Stmt {
/// 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.
#[cfg(not(feature = "no_closure"))]
Share(crate::Identifier),
Share(crate::Identifier, Position),
}
impl Default for Stmt {
@ -427,7 +427,7 @@ impl Stmt {
Self::Export(.., pos) => *pos,
#[cfg(not(feature = "no_closure"))]
Self::Share(..) => Position::NONE,
Self::Share(.., pos) => *pos,
}
}
/// Override the [position][Position] of this statement.
@ -458,7 +458,7 @@ impl Stmt {
Self::Export(.., pos) => *pos = new_pos,
#[cfg(not(feature = "no_closure"))]
Self::Share(..) => (),
Self::Share(.., pos) => *pos = new_pos,
}
self

View File

@ -977,7 +977,7 @@ impl Engine {
// Share statement
#[cfg(not(feature = "no_closure"))]
Stmt::Share(name) => {
Stmt::Share(name, ..) => {
if let Some((index, ..)) = scope.get_index(name) {
let val = scope.get_mut_by_index(index);
@ -985,6 +985,8 @@ impl Engine {
// Replace the variable with a shared value.
*val = std::mem::take(val).into_shared();
}
} else {
unreachable!("variable {} not found for sharing", name);
}
Ok(Dynamic::UNIT)
}

View File

@ -3226,7 +3226,7 @@ fn parse_fn(
fn make_curry_from_externals(
state: &mut ParseState,
fn_expr: Expr,
externals: StaticVec<Identifier>,
externals: StaticVec<crate::ast::Ident>,
pos: Position,
) -> Expr {
// If there are no captured variables, no need to curry
@ -3239,21 +3239,26 @@ fn make_curry_from_externals(
args.push(fn_expr);
args.extend(externals.iter().cloned().map(|x| {
args.extend(
externals
.iter()
.cloned()
.map(|crate::ast::Ident { name, pos }| {
Expr::Variable(
None,
Position::NONE,
pos,
(
None,
#[cfg(not(feature = "no_module"))]
None,
#[cfg(feature = "no_module")]
(),
x,
name,
)
.into(),
)
}));
}),
);
let expr = FnCallExpr {
name: state.get_identifier("", crate::engine::KEYWORD_FN_PTR_CURRY),
@ -3270,7 +3275,11 @@ fn make_curry_from_externals(
// 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(externals.into_iter().map(Stmt::Share));
statements.extend(
externals
.into_iter()
.map(|crate::ast::Ident { name, pos }| Stmt::Share(name, pos)),
);
statements.push(Stmt::Expr(expr));
Expr::Stmt(crate::ast::StmtBlock::new(statements, pos, Position::NONE).into())
}
@ -3336,14 +3345,14 @@ fn parse_anon_fn(
// so extract them into a list.
#[cfg(not(feature = "no_closure"))]
let (mut params, externals) = {
let externals: StaticVec<Identifier> = state
.external_vars
.iter()
.map(|crate::ast::Ident { name, .. }| name.clone())
.collect();
let externals: StaticVec<_> = state.external_vars.iter().cloned().collect();
let mut params = StaticVec::with_capacity(params_list.len() + externals.len());
params.extend(externals.iter().cloned());
params.extend(
externals
.iter()
.map(|crate::ast::Ident { name, .. }| name.clone()),
);
(params, externals)
};