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(")") f.write_str(")")
} }
Self::Property(x, ..) => write!(f, "Property({})", x.2), 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) => { Self::Stmt(x) => {
f.write_str("ExprStmtBlock")?; f.write_str("ExprStmtBlock")?;
f.debug_list().entries(x.iter()).finish() 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 /// 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 a normal variable into a shared variable when the variable is _captured_ by a closure.
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Share(crate::Identifier), Share(crate::Identifier, Position),
} }
impl Default for Stmt { impl Default for Stmt {
@ -427,7 +427,7 @@ impl Stmt {
Self::Export(.., pos) => *pos, Self::Export(.., pos) => *pos,
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Self::Share(..) => Position::NONE, Self::Share(.., pos) => *pos,
} }
} }
/// Override the [position][Position] of this statement. /// Override the [position][Position] of this statement.
@ -458,7 +458,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(..) => (), Self::Share(.., pos) => *pos = new_pos,
} }
self self

View File

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

View File

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