commit
3078a281b2
18
CHANGELOG.md
18
CHANGELOG.md
@ -1,6 +1,24 @@
|
||||
Rhai Release Notes
|
||||
==================
|
||||
|
||||
Version 1.10.0
|
||||
==============
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
|
||||
* API for registering property getters/setters and indexers to an `Engine` now works with functions that take a first parameter of `NativeCallContext`.
|
||||
* Missing API function `Module::set_getter_setter_fn` is added.
|
||||
|
||||
New features
|
||||
------------
|
||||
|
||||
Fallible type iterators
|
||||
-----------------------
|
||||
|
||||
* For very special needs, the ability to register fallible type iterators is added.
|
||||
|
||||
|
||||
Version 1.9.0
|
||||
=============
|
||||
|
||||
|
@ -125,10 +125,10 @@ impl<'a, T: Variant + Clone> TypeBuilder<'a, T> {
|
||||
|
||||
/// Register a custom function.
|
||||
#[inline(always)]
|
||||
pub fn with_fn<N, A, F>(&mut self, name: N, method: F) -> &mut Self
|
||||
pub fn with_fn<N, A, F, R, S>(&mut self, name: N, method: F) -> &mut Self
|
||||
where
|
||||
N: AsRef<str> + Into<Identifier>,
|
||||
F: RegisterNativeFunction<A, ()>,
|
||||
F: RegisterNativeFunction<A, R, S>,
|
||||
{
|
||||
self.engine.register_fn(name, method);
|
||||
self
|
||||
@ -136,10 +136,10 @@ impl<'a, T: Variant + Clone> TypeBuilder<'a, T> {
|
||||
|
||||
/// Register a custom fallible function.
|
||||
#[inline(always)]
|
||||
pub fn with_result_fn<N, A, F, R>(&mut self, name: N, method: F) -> &mut Self
|
||||
pub fn with_result_fn<N, A, F, R, S>(&mut self, name: N, method: F) -> &mut Self
|
||||
where
|
||||
N: AsRef<str> + Into<Identifier>,
|
||||
F: RegisterNativeFunction<A, RhaiResultOf<R>>,
|
||||
F: RegisterNativeFunction<A, R, RhaiResultOf<S>>,
|
||||
{
|
||||
self.engine.register_result_fn(name, method);
|
||||
self
|
||||
|
@ -72,16 +72,13 @@ impl Engine {
|
||||
Token::LeftBrace => Token::MapStart,
|
||||
// Disallowed syntax
|
||||
t @ (Token::Unit | Token::MapStart) => Token::LexError(
|
||||
LexError::ImproperSymbol(
|
||||
t.literal_syntax().to_string(),
|
||||
"".to_string(),
|
||||
)
|
||||
LexError::ImproperSymbol(t.literal_syntax().to_string(), String::new())
|
||||
.into(),
|
||||
),
|
||||
Token::InterpolatedString(..) => Token::LexError(
|
||||
LexError::ImproperSymbol(
|
||||
"interpolated string".to_string(),
|
||||
"".to_string(),
|
||||
String::new(),
|
||||
)
|
||||
.into(),
|
||||
),
|
||||
@ -93,7 +90,7 @@ impl Engine {
|
||||
Some(&|token, _, _| {
|
||||
match token {
|
||||
Token::Reserved(s) if &*s == "null" => Token::LexError(
|
||||
LexError::ImproperSymbol("null".to_string(), "".to_string()).into(),
|
||||
LexError::ImproperSymbol("null".to_string(), String::new()).into(),
|
||||
),
|
||||
// `{` => `#{`
|
||||
Token::LeftBrace => Token::MapStart,
|
||||
|
@ -1,5 +1,6 @@
|
||||
//! Module that defines the public function/module registration API of [`Engine`].
|
||||
|
||||
use crate::func::register::Mut;
|
||||
use crate::func::{FnCallArgs, RegisterNativeFunction, SendSync};
|
||||
use crate::types::dynamic::Variant;
|
||||
use crate::{
|
||||
@ -50,10 +51,10 @@ impl Engine {
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn register_fn<N, A, F>(&mut self, name: N, func: F) -> &mut Self
|
||||
pub fn register_fn<N, A, F, R, S>(&mut self, name: N, func: F) -> &mut Self
|
||||
where
|
||||
N: AsRef<str> + Into<Identifier>,
|
||||
F: RegisterNativeFunction<A, ()>,
|
||||
F: RegisterNativeFunction<A, R, S>,
|
||||
{
|
||||
let param_types = F::param_types();
|
||||
|
||||
@ -112,10 +113,10 @@ impl Engine {
|
||||
/// .expect_err("expecting division by zero error!");
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn register_result_fn<N, A, F, R>(&mut self, name: N, func: F) -> &mut Self
|
||||
pub fn register_result_fn<N, A, F, R, S>(&mut self, name: N, func: F) -> &mut Self
|
||||
where
|
||||
N: AsRef<str> + Into<Identifier>,
|
||||
F: RegisterNativeFunction<A, RhaiResultOf<R>>,
|
||||
F: RegisterNativeFunction<A, R, RhaiResultOf<S>>,
|
||||
{
|
||||
let param_types = F::param_types();
|
||||
|
||||
@ -291,7 +292,7 @@ impl Engine {
|
||||
.set_custom_type_raw(fully_qualified_type_path, name);
|
||||
self
|
||||
}
|
||||
/// Register an type iterator for an iterable type with the [`Engine`].
|
||||
/// Register a type iterator for an iterable type with the [`Engine`].
|
||||
/// This is an advanced API.
|
||||
#[inline(always)]
|
||||
pub fn register_iterator<T>(&mut self) -> &mut Self
|
||||
@ -302,6 +303,17 @@ impl Engine {
|
||||
self.global_namespace_mut().set_iterable::<T>();
|
||||
self
|
||||
}
|
||||
/// Register a fallible type iterator for an iterable type with the [`Engine`].
|
||||
/// This is an advanced API.
|
||||
#[inline(always)]
|
||||
pub fn register_iterator_result<T, X>(&mut self) -> &mut Self
|
||||
where
|
||||
T: Variant + Clone + IntoIterator<Item = RhaiResultOf<X>>,
|
||||
X: Variant + Clone,
|
||||
{
|
||||
self.global_namespace_mut().set_iterable_result::<T, X>();
|
||||
self
|
||||
}
|
||||
/// Register a getter function for a member of a registered type with the [`Engine`].
|
||||
///
|
||||
/// The function signature must start with `&mut self` and not `&self`.
|
||||
@ -344,10 +356,10 @@ impl Engine {
|
||||
/// ```
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
#[inline(always)]
|
||||
pub fn register_get<T: Variant + Clone, V: Variant + Clone>(
|
||||
pub fn register_get<T: Variant + Clone, V: Variant + Clone, S>(
|
||||
&mut self,
|
||||
name: impl AsRef<str>,
|
||||
get_fn: impl Fn(&mut T) -> V + SendSync + 'static,
|
||||
get_fn: impl RegisterNativeFunction<(Mut<T>,), V, S> + SendSync + 'static,
|
||||
) -> &mut Self {
|
||||
self.register_fn(crate::engine::make_getter(name.as_ref()).as_str(), get_fn)
|
||||
}
|
||||
@ -393,10 +405,10 @@ impl Engine {
|
||||
/// ```
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
#[inline(always)]
|
||||
pub fn register_get_result<T: Variant + Clone, V: Variant + Clone>(
|
||||
pub fn register_get_result<T: Variant + Clone, V: Variant + Clone, S>(
|
||||
&mut self,
|
||||
name: impl AsRef<str>,
|
||||
get_fn: impl Fn(&mut T) -> RhaiResultOf<V> + SendSync + 'static,
|
||||
get_fn: impl RegisterNativeFunction<(Mut<T>,), V, RhaiResultOf<S>> + SendSync + 'static,
|
||||
) -> &mut Self {
|
||||
self.register_result_fn(crate::engine::make_getter(name.as_ref()).as_str(), get_fn)
|
||||
}
|
||||
@ -443,10 +455,10 @@ impl Engine {
|
||||
/// ```
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
#[inline(always)]
|
||||
pub fn register_set<T: Variant + Clone, V: Variant + Clone>(
|
||||
pub fn register_set<T: Variant + Clone, V: Variant + Clone, S>(
|
||||
&mut self,
|
||||
name: impl AsRef<str>,
|
||||
set_fn: impl Fn(&mut T, V) + SendSync + 'static,
|
||||
set_fn: impl RegisterNativeFunction<(Mut<T>, V), (), S> + SendSync + 'static,
|
||||
) -> &mut Self {
|
||||
self.register_fn(crate::engine::make_setter(name.as_ref()).as_str(), set_fn)
|
||||
}
|
||||
@ -494,10 +506,10 @@ impl Engine {
|
||||
/// ```
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
#[inline(always)]
|
||||
pub fn register_set_result<T: Variant + Clone, V: Variant + Clone>(
|
||||
pub fn register_set_result<T: Variant + Clone, V: Variant + Clone, S>(
|
||||
&mut self,
|
||||
name: impl AsRef<str>,
|
||||
set_fn: impl Fn(&mut T, V) -> RhaiResultOf<()> + SendSync + 'static,
|
||||
set_fn: impl RegisterNativeFunction<(Mut<T>, V), (), RhaiResultOf<S>> + SendSync + 'static,
|
||||
) -> &mut Self {
|
||||
self.register_result_fn(crate::engine::make_setter(name.as_ref()).as_str(), set_fn)
|
||||
}
|
||||
@ -548,11 +560,11 @@ impl Engine {
|
||||
/// ```
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
#[inline(always)]
|
||||
pub fn register_get_set<T: Variant + Clone, V: Variant + Clone>(
|
||||
pub fn register_get_set<T: Variant + Clone, V: Variant + Clone, S1, S2>(
|
||||
&mut self,
|
||||
name: impl AsRef<str>,
|
||||
get_fn: impl Fn(&mut T) -> V + SendSync + 'static,
|
||||
set_fn: impl Fn(&mut T, V) + SendSync + 'static,
|
||||
get_fn: impl RegisterNativeFunction<(Mut<T>,), V, S1> + SendSync + 'static,
|
||||
set_fn: impl RegisterNativeFunction<(Mut<T>, V), (), S2> + SendSync + 'static,
|
||||
) -> &mut Self {
|
||||
self.register_get(&name, get_fn).register_set(&name, set_fn)
|
||||
}
|
||||
@ -607,9 +619,9 @@ impl Engine {
|
||||
/// ```
|
||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||
#[inline]
|
||||
pub fn register_indexer_get<T: Variant + Clone, X: Variant + Clone, V: Variant + Clone>(
|
||||
pub fn register_indexer_get<T: Variant + Clone, X: Variant + Clone, V: Variant + Clone, S>(
|
||||
&mut self,
|
||||
get_fn: impl Fn(&mut T, X) -> V + SendSync + 'static,
|
||||
get_fn: impl RegisterNativeFunction<(Mut<T>, X), V, S> + SendSync + 'static,
|
||||
) -> &mut Self {
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
if TypeId::of::<T>() == TypeId::of::<crate::Array>() {
|
||||
@ -686,9 +698,10 @@ impl Engine {
|
||||
T: Variant + Clone,
|
||||
X: Variant + Clone,
|
||||
V: Variant + Clone,
|
||||
S,
|
||||
>(
|
||||
&mut self,
|
||||
get_fn: impl Fn(&mut T, X) -> RhaiResultOf<V> + SendSync + 'static,
|
||||
get_fn: impl RegisterNativeFunction<(Mut<T>, X), V, RhaiResultOf<S>> + SendSync + 'static,
|
||||
) -> &mut Self {
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
if TypeId::of::<T>() == TypeId::of::<crate::Array>() {
|
||||
@ -761,9 +774,9 @@ impl Engine {
|
||||
/// ```
|
||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||
#[inline]
|
||||
pub fn register_indexer_set<T: Variant + Clone, X: Variant + Clone, V: Variant + Clone>(
|
||||
pub fn register_indexer_set<T: Variant + Clone, X: Variant + Clone, V: Variant + Clone, S>(
|
||||
&mut self,
|
||||
set_fn: impl Fn(&mut T, X, V) + SendSync + 'static,
|
||||
set_fn: impl RegisterNativeFunction<(Mut<T>, X, V), (), S> + SendSync + 'static,
|
||||
) -> &mut Self {
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
if TypeId::of::<T>() == TypeId::of::<crate::Array>() {
|
||||
@ -841,9 +854,10 @@ impl Engine {
|
||||
T: Variant + Clone,
|
||||
X: Variant + Clone,
|
||||
V: Variant + Clone,
|
||||
S,
|
||||
>(
|
||||
&mut self,
|
||||
set_fn: impl Fn(&mut T, X, V) -> RhaiResultOf<()> + SendSync + 'static,
|
||||
set_fn: impl RegisterNativeFunction<(Mut<T>, X, V), (), RhaiResultOf<S>> + SendSync + 'static,
|
||||
) -> &mut Self {
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
if TypeId::of::<T>() == TypeId::of::<crate::Array>() {
|
||||
@ -917,10 +931,16 @@ impl Engine {
|
||||
/// ```
|
||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||
#[inline(always)]
|
||||
pub fn register_indexer_get_set<T: Variant + Clone, X: Variant + Clone, V: Variant + Clone>(
|
||||
pub fn register_indexer_get_set<
|
||||
T: Variant + Clone,
|
||||
X: Variant + Clone,
|
||||
V: Variant + Clone,
|
||||
S1,
|
||||
S2,
|
||||
>(
|
||||
&mut self,
|
||||
get_fn: impl Fn(&mut T, X) -> V + SendSync + 'static,
|
||||
set_fn: impl Fn(&mut T, X, V) + SendSync + 'static,
|
||||
get_fn: impl RegisterNativeFunction<(Mut<T>, X), V, S1> + SendSync + 'static,
|
||||
set_fn: impl RegisterNativeFunction<(Mut<T>, X, V), (), S2> + SendSync + 'static,
|
||||
) -> &mut Self {
|
||||
self.register_indexer_get(get_fn)
|
||||
.register_indexer_set(set_fn)
|
||||
|
@ -90,12 +90,12 @@ fn print_error(input: &str, mut err: EvalAltResult) {
|
||||
|
||||
let line_no = if lines.len() > 1 {
|
||||
if pos.is_none() {
|
||||
"".to_string()
|
||||
String::new()
|
||||
} else {
|
||||
format!("{}: ", pos.line().unwrap())
|
||||
}
|
||||
} else {
|
||||
"".to_string()
|
||||
String::new()
|
||||
};
|
||||
|
||||
// Print error position
|
||||
|
@ -15,12 +15,12 @@ fn print_error(input: &str, mut err: EvalAltResult) {
|
||||
|
||||
let line_no = if lines.len() > 1 {
|
||||
if pos.is_none() {
|
||||
"".to_string()
|
||||
String::new()
|
||||
} else {
|
||||
format!("{}: ", pos.line().unwrap())
|
||||
}
|
||||
} else {
|
||||
"".to_string()
|
||||
String::new()
|
||||
};
|
||||
|
||||
// Print error position
|
||||
|
@ -641,38 +641,21 @@ impl Engine {
|
||||
break;
|
||||
}
|
||||
|
||||
let index_value = (x as INT).into();
|
||||
let index_value = Dynamic::from(x as INT);
|
||||
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
{
|
||||
let index_var = scope.get_mut_by_index(counter_index);
|
||||
if index_var.is_shared() {
|
||||
*index_var.write_lock().expect("`Dynamic`") = index_value;
|
||||
} else {
|
||||
*index_var = index_value;
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "no_closure")]
|
||||
{
|
||||
*scope.get_mut_by_index(counter_index) = index_value;
|
||||
}
|
||||
*scope.get_mut_by_index(counter_index).write_lock().unwrap() =
|
||||
index_value;
|
||||
}
|
||||
|
||||
let value = iter_value.flatten();
|
||||
let value = match iter_value {
|
||||
Ok(v) => v.flatten(),
|
||||
Err(err) => {
|
||||
loop_result = Err(err.fill_position(expr.position()));
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
{
|
||||
let loop_var = scope.get_mut_by_index(index);
|
||||
if loop_var.is_shared() {
|
||||
*loop_var.write_lock().expect("`Dynamic`") = value;
|
||||
} else {
|
||||
*loop_var = value;
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "no_closure")]
|
||||
{
|
||||
*scope.get_mut_by_index(index) = value;
|
||||
}
|
||||
*scope.get_mut_by_index(index).write_lock().unwrap() = value;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
if let Err(err) = self
|
||||
|
@ -426,10 +426,11 @@ pub type FnBuiltin = fn(NativeCallContext, &mut FnCallArgs) -> RhaiResult;
|
||||
|
||||
/// Function that gets an iterator from a type.
|
||||
#[cfg(not(feature = "sync"))]
|
||||
pub type IteratorFn = dyn Fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>>;
|
||||
pub type IteratorFn = dyn Fn(Dynamic) -> Box<dyn Iterator<Item = RhaiResultOf<Dynamic>>>;
|
||||
/// Function that gets an iterator from a type.
|
||||
#[cfg(feature = "sync")]
|
||||
pub type IteratorFn = dyn Fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>> + Send + Sync;
|
||||
pub type IteratorFn =
|
||||
dyn Fn(Dynamic) -> Box<dyn Iterator<Item = RhaiResultOf<Dynamic>>> + Send + Sync;
|
||||
|
||||
#[cfg(not(feature = "sync"))]
|
||||
pub type FnPlugin = dyn PluginFunction;
|
||||
|
@ -60,7 +60,7 @@ pub fn by_value<T: Variant + Clone>(data: &mut Dynamic) -> T {
|
||||
}
|
||||
|
||||
/// Trait to register custom Rust functions.
|
||||
pub trait RegisterNativeFunction<Args, Result> {
|
||||
pub trait RegisterNativeFunction<ARGS, RET, RESULT> {
|
||||
/// Convert this function into a [`CallableFunction`].
|
||||
#[must_use]
|
||||
fn into_callable_function(self) -> CallableFunction;
|
||||
@ -128,7 +128,7 @@ macro_rules! def_register {
|
||||
FN: Fn($($param),*) -> RET + SendSync + 'static,
|
||||
$($par: Variant + Clone,)*
|
||||
RET: Variant + Clone
|
||||
> RegisterNativeFunction<($($mark,)*), ()> for FN {
|
||||
> RegisterNativeFunction<($($mark,)*), RET, ()> for FN {
|
||||
#[inline(always)] fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() }
|
||||
#[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(std::any::type_name::<$param>()),*].into_boxed_slice() }
|
||||
#[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::<RET>() }
|
||||
@ -154,7 +154,7 @@ macro_rules! def_register {
|
||||
FN: for<'a> Fn(NativeCallContext<'a>, $($param),*) -> RET + SendSync + 'static,
|
||||
$($par: Variant + Clone,)*
|
||||
RET: Variant + Clone
|
||||
> RegisterNativeFunction<(NativeCallContext<'static>, $($mark,)*), ()> for FN {
|
||||
> RegisterNativeFunction<($($mark,)*), RET, NativeCallContext<'static>> for FN {
|
||||
#[inline(always)] fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() }
|
||||
#[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(std::any::type_name::<$param>()),*].into_boxed_slice() }
|
||||
#[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::<RET>() }
|
||||
@ -180,7 +180,7 @@ macro_rules! def_register {
|
||||
FN: Fn($($param),*) -> RhaiResultOf<RET> + SendSync + 'static,
|
||||
$($par: Variant + Clone,)*
|
||||
RET: Variant + Clone
|
||||
> RegisterNativeFunction<($($mark,)*), RhaiResultOf<RET>> for FN {
|
||||
> RegisterNativeFunction<($($mark,)*), RET, RhaiResultOf<()>> for FN {
|
||||
#[inline(always)] fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() }
|
||||
#[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(std::any::type_name::<$param>()),*].into_boxed_slice() }
|
||||
#[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::<RhaiResultOf<RET>>() }
|
||||
@ -203,7 +203,7 @@ macro_rules! def_register {
|
||||
FN: for<'a> Fn(NativeCallContext<'a>, $($param),*) -> RhaiResultOf<RET> + SendSync + 'static,
|
||||
$($par: Variant + Clone,)*
|
||||
RET: Variant + Clone
|
||||
> RegisterNativeFunction<(NativeCallContext<'static>, $($mark,)*), RhaiResultOf<RET>> for FN {
|
||||
> RegisterNativeFunction<($($mark,)*), RET, RhaiResultOf<NativeCallContext<'static>>> for FN {
|
||||
#[inline(always)] fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() }
|
||||
#[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(std::any::type_name::<$param>()),*].into_boxed_slice() }
|
||||
#[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::<RhaiResultOf<RET>>() }
|
||||
|
@ -1,6 +1,7 @@
|
||||
//! Module defining external-loaded modules for Rhai.
|
||||
|
||||
use crate::ast::FnAccess;
|
||||
use crate::func::register::Mut;
|
||||
use crate::func::{
|
||||
shared_take_or_clone, CallableFunction, FnCallArgs, IteratorFn, RegisterNativeFunction,
|
||||
SendSync,
|
||||
@ -1290,11 +1291,11 @@ impl Module {
|
||||
/// assert!(module.contains_fn(hash));
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub fn set_native_fn<ARGS, N, T, F>(&mut self, name: N, func: F) -> u64
|
||||
pub fn set_native_fn<ARGS, N, T, F, S>(&mut self, name: N, func: F) -> u64
|
||||
where
|
||||
N: AsRef<str> + Into<Identifier>,
|
||||
T: Variant + Clone,
|
||||
F: RegisterNativeFunction<ARGS, RhaiResultOf<T>>,
|
||||
F: RegisterNativeFunction<ARGS, T, RhaiResultOf<S>>,
|
||||
{
|
||||
self.set_fn(
|
||||
name,
|
||||
@ -1326,14 +1327,11 @@ impl Module {
|
||||
/// ```
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
#[inline(always)]
|
||||
pub fn set_getter_fn<ARGS, A, T, F>(&mut self, name: impl AsRef<str>, func: F) -> u64
|
||||
pub fn set_getter_fn<A, T, F, S>(&mut self, name: impl AsRef<str>, func: F) -> u64
|
||||
where
|
||||
A: Variant + Clone,
|
||||
T: Variant + Clone,
|
||||
F: RegisterNativeFunction<ARGS, RhaiResultOf<T>>
|
||||
+ Fn(&mut A) -> RhaiResultOf<T>
|
||||
+ SendSync
|
||||
+ 'static,
|
||||
F: RegisterNativeFunction<(Mut<A>,), T, RhaiResultOf<S>> + SendSync + 'static,
|
||||
{
|
||||
self.set_fn(
|
||||
crate::engine::make_getter(name.as_ref()).as_str(),
|
||||
@ -1370,14 +1368,11 @@ impl Module {
|
||||
/// ```
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
#[inline(always)]
|
||||
pub fn set_setter_fn<ARGS, A, B, F>(&mut self, name: impl AsRef<str>, func: F) -> u64
|
||||
pub fn set_setter_fn<A, T, F, S>(&mut self, name: impl AsRef<str>, func: F) -> u64
|
||||
where
|
||||
A: Variant + Clone,
|
||||
B: Variant + Clone,
|
||||
F: RegisterNativeFunction<ARGS, RhaiResultOf<()>>
|
||||
+ Fn(&mut A, B) -> RhaiResultOf<()>
|
||||
+ SendSync
|
||||
+ 'static,
|
||||
T: Variant + Clone,
|
||||
F: RegisterNativeFunction<(Mut<A>, T), (), RhaiResultOf<S>> + SendSync + 'static,
|
||||
{
|
||||
self.set_fn(
|
||||
crate::engine::make_setter(name.as_ref()).as_str(),
|
||||
@ -1389,6 +1384,48 @@ impl Module {
|
||||
)
|
||||
}
|
||||
|
||||
/// Set a pair of Rust getter and setter functions into the [`Module`], returning both non-zero hash keys.
|
||||
/// This is a short-hand for [`set_getter_fn`][Module::set_getter_fn] and [`set_setter_fn`][Module::set_setter_fn].
|
||||
///
|
||||
/// These function are automatically exposed to the global namespace.
|
||||
///
|
||||
/// If there are similar existing Rust functions, they are replaced.
|
||||
///
|
||||
/// # Function Metadata
|
||||
///
|
||||
/// No metadata for the function is registered.
|
||||
/// Use [`update_fn_metadata`][Module::update_fn_metadata] to add metadata.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::{Module, ImmutableString};
|
||||
///
|
||||
/// let mut module = Module::new();
|
||||
/// let (hash_get, hash_set) = module.set_getter_setter_fn("value",
|
||||
/// |x: &mut i64| { Ok(x.to_string().into()) },
|
||||
/// |x: &mut i64, y: ImmutableString| {
|
||||
/// *x = y.len() as i64;
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// );
|
||||
/// assert!(module.contains_fn(hash_get));
|
||||
/// assert!(module.contains_fn(hash_set));
|
||||
/// ```
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
#[inline(always)]
|
||||
pub fn set_getter_setter_fn<A: Variant + Clone, T: Variant + Clone, S1, S2>(
|
||||
&mut self,
|
||||
name: impl AsRef<str>,
|
||||
getter: impl RegisterNativeFunction<(Mut<A>,), T, RhaiResultOf<S1>> + SendSync + 'static,
|
||||
setter: impl RegisterNativeFunction<(Mut<A>, T), (), RhaiResultOf<S2>> + SendSync + 'static,
|
||||
) -> (u64, u64) {
|
||||
(
|
||||
self.set_getter_fn(name.as_ref(), getter),
|
||||
self.set_setter_fn(name.as_ref(), setter),
|
||||
)
|
||||
}
|
||||
|
||||
/// Set a Rust index getter taking two parameters (the first one mutable) into the [`Module`],
|
||||
/// returning a non-zero hash key.
|
||||
/// This function is automatically exposed to the global namespace.
|
||||
@ -1418,15 +1455,12 @@ impl Module {
|
||||
/// ```
|
||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||
#[inline]
|
||||
pub fn set_indexer_get_fn<ARGS, A, B, T, F>(&mut self, func: F) -> u64
|
||||
pub fn set_indexer_get_fn<A, B, T, F, S>(&mut self, func: F) -> u64
|
||||
where
|
||||
A: Variant + Clone,
|
||||
B: Variant + Clone,
|
||||
T: Variant + Clone,
|
||||
F: RegisterNativeFunction<ARGS, RhaiResultOf<T>>
|
||||
+ Fn(&mut A, B) -> RhaiResultOf<T>
|
||||
+ SendSync
|
||||
+ 'static,
|
||||
F: RegisterNativeFunction<(Mut<A>, B), T, RhaiResultOf<S>> + SendSync + 'static,
|
||||
{
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
if TypeId::of::<A>() == TypeId::of::<crate::Array>() {
|
||||
@ -1482,15 +1516,12 @@ impl Module {
|
||||
/// ```
|
||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||
#[inline]
|
||||
pub fn set_indexer_set_fn<ARGS, A, B, C, F>(&mut self, func: F) -> u64
|
||||
pub fn set_indexer_set_fn<A, B, T, F, S>(&mut self, func: F) -> u64
|
||||
where
|
||||
A: Variant + Clone,
|
||||
B: Variant + Clone,
|
||||
C: Variant + Clone,
|
||||
F: RegisterNativeFunction<ARGS, RhaiResultOf<()>>
|
||||
+ Fn(&mut A, B, C) -> RhaiResultOf<()>
|
||||
+ SendSync
|
||||
+ 'static,
|
||||
T: Variant + Clone,
|
||||
F: RegisterNativeFunction<(Mut<A>, B, T), (), RhaiResultOf<S>> + SendSync + 'static,
|
||||
{
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
if TypeId::of::<A>() == TypeId::of::<crate::Array>() {
|
||||
@ -1517,10 +1548,12 @@ impl Module {
|
||||
)
|
||||
}
|
||||
|
||||
/// Set a pair of Rust index getter and setter functions, returning both non-zero hash keys.
|
||||
/// Set a pair of Rust index getter and setter functions into the [`Module`], returning both non-zero hash keys.
|
||||
/// This is a short-hand for [`set_indexer_get_fn`][Module::set_indexer_get_fn] and
|
||||
/// [`set_indexer_set_fn`][Module::set_indexer_set_fn].
|
||||
///
|
||||
/// These functions are automatically exposed to the global namespace.
|
||||
///
|
||||
/// If there are similar existing Rust functions, they are replaced.
|
||||
///
|
||||
/// # Panics
|
||||
@ -1552,10 +1585,10 @@ impl Module {
|
||||
/// ```
|
||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||
#[inline(always)]
|
||||
pub fn set_indexer_get_set_fn<A, B, T>(
|
||||
pub fn set_indexer_get_set_fn<A, B, T, S1, S2>(
|
||||
&mut self,
|
||||
get_fn: impl Fn(&mut A, B) -> RhaiResultOf<T> + SendSync + 'static,
|
||||
set_fn: impl Fn(&mut A, B, T) -> RhaiResultOf<()> + SendSync + 'static,
|
||||
get_fn: impl RegisterNativeFunction<(Mut<A>, B), T, RhaiResultOf<S1>> + SendSync + 'static,
|
||||
set_fn: impl RegisterNativeFunction<(Mut<A>, B, T), (), RhaiResultOf<S2>> + SendSync + 'static,
|
||||
) -> (u64, u64)
|
||||
where
|
||||
A: Variant + Clone,
|
||||
@ -2016,7 +2049,7 @@ impl Module {
|
||||
if let Some(fn_ptr) = value.downcast_ref::<crate::FnPtr>() {
|
||||
if ast.iter_fn_def().any(|f| f.name == fn_ptr.fn_name()) {
|
||||
return Err(crate::ERR::ErrorMismatchDataType(
|
||||
"".to_string(),
|
||||
String::new(),
|
||||
if fn_ptr.is_anonymous() {
|
||||
format!("cannot export closure in variable {_name}")
|
||||
} else {
|
||||
@ -2217,29 +2250,23 @@ impl Module {
|
||||
}
|
||||
|
||||
/// Set a type iterator into the [`Module`].
|
||||
#[cfg(not(feature = "sync"))]
|
||||
#[inline]
|
||||
pub fn set_iter(
|
||||
&mut self,
|
||||
type_id: TypeId,
|
||||
func: impl Fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>> + 'static,
|
||||
) -> &mut Self {
|
||||
let func = Shared::new(func);
|
||||
if self.indexed {
|
||||
self.all_type_iterators.insert(type_id, func.clone());
|
||||
self.contains_indexed_global_functions = true;
|
||||
}
|
||||
self.type_iterators.insert(type_id, func);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set a type iterator into the [`Module`].
|
||||
#[cfg(feature = "sync")]
|
||||
#[inline]
|
||||
#[inline(always)]
|
||||
pub fn set_iter(
|
||||
&mut self,
|
||||
type_id: TypeId,
|
||||
func: impl Fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>> + SendSync + 'static,
|
||||
) -> &mut Self {
|
||||
self.set_iter_result(type_id, move |x| {
|
||||
Box::new(func(x).map(Ok)) as Box<dyn Iterator<Item = RhaiResultOf<Dynamic>>>
|
||||
})
|
||||
}
|
||||
|
||||
/// Set a fallible type iterator into the [`Module`].
|
||||
#[inline]
|
||||
pub fn set_iter_result(
|
||||
&mut self,
|
||||
type_id: TypeId,
|
||||
func: impl Fn(Dynamic) -> Box<dyn Iterator<Item = RhaiResultOf<Dynamic>>> + SendSync + 'static,
|
||||
) -> &mut Self {
|
||||
let func = Shared::new(func);
|
||||
if self.indexed {
|
||||
@ -2251,7 +2278,7 @@ impl Module {
|
||||
}
|
||||
|
||||
/// Set a type iterator into the [`Module`].
|
||||
#[inline]
|
||||
#[inline(always)]
|
||||
pub fn set_iterable<T>(&mut self) -> &mut Self
|
||||
where
|
||||
T: Variant + Clone + IntoIterator,
|
||||
@ -2262,8 +2289,20 @@ impl Module {
|
||||
})
|
||||
}
|
||||
|
||||
/// Set a fallible type iterator into the [`Module`].
|
||||
#[inline(always)]
|
||||
pub fn set_iterable_result<T, X>(&mut self) -> &mut Self
|
||||
where
|
||||
T: Variant + Clone + IntoIterator<Item = RhaiResultOf<X>>,
|
||||
X: Variant + Clone,
|
||||
{
|
||||
self.set_iter_result(TypeId::of::<T>(), |obj: Dynamic| {
|
||||
Box::new(obj.cast::<T>().into_iter().map(|v| v.map(Dynamic::from)))
|
||||
})
|
||||
}
|
||||
|
||||
/// Set an iterator type into the [`Module`] as a type iterator.
|
||||
#[inline]
|
||||
#[inline(always)]
|
||||
pub fn set_iterator<T>(&mut self) -> &mut Self
|
||||
where
|
||||
T: Variant + Clone + Iterator,
|
||||
@ -2274,6 +2313,18 @@ impl Module {
|
||||
})
|
||||
}
|
||||
|
||||
/// Set a iterator type into the [`Module`] as a fallible type iterator.
|
||||
#[inline(always)]
|
||||
pub fn set_iterator_result<T, X>(&mut self) -> &mut Self
|
||||
where
|
||||
T: Variant + Clone + Iterator<Item = RhaiResultOf<X>>,
|
||||
X: Variant + Clone,
|
||||
{
|
||||
self.set_iter_result(TypeId::of::<T>(), |obj: Dynamic| {
|
||||
Box::new(obj.cast::<T>().map(|v| v.map(Dynamic::from)))
|
||||
})
|
||||
}
|
||||
|
||||
/// Get the specified type iterator.
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
#[inline]
|
||||
|
@ -2051,12 +2051,12 @@ impl Engine {
|
||||
Ok(Stmt::Assignment((op_info, (lhs, rhs).into()).into()))
|
||||
}
|
||||
// expr[???] = rhs, expr.??? = rhs
|
||||
ref expr => Err(PERR::AssignmentToInvalidLHS("".to_string())
|
||||
ref expr => Err(PERR::AssignmentToInvalidLHS(String::new())
|
||||
.into_err(expr.position())),
|
||||
}
|
||||
}
|
||||
Some(err_pos) => {
|
||||
Err(PERR::AssignmentToInvalidLHS("".to_string()).into_err(err_pos))
|
||||
Err(PERR::AssignmentToInvalidLHS(String::new()).into_err(err_pos))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2067,7 +2067,7 @@ impl Engine {
|
||||
)
|
||||
.into_err(op_pos)),
|
||||
// expr = rhs
|
||||
_ => Err(PERR::AssignmentToInvalidLHS("".to_string()).into_err(lhs.position())),
|
||||
_ => Err(PERR::AssignmentToInvalidLHS(String::new()).into_err(lhs.position())),
|
||||
}
|
||||
}
|
||||
|
||||
@ -3665,8 +3665,9 @@ impl Engine {
|
||||
(Token::Pipe, ..) => break,
|
||||
(Token::Identifier(s), pos) => {
|
||||
if params_list.iter().any(|p| p.as_str() == &*s) {
|
||||
return Err(PERR::FnDuplicatedParam("".to_string(), s.to_string())
|
||||
.into_err(pos));
|
||||
return Err(
|
||||
PERR::FnDuplicatedParam(String::new(), s.to_string()).into_err(pos)
|
||||
);
|
||||
}
|
||||
let s = state.get_interned_string(s);
|
||||
state.stack.push(s.clone(), ());
|
||||
|
@ -51,8 +51,7 @@ impl fmt::Display for LexError {
|
||||
Self::ImproperSymbol(s, d) if d.is_empty() => {
|
||||
write!(f, "Invalid symbol encountered: '{}'", s)
|
||||
}
|
||||
Self::ImproperSymbol(s, d) if s.is_empty() => f.write_str(d),
|
||||
Self::ImproperSymbol(s, d) => write!(f, "{}: '{}'", d, s),
|
||||
Self::ImproperSymbol(.., d) => f.write_str(d),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,28 +25,28 @@ fn test_assignments_bad_lhs() -> Result<(), Box<EvalAltResult>> {
|
||||
.compile("(x+y) = 42;")
|
||||
.expect_err("should error")
|
||||
.err_type(),
|
||||
ParseErrorType::AssignmentToInvalidLHS("".to_string())
|
||||
ParseErrorType::AssignmentToInvalidLHS(String::new())
|
||||
);
|
||||
assert_eq!(
|
||||
*engine
|
||||
.compile("foo(x) = 42;")
|
||||
.expect_err("should error")
|
||||
.err_type(),
|
||||
ParseErrorType::AssignmentToInvalidLHS("".to_string())
|
||||
ParseErrorType::AssignmentToInvalidLHS(String::new())
|
||||
);
|
||||
assert_eq!(
|
||||
*engine
|
||||
.compile("true = 42;")
|
||||
.expect_err("should error")
|
||||
.err_type(),
|
||||
ParseErrorType::AssignmentToConstant("".to_string())
|
||||
ParseErrorType::AssignmentToConstant(String::new())
|
||||
);
|
||||
assert_eq!(
|
||||
*engine
|
||||
.compile("123 = 42;")
|
||||
.expect_err("should error")
|
||||
.err_type(),
|
||||
ParseErrorType::AssignmentToConstant("".to_string())
|
||||
ParseErrorType::AssignmentToConstant(String::new())
|
||||
);
|
||||
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
@ -56,21 +56,21 @@ fn test_assignments_bad_lhs() -> Result<(), Box<EvalAltResult>> {
|
||||
.compile("x.foo() = 42;")
|
||||
.expect_err("should error")
|
||||
.err_type(),
|
||||
ParseErrorType::AssignmentToInvalidLHS("".to_string())
|
||||
ParseErrorType::AssignmentToInvalidLHS(String::new())
|
||||
);
|
||||
assert_eq!(
|
||||
*engine
|
||||
.compile("x.foo().x.y = 42;")
|
||||
.expect_err("should error")
|
||||
.err_type(),
|
||||
ParseErrorType::AssignmentToInvalidLHS("".to_string())
|
||||
ParseErrorType::AssignmentToInvalidLHS(String::new())
|
||||
);
|
||||
assert_eq!(
|
||||
*engine
|
||||
.compile("x.y.z.foo() = 42;")
|
||||
.expect_err("should error")
|
||||
.err_type(),
|
||||
ParseErrorType::AssignmentToInvalidLHS("".to_string())
|
||||
ParseErrorType::AssignmentToInvalidLHS(String::new())
|
||||
);
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
assert_eq!(
|
||||
@ -78,7 +78,7 @@ fn test_assignments_bad_lhs() -> Result<(), Box<EvalAltResult>> {
|
||||
.compile("x.foo()[0] = 42;")
|
||||
.expect_err("should error")
|
||||
.err_type(),
|
||||
ParseErrorType::AssignmentToInvalidLHS("".to_string())
|
||||
ParseErrorType::AssignmentToInvalidLHS(String::new())
|
||||
);
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
assert_eq!(
|
||||
@ -86,7 +86,7 @@ fn test_assignments_bad_lhs() -> Result<(), Box<EvalAltResult>> {
|
||||
.compile("x[y].z.foo() = 42;")
|
||||
.expect_err("should error")
|
||||
.err_type(),
|
||||
ParseErrorType::AssignmentToInvalidLHS("".to_string())
|
||||
ParseErrorType::AssignmentToInvalidLHS(String::new())
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -303,7 +303,7 @@ fn test_custom_syntax_raw() -> Result<(), Box<EvalAltResult>> {
|
||||
.compile("hello hey")
|
||||
.expect_err("should error")
|
||||
.err_type(),
|
||||
ParseErrorType::BadInput(LexError::ImproperSymbol("hey".to_string(), "".to_string()))
|
||||
ParseErrorType::BadInput(LexError::ImproperSymbol("hey".to_string(), String::new()))
|
||||
);
|
||||
|
||||
Ok(())
|
||||
|
@ -1,6 +1,6 @@
|
||||
#![cfg(not(feature = "no_object"))]
|
||||
|
||||
use rhai::{Engine, EvalAltResult, Scope, INT};
|
||||
use rhai::{Engine, EvalAltResult, NativeCallContext, Scope, INT};
|
||||
|
||||
#[test]
|
||||
fn test_get_set() -> Result<(), Box<EvalAltResult>> {
|
||||
@ -217,12 +217,14 @@ fn test_get_set_chain_without_write_back() -> Result<(), Box<EvalAltResult>> {
|
||||
.register_get_set(
|
||||
"value",
|
||||
|t: &mut Inner| t.value,
|
||||
|_: &mut Inner, new: INT| panic!("Inner::value setter called with {}", new),
|
||||
|_: NativeCallContext, _: &mut Inner, new: INT| {
|
||||
panic!("Inner::value setter called with {}", new)
|
||||
},
|
||||
)
|
||||
.register_type::<Outer>()
|
||||
.register_get_set(
|
||||
"inner",
|
||||
|t: &mut Outer| t.inner.clone(),
|
||||
|_: NativeCallContext, t: &mut Outer| t.inner.clone(),
|
||||
|_: &mut Outer, new: Inner| panic!("Outer::inner setter called with {:?}", new),
|
||||
);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user