Pass Position into function calls.

This commit is contained in:
Stephen Chung
2020-12-12 11:15:09 +08:00
parent 4438c358d5
commit 5443368359
5 changed files with 86 additions and 78 deletions

View File

@@ -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<EvalAltResult>> {
self.inc_operations(state)?;
@@ -204,7 +204,7 @@ impl Engine {
EvalAltResult::ErrorMismatchOutputType(
self.map_type_name(type_name::<ImmutableString>()).into(),
typ.into(),
Position::NONE,
pos,
)
})?)
.into(),
@@ -215,7 +215,7 @@ impl Engine {
EvalAltResult::ErrorMismatchOutputType(
self.map_type_name(type_name::<ImmutableString>()).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::<Vec<_>>()
.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<Dynamic, Box<EvalAltResult>> {
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<Scope>,
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<Dynamic, Box<EvalAltResult>> {
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<EvalAltResult>> {
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::<FnPtr>() {
// 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<Dynamic, Box<EvalAltResult>> {
@@ -956,9 +959,8 @@ impl Engine {
let script = script.as_str().map_err(|typ| {
self.make_type_mismatch_err::<ImmutableString>(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<Dynamic, Box<EvalAltResult>> {
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::<Vec<_>>()
.join(", ")
),
Position::NONE,
pos,
)
.into(),
}