Add NativeCallContext::position.
This commit is contained in:
parent
ff9ac41da2
commit
affbb81d8a
@ -19,6 +19,7 @@ Enhancements
|
||||
* Array adds a `sort` method with no parameters which sorts homogeneous arrays of built-in comparable types (e.g. `INT`).
|
||||
* Inlining is disabled for error-path functions because errors are exceptional and scripts usually fail completely when an error is encountered.
|
||||
* The `optimize` module is completely eliminated under `no_optimize`, which should yield smaller code size.
|
||||
* Add `NativeCallContext::position` to return the position of the function call.
|
||||
|
||||
Deprecated API's
|
||||
----------------
|
||||
|
@ -339,12 +339,14 @@ impl Engine {
|
||||
.map(|s| s.as_str());
|
||||
|
||||
let result = if func.is_plugin_fn() {
|
||||
let context = (self, name, source, mods, lib, pos).into();
|
||||
func.get_plugin_fn()
|
||||
.expect("plugin function")
|
||||
.call((self, name, source, mods, lib).into(), args)
|
||||
.call(context, args)
|
||||
} else {
|
||||
let func = func.get_native_fn().expect("native function");
|
||||
func((self, name, source, mods, lib).into(), args)
|
||||
let context = (self, name, source, mods, lib, pos).into();
|
||||
func(context, args)
|
||||
};
|
||||
|
||||
// Restore the original reference
|
||||
@ -1448,17 +1450,19 @@ impl Engine {
|
||||
}
|
||||
}
|
||||
|
||||
Some(f) if f.is_plugin_fn() => f
|
||||
.get_plugin_fn()
|
||||
.expect("plugin function")
|
||||
.clone()
|
||||
.call((self, fn_name, module.id(), &*mods, lib).into(), &mut args)
|
||||
.map_err(|err| err.fill_position(pos)),
|
||||
Some(f) if f.is_plugin_fn() => {
|
||||
let context = (self, fn_name, module.id(), &*mods, lib, pos).into();
|
||||
f.get_plugin_fn()
|
||||
.expect("plugin function")
|
||||
.clone()
|
||||
.call(context, &mut args)
|
||||
.map_err(|err| err.fill_position(pos))
|
||||
}
|
||||
|
||||
Some(f) if f.is_native() => {
|
||||
let func = f.get_native_fn().expect("native function");
|
||||
func((self, fn_name, module.id(), &*mods, lib).into(), &mut args)
|
||||
.map_err(|err| err.fill_position(pos))
|
||||
let context = (self, fn_name, module.id(), &*mods, lib, pos).into();
|
||||
func(context, &mut args).map_err(|err| err.fill_position(pos))
|
||||
}
|
||||
|
||||
Some(f) => unreachable!("unknown function type: {:?}", f),
|
||||
|
@ -54,34 +54,53 @@ pub struct NativeCallContext<'a> {
|
||||
source: Option<&'a str>,
|
||||
mods: Option<&'a Imports>,
|
||||
lib: &'a [&'a Module],
|
||||
pos: Position,
|
||||
}
|
||||
|
||||
impl<'a, M: AsRef<[&'a Module]> + ?Sized>
|
||||
From<(&'a Engine, &'a str, Option<&'a str>, &'a Imports, &'a M)> for NativeCallContext<'a>
|
||||
From<(
|
||||
&'a Engine,
|
||||
&'a str,
|
||||
Option<&'a str>,
|
||||
&'a Imports,
|
||||
&'a M,
|
||||
Position,
|
||||
)> for NativeCallContext<'a>
|
||||
{
|
||||
#[inline(always)]
|
||||
fn from(value: (&'a Engine, &'a str, Option<&'a str>, &'a Imports, &'a M)) -> Self {
|
||||
fn from(
|
||||
value: (
|
||||
&'a Engine,
|
||||
&'a str,
|
||||
Option<&'a str>,
|
||||
&'a Imports,
|
||||
&'a M,
|
||||
Position,
|
||||
),
|
||||
) -> Self {
|
||||
Self {
|
||||
engine: value.0,
|
||||
fn_name: value.1,
|
||||
source: value.2,
|
||||
mods: Some(value.3),
|
||||
lib: value.4.as_ref(),
|
||||
pos: value.5,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, M: AsRef<[&'a Module]> + ?Sized> From<(&'a Engine, &'a str, &'a M)>
|
||||
impl<'a, M: AsRef<[&'a Module]> + ?Sized> From<(&'a Engine, &'a str, &'a M, Position)>
|
||||
for NativeCallContext<'a>
|
||||
{
|
||||
#[inline(always)]
|
||||
fn from(value: (&'a Engine, &'a str, &'a M)) -> Self {
|
||||
fn from(value: (&'a Engine, &'a str, &'a M, Position)) -> Self {
|
||||
Self {
|
||||
engine: value.0,
|
||||
fn_name: value.1,
|
||||
source: None,
|
||||
mods: None,
|
||||
lib: value.2.as_ref(),
|
||||
pos: value.3,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -90,13 +109,19 @@ impl<'a> NativeCallContext<'a> {
|
||||
/// Create a new [`NativeCallContext`].
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn new(engine: &'a Engine, fn_name: &'a str, lib: &'a [&Module]) -> Self {
|
||||
pub const fn new(
|
||||
engine: &'a Engine,
|
||||
fn_name: &'a str,
|
||||
lib: &'a [&Module],
|
||||
pos: Position,
|
||||
) -> Self {
|
||||
Self {
|
||||
engine,
|
||||
fn_name,
|
||||
source: None,
|
||||
mods: None,
|
||||
lib,
|
||||
pos,
|
||||
}
|
||||
}
|
||||
/// _(internals)_ Create a new [`NativeCallContext`].
|
||||
@ -113,6 +138,7 @@ impl<'a> NativeCallContext<'a> {
|
||||
source: Option<&'a str>,
|
||||
imports: &'a Imports,
|
||||
lib: &'a [&Module],
|
||||
pos: Position,
|
||||
) -> Self {
|
||||
Self {
|
||||
engine,
|
||||
@ -120,6 +146,7 @@ impl<'a> NativeCallContext<'a> {
|
||||
source,
|
||||
mods: Some(imports),
|
||||
lib,
|
||||
pos,
|
||||
}
|
||||
}
|
||||
/// The current [`Engine`].
|
||||
@ -134,6 +161,12 @@ impl<'a> NativeCallContext<'a> {
|
||||
pub const fn fn_name(&self) -> &str {
|
||||
self.fn_name
|
||||
}
|
||||
/// [Position][`Position`] of the function call.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn position(&self) -> Position {
|
||||
self.pos
|
||||
}
|
||||
/// The current source.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
|
@ -1000,9 +1000,9 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) {
|
||||
_ if x.args.len() == 2 && !state.has_native_fn(x.hashes.native, arg_types.as_ref()) => {
|
||||
if let Some(result) = get_builtin_binary_op_fn(x.name.as_ref(), &arg_values[0], &arg_values[1])
|
||||
.and_then(|f| {
|
||||
let ctx = (state.engine, x.name.as_ref(), state.lib).into();
|
||||
let context = (state.engine, x.name.as_ref(), state.lib, Position::NONE).into();
|
||||
let (first, second) = arg_values.split_first_mut().expect("`arg_values` is not empty");
|
||||
(f)(ctx, &mut [ first, &mut second[0] ]).ok()
|
||||
(f)(context, &mut [ first, &mut second[0] ]).ok()
|
||||
}) {
|
||||
state.set_dirty();
|
||||
*expr = Expr::from_dynamic(result, *pos);
|
||||
|
@ -36,4 +36,5 @@ fn check_struct_sizes() {
|
||||
if cfg!(feature = "no_position") { 8 } else { 16 }
|
||||
);
|
||||
assert_eq!(size_of::<EvalAltResult>(), 72);
|
||||
assert_eq!(size_of::<NativeCallContext>(), 72);
|
||||
}
|
||||
|
@ -338,7 +338,7 @@ fn test_closures_external() -> Result<(), Box<EvalAltResult>> {
|
||||
|
||||
// Create native call context
|
||||
let fn_name = fn_ptr.fn_name().to_string();
|
||||
let context = NativeCallContext::new(&engine, &fn_name, &lib);
|
||||
let context = NativeCallContext::new(&engine, &fn_name, &lib, rhai::Position::NONE);
|
||||
|
||||
// Closure 'f' captures: the engine, the AST, and the curried function pointer
|
||||
let f = move |x: INT| fn_ptr.call_dynamic(&context, None, [x.into()]);
|
||||
|
Loading…
Reference in New Issue
Block a user