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`).
|
* 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.
|
* 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.
|
* 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
|
Deprecated API's
|
||||||
----------------
|
----------------
|
||||||
|
@ -339,12 +339,14 @@ impl Engine {
|
|||||||
.map(|s| s.as_str());
|
.map(|s| s.as_str());
|
||||||
|
|
||||||
let result = if func.is_plugin_fn() {
|
let result = if func.is_plugin_fn() {
|
||||||
|
let context = (self, name, source, mods, lib, pos).into();
|
||||||
func.get_plugin_fn()
|
func.get_plugin_fn()
|
||||||
.expect("plugin function")
|
.expect("plugin function")
|
||||||
.call((self, name, source, mods, lib).into(), args)
|
.call(context, args)
|
||||||
} else {
|
} else {
|
||||||
let func = func.get_native_fn().expect("native function");
|
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
|
// Restore the original reference
|
||||||
@ -1448,17 +1450,19 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(f) if f.is_plugin_fn() => f
|
Some(f) if f.is_plugin_fn() => {
|
||||||
.get_plugin_fn()
|
let context = (self, fn_name, module.id(), &*mods, lib, pos).into();
|
||||||
.expect("plugin function")
|
f.get_plugin_fn()
|
||||||
.clone()
|
.expect("plugin function")
|
||||||
.call((self, fn_name, module.id(), &*mods, lib).into(), &mut args)
|
.clone()
|
||||||
.map_err(|err| err.fill_position(pos)),
|
.call(context, &mut args)
|
||||||
|
.map_err(|err| err.fill_position(pos))
|
||||||
|
}
|
||||||
|
|
||||||
Some(f) if f.is_native() => {
|
Some(f) if f.is_native() => {
|
||||||
let func = f.get_native_fn().expect("native function");
|
let func = f.get_native_fn().expect("native function");
|
||||||
func((self, fn_name, module.id(), &*mods, lib).into(), &mut args)
|
let context = (self, fn_name, module.id(), &*mods, lib, pos).into();
|
||||||
.map_err(|err| err.fill_position(pos))
|
func(context, &mut args).map_err(|err| err.fill_position(pos))
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(f) => unreachable!("unknown function type: {:?}", f),
|
Some(f) => unreachable!("unknown function type: {:?}", f),
|
||||||
|
@ -54,34 +54,53 @@ pub struct NativeCallContext<'a> {
|
|||||||
source: Option<&'a str>,
|
source: Option<&'a str>,
|
||||||
mods: Option<&'a Imports>,
|
mods: Option<&'a Imports>,
|
||||||
lib: &'a [&'a Module],
|
lib: &'a [&'a Module],
|
||||||
|
pos: Position,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, M: AsRef<[&'a Module]> + ?Sized>
|
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)]
|
#[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 {
|
Self {
|
||||||
engine: value.0,
|
engine: value.0,
|
||||||
fn_name: value.1,
|
fn_name: value.1,
|
||||||
source: value.2,
|
source: value.2,
|
||||||
mods: Some(value.3),
|
mods: Some(value.3),
|
||||||
lib: value.4.as_ref(),
|
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>
|
for NativeCallContext<'a>
|
||||||
{
|
{
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(value: (&'a Engine, &'a str, &'a M)) -> Self {
|
fn from(value: (&'a Engine, &'a str, &'a M, Position)) -> Self {
|
||||||
Self {
|
Self {
|
||||||
engine: value.0,
|
engine: value.0,
|
||||||
fn_name: value.1,
|
fn_name: value.1,
|
||||||
source: None,
|
source: None,
|
||||||
mods: None,
|
mods: None,
|
||||||
lib: value.2.as_ref(),
|
lib: value.2.as_ref(),
|
||||||
|
pos: value.3,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -90,13 +109,19 @@ impl<'a> NativeCallContext<'a> {
|
|||||||
/// Create a new [`NativeCallContext`].
|
/// Create a new [`NativeCallContext`].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[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 {
|
Self {
|
||||||
engine,
|
engine,
|
||||||
fn_name,
|
fn_name,
|
||||||
source: None,
|
source: None,
|
||||||
mods: None,
|
mods: None,
|
||||||
lib,
|
lib,
|
||||||
|
pos,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// _(internals)_ Create a new [`NativeCallContext`].
|
/// _(internals)_ Create a new [`NativeCallContext`].
|
||||||
@ -113,6 +138,7 @@ impl<'a> NativeCallContext<'a> {
|
|||||||
source: Option<&'a str>,
|
source: Option<&'a str>,
|
||||||
imports: &'a Imports,
|
imports: &'a Imports,
|
||||||
lib: &'a [&Module],
|
lib: &'a [&Module],
|
||||||
|
pos: Position,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
engine,
|
engine,
|
||||||
@ -120,6 +146,7 @@ impl<'a> NativeCallContext<'a> {
|
|||||||
source,
|
source,
|
||||||
mods: Some(imports),
|
mods: Some(imports),
|
||||||
lib,
|
lib,
|
||||||
|
pos,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// The current [`Engine`].
|
/// The current [`Engine`].
|
||||||
@ -134,6 +161,12 @@ impl<'a> NativeCallContext<'a> {
|
|||||||
pub const fn fn_name(&self) -> &str {
|
pub const fn fn_name(&self) -> &str {
|
||||||
self.fn_name
|
self.fn_name
|
||||||
}
|
}
|
||||||
|
/// [Position][`Position`] of the function call.
|
||||||
|
#[inline(always)]
|
||||||
|
#[must_use]
|
||||||
|
pub const fn position(&self) -> Position {
|
||||||
|
self.pos
|
||||||
|
}
|
||||||
/// The current source.
|
/// The current source.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[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 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])
|
if let Some(result) = get_builtin_binary_op_fn(x.name.as_ref(), &arg_values[0], &arg_values[1])
|
||||||
.and_then(|f| {
|
.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");
|
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();
|
state.set_dirty();
|
||||||
*expr = Expr::from_dynamic(result, *pos);
|
*expr = Expr::from_dynamic(result, *pos);
|
||||||
|
@ -36,4 +36,5 @@ fn check_struct_sizes() {
|
|||||||
if cfg!(feature = "no_position") { 8 } else { 16 }
|
if cfg!(feature = "no_position") { 8 } else { 16 }
|
||||||
);
|
);
|
||||||
assert_eq!(size_of::<EvalAltResult>(), 72);
|
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
|
// Create native call context
|
||||||
let fn_name = fn_ptr.fn_name().to_string();
|
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
|
// 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()]);
|
let f = move |x: INT| fn_ptr.call_dynamic(&context, None, [x.into()]);
|
||||||
|
Loading…
Reference in New Issue
Block a user