From 5443368359782eec1ce46d379698ad3949479a1a Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sat, 12 Dec 2020 11:15:09 +0800 Subject: [PATCH] Pass Position into function calls. --- src/engine.rs | 77 +++++++++++++++++++++-------------------------- src/engine_api.rs | 12 +++++++- src/fn_call.rs | 73 +++++++++++++++++++++++--------------------- src/fn_native.rs | 1 + src/optimize.rs | 1 + 5 files changed, 86 insertions(+), 78 deletions(-) diff --git a/src/engine.rs b/src/engine.rs index b3314482..38a62918 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -1016,8 +1016,8 @@ impl Engine { let args = &mut [target_val, &mut idx_val2, &mut new_val.0]; self.exec_fn_call( - mods, state, lib, FN_IDX_SET, 0, args, is_ref, true, false, None, - None, level, + mods, state, lib, FN_IDX_SET, 0, args, is_ref, true, false, + new_val.1, None, None, level, ) .map_err(|err| match *err { EvalAltResult::ErrorFunctionNotFound(fn_sig, _) @@ -1061,9 +1061,8 @@ impl Engine { let args = idx_val.as_fn_call_args(); self.make_method_call( mods, state, lib, name, *hash, target, args, def_value, *native, false, - level, + *pos, level, ) - .map_err(|err| err.fill_position(*pos)) } // xxx.module::fn_name(...) - syntax error Expr::FnCall(_, _) => unreachable!(), @@ -1094,8 +1093,8 @@ impl Engine { let mut new_val = new_val; let mut args = [target_val, &mut new_val.as_mut().unwrap().0]; self.exec_fn_call( - mods, state, lib, setter, 0, &mut args, is_ref, true, false, None, - None, level, + mods, state, lib, setter, 0, &mut args, is_ref, true, false, *pos, + None, None, level, ) .map(|(v, _)| (v, true)) .map_err(|err| err.fill_position(*pos)) @@ -1105,8 +1104,8 @@ impl Engine { let ((getter, _), IdentX { pos, .. }) = x.as_ref(); let mut args = [target_val]; self.exec_fn_call( - mods, state, lib, getter, 0, &mut args, is_ref, true, false, None, - None, level, + mods, state, lib, getter, 0, &mut args, is_ref, true, false, *pos, + None, None, level, ) .map(|(v, _)| (v, false)) .map_err(|err| err.fill_position(*pos)) @@ -1133,12 +1132,10 @@ impl Engine { } = x.as_ref(); let def_value = def_value.as_ref(); let args = idx_val.as_fn_call_args(); - let (val, _) = self - .make_method_call( - mods, state, lib, name, *hash, target, args, def_value, - *native, false, level, - ) - .map_err(|err| err.fill_position(*pos))?; + let (val, _) = self.make_method_call( + mods, state, lib, name, *hash, target, args, def_value, + *native, false, *pos, level, + )?; val.into() } // {xxx:map}.module::fn_name(...) - syntax error @@ -1164,7 +1161,7 @@ impl Engine { let (mut val, updated) = self .exec_fn_call( mods, state, lib, getter, 0, args, is_ref, true, false, - None, None, level, + *pos, None, None, level, ) .map_err(|err| err.fill_position(*pos))?; @@ -1191,7 +1188,7 @@ impl Engine { arg_values[1] = val; self.exec_fn_call( mods, state, lib, setter, 0, arg_values, is_ref, true, - false, None, None, level, + false, *pos, None, None, level, ) .or_else( |err| match *err { @@ -1217,12 +1214,10 @@ impl Engine { } = f.as_ref(); let def_value = def_value.as_ref(); let args = idx_val.as_fn_call_args(); - let (mut val, _) = self - .make_method_call( - mods, state, lib, name, *hash, target, args, def_value, - *native, false, level, - ) - .map_err(|err| err.fill_position(*pos))?; + let (mut val, _) = self.make_method_call( + mods, state, lib, name, *hash, target, args, def_value, + *native, false, *pos, level, + )?; let val = &mut val; let target = &mut val.into(); @@ -1475,8 +1470,8 @@ impl Engine { let mut idx = idx; let args = &mut [target, &mut idx]; self.exec_fn_call( - _mods, state, _lib, FN_IDX_GET, 0, args, _is_ref, true, false, None, None, - _level, + _mods, state, _lib, FN_IDX_GET, 0, args, _is_ref, true, false, idx_pos, None, + None, _level, ) .map(|(v, _)| v.into()) .map_err(|err| match *err { @@ -1530,11 +1525,12 @@ impl Engine { let hash = calc_native_fn_hash(empty(), OP_EQUALS, args.iter().map(|a| a.type_id())); + let pos = rhs.position(); + if self .call_native_fn( - mods, state, lib, OP_EQUALS, hash, args, false, false, def_value, - ) - .map_err(|err| err.fill_position(rhs.position()))? + mods, state, lib, OP_EQUALS, hash, args, false, false, pos, def_value, + )? .0 .as_bool() .unwrap_or(false) @@ -1654,11 +1650,10 @@ impl Engine { let ((getter, _), IdentX { pos, .. }) = p.as_ref(); let mut args = [target.as_mut()]; self.exec_fn_call( - mods, state, lib, getter, 0, &mut args, is_ref, true, false, None, - None, level, + mods, state, lib, getter, 0, &mut args, is_ref, true, false, *pos, + None, None, level, ) .map(|(v, _)| (v.into(), *pos)) - .map_err(|err| err.fill_position(*pos)) } } // var.??? @@ -1764,9 +1759,8 @@ impl Engine { let def_value = def_value.as_ref(); self.make_function_call( scope, mods, state, lib, this_ptr, name, args, def_value, *hash, *native, - false, *cap_scope, level, + false, *pos, *cap_scope, level, ) - .map_err(|err| err.fill_position(*pos)) } // Namespace-qualified function call @@ -1783,9 +1777,8 @@ impl Engine { let def_value = def_value.as_ref(); self.make_qualified_function_call( scope, mods, state, lib, this_ptr, namespace, name, args, def_value, *hash, - level, + *pos, level, ) - .map_err(|err| err.fill_position(*pos)) } Expr::In(x, _) => { @@ -1984,12 +1977,10 @@ impl Engine { let args = &mut [&mut lhs_ptr.as_mut().clone(), &mut rhs_val]; // Run function - let (value, _) = self - .exec_fn_call( - mods, state, lib, op, 0, args, false, false, false, None, None, - level, - ) - .map_err(|err| err.fill_position(*op_pos))?; + let (value, _) = self.exec_fn_call( + mods, state, lib, op, 0, args, false, false, false, *op_pos, None, + None, level, + )?; let value = value.flatten(); @@ -2023,10 +2014,10 @@ impl Engine { let result = self .exec_fn_call( - mods, state, lib, op, 0, args, false, false, false, None, None, level, + mods, state, lib, op, 0, args, false, false, false, *op_pos, None, + None, level, ) - .map(|(v, _)| v) - .map_err(|err| err.fill_position(*op_pos))?; + .map(|(v, _)| v)?; Some((result, rhs_expr.position())) }; diff --git a/src/engine_api.rs b/src/engine_api.rs index 6a2a5923..5cdaf1e2 100644 --- a/src/engine_api.rs +++ b/src/engine_api.rs @@ -1611,7 +1611,17 @@ impl Engine { crate::fn_call::ensure_no_data_race(name, args, false)?; } - self.call_script_fn(scope, &mut mods, &mut state, lib, this_ptr, fn_def, args, 0) + self.call_script_fn( + scope, + &mut mods, + &mut state, + lib, + this_ptr, + fn_def, + args, + Position::NONE, + 0, + ) } /// Optimize the [`AST`] with constants defined in an external Scope. /// An optimized copy of the [`AST`] is returned while the original [`AST`] is consumed. diff --git a/src/fn_call.rs b/src/fn_call.rs index 8e2c88bd..9c498f29 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -149,7 +149,6 @@ pub fn ensure_no_data_race( impl Engine { /// Call a native Rust function registered with the [`Engine`]. - /// [`Position`] in [`EvalAltResult`] is [`None`][Position::None] and must be set afterwards. /// /// ## WARNING /// @@ -166,6 +165,7 @@ impl Engine { args: &mut FnCallArgs, is_ref: bool, pub_only: bool, + pos: Position, def_val: Option<&Dynamic>, ) -> Result<(Dynamic, bool), Box> { self.inc_operations(state)?; @@ -204,7 +204,7 @@ impl Engine { EvalAltResult::ErrorMismatchOutputType( self.map_type_name(type_name::()).into(), typ.into(), - Position::NONE, + pos, ) })?) .into(), @@ -215,7 +215,7 @@ impl Engine { EvalAltResult::ErrorMismatchOutputType( self.map_type_name(type_name::()).into(), typ.into(), - Position::NONE, + pos, ) })?) .into(), @@ -247,7 +247,7 @@ impl Engine { prop, self.map_type_name(args[0].type_name()) ), - Position::NONE, + pos, ) .into(); } @@ -262,7 +262,7 @@ impl Engine { self.map_type_name(args[0].type_name()), self.map_type_name(args[1].type_name()), ), - Position::NONE, + pos, ) .into(); } @@ -276,7 +276,7 @@ impl Engine { self.map_type_name(args[0].type_name()), self.map_type_name(args[1].type_name()), ), - Position::NONE, + pos, ) .into(); } @@ -290,7 +290,7 @@ impl Engine { self.map_type_name(args[0].type_name()), self.map_type_name(args[1].type_name()), ), - Position::NONE, + pos, ) .into(); } @@ -309,13 +309,12 @@ impl Engine { .collect::>() .join(", ") ), - Position::NONE, + pos, ) .into() } /// Call a script-defined function. - /// [`Position`] in [`EvalAltResult`] is [`None`][Position::None] and must be set afterwards. /// /// ## WARNING /// @@ -332,6 +331,7 @@ impl Engine { this_ptr: &mut Option<&mut Dynamic>, fn_def: &crate::ast::ScriptFnDef, args: &mut FnCallArgs, + pos: Position, level: usize, ) -> Result> { self.inc_operations(state)?; @@ -340,7 +340,7 @@ impl Engine { #[cfg(not(feature = "no_function"))] #[cfg(not(feature = "unchecked"))] if level > self.max_call_levels() { - return Err(Box::new(EvalAltResult::ErrorStackOverflow(Position::NONE))); + return Err(Box::new(EvalAltResult::ErrorStackOverflow(pos))); } let orig_scope_level = state.scope_level; @@ -392,17 +392,14 @@ impl Engine { EvalAltResult::ErrorInFunctionCall( format!("{} > {}", fn_def.name, name), err, - Position::NONE, + pos, ) .into() } // System errors are passed straight-through err if err.is_system_exception() => Err(Box::new(err)), // Other errors are wrapped in `ErrorInFunctionCall` - _ => { - EvalAltResult::ErrorInFunctionCall(fn_def.name.to_string(), err, Position::NONE) - .into() - } + _ => EvalAltResult::ErrorInFunctionCall(fn_def.name.to_string(), err, pos).into(), }); // Remove all local variables @@ -456,7 +453,6 @@ impl Engine { } /// Perform an actual function call, native Rust or scripted, taking care of special functions. - /// [`Position`] in [`EvalAltResult`] is [`None`][Position::None] and must be set afterwards. /// /// ## WARNING /// @@ -474,6 +470,7 @@ impl Engine { is_ref: bool, _is_method: bool, pub_only: bool, + pos: Position, _capture_scope: Option, def_val: Option<&Dynamic>, _level: usize, @@ -511,7 +508,7 @@ impl Engine { fn_name, fn_name ) .into(), - Position::NONE, + pos, ) .into() } @@ -558,6 +555,7 @@ impl Engine { &mut Some(*first), func, rest, + pos, _level, )? } else { @@ -566,8 +564,9 @@ impl Engine { let mut backup: ArgBackup = Default::default(); backup.change_first_arg_to_copy(is_ref, args); - let result = self - .call_script_fn(scope, mods, state, lib, &mut None, func, args, _level); + let result = self.call_script_fn( + scope, mods, state, lib, &mut None, func, args, pos, _level, + ); // Restore the original reference backup.restore_first_arg(args); @@ -587,6 +586,7 @@ impl Engine { args, is_ref, pub_only, + pos, def_val, ) } @@ -594,7 +594,7 @@ impl Engine { // Normal native function call _ => self.call_native_fn( - mods, state, lib, fn_name, hash_fn, args, is_ref, pub_only, def_val, + mods, state, lib, fn_name, hash_fn, args, is_ref, pub_only, pos, def_val, ), } } @@ -625,7 +625,6 @@ impl Engine { } /// Evaluate a text string as a script - used primarily for 'eval'. - /// [`Position`] in [`EvalAltResult`] is [`None`][Position::None] and must be set afterwards. fn eval_script_expr( &self, scope: &mut Scope, @@ -633,6 +632,7 @@ impl Engine { state: &mut State, lib: &[&Module], script: &str, + pos: Position, _level: usize, ) -> Result> { self.inc_operations(state)?; @@ -646,7 +646,7 @@ impl Engine { #[cfg(not(feature = "no_function"))] #[cfg(not(feature = "unchecked"))] if _level > self.max_call_levels() { - return Err(Box::new(EvalAltResult::ErrorStackOverflow(Position::NONE))); + return Err(Box::new(EvalAltResult::ErrorStackOverflow(pos))); } // Compile the script text @@ -672,7 +672,6 @@ impl Engine { } /// Call a dot method. - /// [`Position`] in [`EvalAltResult`] is [`None`][Position::None] and must be set afterwards. #[cfg(not(feature = "no_object"))] pub(crate) fn make_method_call( &self, @@ -686,6 +685,7 @@ impl Engine { def_val: Option<&Dynamic>, native: bool, pub_only: bool, + pos: Position, level: usize, ) -> Result<(Dynamic, bool), Box> { let is_ref = target.is_ref(); @@ -716,7 +716,8 @@ impl Engine { // Map it to name(args) in function-call style self.exec_fn_call( - mods, state, lib, fn_name, hash, args, false, false, pub_only, None, def_val, level, + mods, state, lib, fn_name, hash, args, false, false, pub_only, pos, None, def_val, + level, ) } else if fn_name == KEYWORD_FN_PTR_CALL && call_args.len() > 0 @@ -743,7 +744,8 @@ impl Engine { // Map it to name(args) in function-call style self.exec_fn_call( - mods, state, lib, fn_name, hash, args, is_ref, true, pub_only, None, def_val, level, + mods, state, lib, fn_name, hash, args, is_ref, true, pub_only, pos, None, def_val, + level, ) } else if fn_name == KEYWORD_FN_PTR_CURRY && obj.is::() { // Curry call @@ -811,7 +813,8 @@ impl Engine { let args = arg_values.as_mut(); self.exec_fn_call( - mods, state, lib, fn_name, hash, args, is_ref, true, pub_only, None, def_val, level, + mods, state, lib, fn_name, hash, args, is_ref, true, pub_only, pos, None, def_val, + level, ) }?; @@ -824,7 +827,6 @@ impl Engine { } /// Call a function in normal function-call style. - /// [`Position`] in [`EvalAltResult`] is [`None`][Position::None] and must be set afterwards. pub(crate) fn make_function_call( &self, scope: &mut Scope, @@ -838,6 +840,7 @@ impl Engine { mut hash_script: u64, native: bool, pub_only: bool, + pos: Position, capture_scope: bool, level: usize, ) -> Result> { @@ -956,9 +959,8 @@ impl Engine { let script = script.as_str().map_err(|typ| { self.make_type_mismatch_err::(typ, args_expr[0].position()) })?; - let result = self - .eval_script_expr(scope, mods, state, lib, script, level + 1) - .map_err(|err| err.fill_position(args_expr[0].position())); + let pos = args_expr[0].position(); + let result = self.eval_script_expr(scope, mods, state, lib, script, pos, level + 1); // IMPORTANT! If the eval defines new variables in the current scope, // all variable offsets from this point on will be mis-aligned. @@ -1029,13 +1031,13 @@ impl Engine { let args = args.as_mut(); self.exec_fn_call( - mods, state, lib, name, hash, args, is_ref, false, pub_only, capture, def_val, level, + mods, state, lib, name, hash, args, is_ref, false, pub_only, pos, capture, def_val, + level, ) .map(|(v, _)| v) } /// Call a namespace-qualified function in normal function-call style. - /// [`Position`] in [`EvalAltResult`] is [`None`][Position::None] and must be set afterwards. pub(crate) fn make_qualified_function_call( &self, scope: &mut Scope, @@ -1048,6 +1050,7 @@ impl Engine { args_expr: impl AsRef<[Expr]>, def_val: Option<&Dynamic>, hash_script: u64, + pos: Position, level: usize, ) -> Result> { let args_expr = args_expr.as_ref(); @@ -1143,7 +1146,9 @@ impl Engine { let args = args.as_mut(); let new_scope = &mut Default::default(); let fn_def = f.get_fn_def().clone(); - self.call_script_fn(new_scope, mods, state, lib, &mut None, &fn_def, args, level) + self.call_script_fn( + new_scope, mods, state, lib, &mut None, &fn_def, args, pos, level, + ) } Some(f) if f.is_plugin_fn() => f .get_plugin_fn() @@ -1177,7 +1182,7 @@ impl Engine { .collect::>() .join(", ") ), - Position::NONE, + pos, ) .into(), } diff --git a/src/fn_native.rs b/src/fn_native.rs index 0706983d..df74e163 100644 --- a/src/fn_native.rs +++ b/src/fn_native.rs @@ -164,6 +164,7 @@ impl<'e, 'a, 'm, 'pm> NativeCallContext<'e, 'a, 'm, 'pm> { is_method, is_method, public_only, + Position::NONE, None, def_value, 0, diff --git a/src/optimize.rs b/src/optimize.rs index f04dda40..4727dff4 100644 --- a/src/optimize.rs +++ b/src/optimize.rs @@ -142,6 +142,7 @@ fn call_fn_with_constant_arguments( arg_values.iter_mut().collect::>().as_mut(), false, true, + Position::NONE, None, ) .ok()