diff --git a/src/ast/expr.rs b/src/ast/expr.rs index 94e5b482..12632325 100644 --- a/src/ast/expr.rs +++ b/src/ast/expr.rs @@ -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() diff --git a/src/ast/stmt.rs b/src/ast/stmt.rs index 93e50190..97cf1eb0 100644 --- a/src/ast/stmt.rs +++ b/src/ast/stmt.rs @@ -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 diff --git a/src/eval/stmt.rs b/src/eval/stmt.rs index a06bb742..5aa179eb 100644 --- a/src/eval/stmt.rs +++ b/src/eval/stmt.rs @@ -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) } diff --git a/src/parser.rs b/src/parser.rs index e9b114d7..b2f95d93 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -3226,7 +3226,7 @@ fn parse_fn( fn make_curry_from_externals( state: &mut ParseState, fn_expr: Expr, - externals: StaticVec, + externals: StaticVec, 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| { - Expr::Variable( - None, - Position::NONE, - ( - None, - #[cfg(not(feature = "no_module"))] - None, - #[cfg(feature = "no_module")] - (), - x, - ) - .into(), - ) - })); + args.extend( + externals + .iter() + .cloned() + .map(|crate::ast::Ident { name, pos }| { + Expr::Variable( + None, + pos, + ( + None, + #[cfg(not(feature = "no_module"))] + None, + #[cfg(feature = "no_module")] + (), + 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 = 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) };