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

@ -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(
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))?;
*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(
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))?;
*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()))
};

View File

@ -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.

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(),
}

View File

@ -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,

View File

@ -142,6 +142,7 @@ fn call_fn_with_constant_arguments(
arg_values.iter_mut().collect::<StaticVec<_>>().as_mut(),
false,
true,
Position::NONE,
None,
)
.ok()