commit
3078a281b2
18
CHANGELOG.md
18
CHANGELOG.md
@ -1,6 +1,24 @@
|
|||||||
Rhai Release Notes
|
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
|
Version 1.9.0
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
@ -125,10 +125,10 @@ impl<'a, T: Variant + Clone> TypeBuilder<'a, T> {
|
|||||||
|
|
||||||
/// Register a custom function.
|
/// Register a custom function.
|
||||||
#[inline(always)]
|
#[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
|
where
|
||||||
N: AsRef<str> + Into<Identifier>,
|
N: AsRef<str> + Into<Identifier>,
|
||||||
F: RegisterNativeFunction<A, ()>,
|
F: RegisterNativeFunction<A, R, S>,
|
||||||
{
|
{
|
||||||
self.engine.register_fn(name, method);
|
self.engine.register_fn(name, method);
|
||||||
self
|
self
|
||||||
@ -136,10 +136,10 @@ impl<'a, T: Variant + Clone> TypeBuilder<'a, T> {
|
|||||||
|
|
||||||
/// Register a custom fallible function.
|
/// Register a custom fallible function.
|
||||||
#[inline(always)]
|
#[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
|
where
|
||||||
N: AsRef<str> + Into<Identifier>,
|
N: AsRef<str> + Into<Identifier>,
|
||||||
F: RegisterNativeFunction<A, RhaiResultOf<R>>,
|
F: RegisterNativeFunction<A, R, RhaiResultOf<S>>,
|
||||||
{
|
{
|
||||||
self.engine.register_result_fn(name, method);
|
self.engine.register_result_fn(name, method);
|
||||||
self
|
self
|
||||||
|
@ -72,16 +72,13 @@ impl Engine {
|
|||||||
Token::LeftBrace => Token::MapStart,
|
Token::LeftBrace => Token::MapStart,
|
||||||
// Disallowed syntax
|
// Disallowed syntax
|
||||||
t @ (Token::Unit | Token::MapStart) => Token::LexError(
|
t @ (Token::Unit | Token::MapStart) => Token::LexError(
|
||||||
LexError::ImproperSymbol(
|
LexError::ImproperSymbol(t.literal_syntax().to_string(), String::new())
|
||||||
t.literal_syntax().to_string(),
|
|
||||||
"".to_string(),
|
|
||||||
)
|
|
||||||
.into(),
|
.into(),
|
||||||
),
|
),
|
||||||
Token::InterpolatedString(..) => Token::LexError(
|
Token::InterpolatedString(..) => Token::LexError(
|
||||||
LexError::ImproperSymbol(
|
LexError::ImproperSymbol(
|
||||||
"interpolated string".to_string(),
|
"interpolated string".to_string(),
|
||||||
"".to_string(),
|
String::new(),
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
),
|
),
|
||||||
@ -93,7 +90,7 @@ impl Engine {
|
|||||||
Some(&|token, _, _| {
|
Some(&|token, _, _| {
|
||||||
match token {
|
match token {
|
||||||
Token::Reserved(s) if &*s == "null" => Token::LexError(
|
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,
|
Token::LeftBrace => Token::MapStart,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
//! Module that defines the public function/module registration API of [`Engine`].
|
//! Module that defines the public function/module registration API of [`Engine`].
|
||||||
|
|
||||||
|
use crate::func::register::Mut;
|
||||||
use crate::func::{FnCallArgs, RegisterNativeFunction, SendSync};
|
use crate::func::{FnCallArgs, RegisterNativeFunction, SendSync};
|
||||||
use crate::types::dynamic::Variant;
|
use crate::types::dynamic::Variant;
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -50,10 +51,10 @@ impl Engine {
|
|||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[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
|
where
|
||||||
N: AsRef<str> + Into<Identifier>,
|
N: AsRef<str> + Into<Identifier>,
|
||||||
F: RegisterNativeFunction<A, ()>,
|
F: RegisterNativeFunction<A, R, S>,
|
||||||
{
|
{
|
||||||
let param_types = F::param_types();
|
let param_types = F::param_types();
|
||||||
|
|
||||||
@ -112,10 +113,10 @@ impl Engine {
|
|||||||
/// .expect_err("expecting division by zero error!");
|
/// .expect_err("expecting division by zero error!");
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[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
|
where
|
||||||
N: AsRef<str> + Into<Identifier>,
|
N: AsRef<str> + Into<Identifier>,
|
||||||
F: RegisterNativeFunction<A, RhaiResultOf<R>>,
|
F: RegisterNativeFunction<A, R, RhaiResultOf<S>>,
|
||||||
{
|
{
|
||||||
let param_types = F::param_types();
|
let param_types = F::param_types();
|
||||||
|
|
||||||
@ -291,7 +292,7 @@ impl Engine {
|
|||||||
.set_custom_type_raw(fully_qualified_type_path, name);
|
.set_custom_type_raw(fully_qualified_type_path, name);
|
||||||
self
|
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.
|
/// This is an advanced API.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn register_iterator<T>(&mut self) -> &mut Self
|
pub fn register_iterator<T>(&mut self) -> &mut Self
|
||||||
@ -302,6 +303,17 @@ impl Engine {
|
|||||||
self.global_namespace_mut().set_iterable::<T>();
|
self.global_namespace_mut().set_iterable::<T>();
|
||||||
self
|
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`].
|
/// 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`.
|
/// The function signature must start with `&mut self` and not `&self`.
|
||||||
@ -344,10 +356,10 @@ impl Engine {
|
|||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
#[inline(always)]
|
#[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,
|
&mut self,
|
||||||
name: impl AsRef<str>,
|
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 {
|
) -> &mut Self {
|
||||||
self.register_fn(crate::engine::make_getter(name.as_ref()).as_str(), get_fn)
|
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"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
#[inline(always)]
|
#[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,
|
&mut self,
|
||||||
name: impl AsRef<str>,
|
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 {
|
) -> &mut Self {
|
||||||
self.register_result_fn(crate::engine::make_getter(name.as_ref()).as_str(), get_fn)
|
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"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
#[inline(always)]
|
#[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,
|
&mut self,
|
||||||
name: impl AsRef<str>,
|
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 {
|
) -> &mut Self {
|
||||||
self.register_fn(crate::engine::make_setter(name.as_ref()).as_str(), set_fn)
|
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"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
#[inline(always)]
|
#[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,
|
&mut self,
|
||||||
name: impl AsRef<str>,
|
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 {
|
) -> &mut Self {
|
||||||
self.register_result_fn(crate::engine::make_setter(name.as_ref()).as_str(), set_fn)
|
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"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
#[inline(always)]
|
#[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,
|
&mut self,
|
||||||
name: impl AsRef<str>,
|
name: impl AsRef<str>,
|
||||||
get_fn: impl Fn(&mut T) -> V + SendSync + 'static,
|
get_fn: impl RegisterNativeFunction<(Mut<T>,), V, S1> + SendSync + 'static,
|
||||||
set_fn: impl Fn(&mut T, V) + SendSync + 'static,
|
set_fn: impl RegisterNativeFunction<(Mut<T>, V), (), S2> + SendSync + 'static,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
self.register_get(&name, get_fn).register_set(&name, set_fn)
|
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")))]
|
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||||
#[inline]
|
#[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,
|
&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 {
|
) -> &mut Self {
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
if TypeId::of::<T>() == TypeId::of::<crate::Array>() {
|
if TypeId::of::<T>() == TypeId::of::<crate::Array>() {
|
||||||
@ -686,9 +698,10 @@ impl Engine {
|
|||||||
T: Variant + Clone,
|
T: Variant + Clone,
|
||||||
X: Variant + Clone,
|
X: Variant + Clone,
|
||||||
V: Variant + Clone,
|
V: Variant + Clone,
|
||||||
|
S,
|
||||||
>(
|
>(
|
||||||
&mut self,
|
&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 {
|
) -> &mut Self {
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
if TypeId::of::<T>() == TypeId::of::<crate::Array>() {
|
if TypeId::of::<T>() == TypeId::of::<crate::Array>() {
|
||||||
@ -761,9 +774,9 @@ impl Engine {
|
|||||||
/// ```
|
/// ```
|
||||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||||
#[inline]
|
#[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,
|
&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 {
|
) -> &mut Self {
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
if TypeId::of::<T>() == TypeId::of::<crate::Array>() {
|
if TypeId::of::<T>() == TypeId::of::<crate::Array>() {
|
||||||
@ -841,9 +854,10 @@ impl Engine {
|
|||||||
T: Variant + Clone,
|
T: Variant + Clone,
|
||||||
X: Variant + Clone,
|
X: Variant + Clone,
|
||||||
V: Variant + Clone,
|
V: Variant + Clone,
|
||||||
|
S,
|
||||||
>(
|
>(
|
||||||
&mut self,
|
&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 {
|
) -> &mut Self {
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
if TypeId::of::<T>() == TypeId::of::<crate::Array>() {
|
if TypeId::of::<T>() == TypeId::of::<crate::Array>() {
|
||||||
@ -917,10 +931,16 @@ impl Engine {
|
|||||||
/// ```
|
/// ```
|
||||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||||
#[inline(always)]
|
#[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,
|
&mut self,
|
||||||
get_fn: impl Fn(&mut T, X) -> V + SendSync + 'static,
|
get_fn: impl RegisterNativeFunction<(Mut<T>, X), V, S1> + SendSync + 'static,
|
||||||
set_fn: impl Fn(&mut T, X, V) + SendSync + 'static,
|
set_fn: impl RegisterNativeFunction<(Mut<T>, X, V), (), S2> + SendSync + 'static,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
self.register_indexer_get(get_fn)
|
self.register_indexer_get(get_fn)
|
||||||
.register_indexer_set(set_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 {
|
let line_no = if lines.len() > 1 {
|
||||||
if pos.is_none() {
|
if pos.is_none() {
|
||||||
"".to_string()
|
String::new()
|
||||||
} else {
|
} else {
|
||||||
format!("{}: ", pos.line().unwrap())
|
format!("{}: ", pos.line().unwrap())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
"".to_string()
|
String::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Print error position
|
// Print error position
|
||||||
|
@ -15,12 +15,12 @@ fn print_error(input: &str, mut err: EvalAltResult) {
|
|||||||
|
|
||||||
let line_no = if lines.len() > 1 {
|
let line_no = if lines.len() > 1 {
|
||||||
if pos.is_none() {
|
if pos.is_none() {
|
||||||
"".to_string()
|
String::new()
|
||||||
} else {
|
} else {
|
||||||
format!("{}: ", pos.line().unwrap())
|
format!("{}: ", pos.line().unwrap())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
"".to_string()
|
String::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Print error position
|
// Print error position
|
||||||
|
@ -641,38 +641,21 @@ impl Engine {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let index_value = (x as INT).into();
|
let index_value = Dynamic::from(x as INT);
|
||||||
|
|
||||||
#[cfg(not(feature = "no_closure"))]
|
*scope.get_mut_by_index(counter_index).write_lock().unwrap() =
|
||||||
{
|
index_value;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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"))]
|
*scope.get_mut_by_index(index).write_lock().unwrap() = value;
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
if let Err(err) = self
|
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.
|
/// Function that gets an iterator from a type.
|
||||||
#[cfg(not(feature = "sync"))]
|
#[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.
|
/// Function that gets an iterator from a type.
|
||||||
#[cfg(feature = "sync")]
|
#[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"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
pub type FnPlugin = dyn PluginFunction;
|
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.
|
/// Trait to register custom Rust functions.
|
||||||
pub trait RegisterNativeFunction<Args, Result> {
|
pub trait RegisterNativeFunction<ARGS, RET, RESULT> {
|
||||||
/// Convert this function into a [`CallableFunction`].
|
/// Convert this function into a [`CallableFunction`].
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn into_callable_function(self) -> CallableFunction;
|
fn into_callable_function(self) -> CallableFunction;
|
||||||
@ -128,7 +128,7 @@ macro_rules! def_register {
|
|||||||
FN: Fn($($param),*) -> RET + SendSync + 'static,
|
FN: Fn($($param),*) -> RET + SendSync + 'static,
|
||||||
$($par: Variant + Clone,)*
|
$($par: Variant + Clone,)*
|
||||||
RET: 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() }
|
#[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 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>() }
|
#[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,
|
FN: for<'a> Fn(NativeCallContext<'a>, $($param),*) -> RET + SendSync + 'static,
|
||||||
$($par: Variant + Clone,)*
|
$($par: Variant + Clone,)*
|
||||||
RET: 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() }
|
#[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 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>() }
|
#[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,
|
FN: Fn($($param),*) -> RhaiResultOf<RET> + SendSync + 'static,
|
||||||
$($par: Variant + Clone,)*
|
$($par: Variant + Clone,)*
|
||||||
RET: 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() }
|
#[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 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>>() }
|
#[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,
|
FN: for<'a> Fn(NativeCallContext<'a>, $($param),*) -> RhaiResultOf<RET> + SendSync + 'static,
|
||||||
$($par: Variant + Clone,)*
|
$($par: Variant + Clone,)*
|
||||||
RET: 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() }
|
#[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 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>>() }
|
#[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::<RhaiResultOf<RET>>() }
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
//! Module defining external-loaded modules for Rhai.
|
//! Module defining external-loaded modules for Rhai.
|
||||||
|
|
||||||
use crate::ast::FnAccess;
|
use crate::ast::FnAccess;
|
||||||
|
use crate::func::register::Mut;
|
||||||
use crate::func::{
|
use crate::func::{
|
||||||
shared_take_or_clone, CallableFunction, FnCallArgs, IteratorFn, RegisterNativeFunction,
|
shared_take_or_clone, CallableFunction, FnCallArgs, IteratorFn, RegisterNativeFunction,
|
||||||
SendSync,
|
SendSync,
|
||||||
@ -1290,11 +1291,11 @@ impl Module {
|
|||||||
/// assert!(module.contains_fn(hash));
|
/// assert!(module.contains_fn(hash));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[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
|
where
|
||||||
N: AsRef<str> + Into<Identifier>,
|
N: AsRef<str> + Into<Identifier>,
|
||||||
T: Variant + Clone,
|
T: Variant + Clone,
|
||||||
F: RegisterNativeFunction<ARGS, RhaiResultOf<T>>,
|
F: RegisterNativeFunction<ARGS, T, RhaiResultOf<S>>,
|
||||||
{
|
{
|
||||||
self.set_fn(
|
self.set_fn(
|
||||||
name,
|
name,
|
||||||
@ -1326,14 +1327,11 @@ impl Module {
|
|||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
#[inline(always)]
|
#[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
|
where
|
||||||
A: Variant + Clone,
|
A: Variant + Clone,
|
||||||
T: Variant + Clone,
|
T: Variant + Clone,
|
||||||
F: RegisterNativeFunction<ARGS, RhaiResultOf<T>>
|
F: RegisterNativeFunction<(Mut<A>,), T, RhaiResultOf<S>> + SendSync + 'static,
|
||||||
+ Fn(&mut A) -> RhaiResultOf<T>
|
|
||||||
+ SendSync
|
|
||||||
+ 'static,
|
|
||||||
{
|
{
|
||||||
self.set_fn(
|
self.set_fn(
|
||||||
crate::engine::make_getter(name.as_ref()).as_str(),
|
crate::engine::make_getter(name.as_ref()).as_str(),
|
||||||
@ -1370,14 +1368,11 @@ impl Module {
|
|||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
#[inline(always)]
|
#[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
|
where
|
||||||
A: Variant + Clone,
|
A: Variant + Clone,
|
||||||
B: Variant + Clone,
|
T: Variant + Clone,
|
||||||
F: RegisterNativeFunction<ARGS, RhaiResultOf<()>>
|
F: RegisterNativeFunction<(Mut<A>, T), (), RhaiResultOf<S>> + SendSync + 'static,
|
||||||
+ Fn(&mut A, B) -> RhaiResultOf<()>
|
|
||||||
+ SendSync
|
|
||||||
+ 'static,
|
|
||||||
{
|
{
|
||||||
self.set_fn(
|
self.set_fn(
|
||||||
crate::engine::make_setter(name.as_ref()).as_str(),
|
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`],
|
/// Set a Rust index getter taking two parameters (the first one mutable) into the [`Module`],
|
||||||
/// returning a non-zero hash key.
|
/// returning a non-zero hash key.
|
||||||
/// This function is automatically exposed to the global namespace.
|
/// 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")))]
|
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||||
#[inline]
|
#[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
|
where
|
||||||
A: Variant + Clone,
|
A: Variant + Clone,
|
||||||
B: Variant + Clone,
|
B: Variant + Clone,
|
||||||
T: Variant + Clone,
|
T: Variant + Clone,
|
||||||
F: RegisterNativeFunction<ARGS, RhaiResultOf<T>>
|
F: RegisterNativeFunction<(Mut<A>, B), T, RhaiResultOf<S>> + SendSync + 'static,
|
||||||
+ Fn(&mut A, B) -> RhaiResultOf<T>
|
|
||||||
+ SendSync
|
|
||||||
+ 'static,
|
|
||||||
{
|
{
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
if TypeId::of::<A>() == TypeId::of::<crate::Array>() {
|
if TypeId::of::<A>() == TypeId::of::<crate::Array>() {
|
||||||
@ -1482,15 +1516,12 @@ impl Module {
|
|||||||
/// ```
|
/// ```
|
||||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||||
#[inline]
|
#[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
|
where
|
||||||
A: Variant + Clone,
|
A: Variant + Clone,
|
||||||
B: Variant + Clone,
|
B: Variant + Clone,
|
||||||
C: Variant + Clone,
|
T: Variant + Clone,
|
||||||
F: RegisterNativeFunction<ARGS, RhaiResultOf<()>>
|
F: RegisterNativeFunction<(Mut<A>, B, T), (), RhaiResultOf<S>> + SendSync + 'static,
|
||||||
+ Fn(&mut A, B, C) -> RhaiResultOf<()>
|
|
||||||
+ SendSync
|
|
||||||
+ 'static,
|
|
||||||
{
|
{
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
if TypeId::of::<A>() == TypeId::of::<crate::Array>() {
|
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
|
/// 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].
|
/// [`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.
|
/// If there are similar existing Rust functions, they are replaced.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
@ -1552,10 +1585,10 @@ impl Module {
|
|||||||
/// ```
|
/// ```
|
||||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||||
#[inline(always)]
|
#[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,
|
&mut self,
|
||||||
get_fn: impl Fn(&mut A, B) -> RhaiResultOf<T> + SendSync + 'static,
|
get_fn: impl RegisterNativeFunction<(Mut<A>, B), T, RhaiResultOf<S1>> + SendSync + 'static,
|
||||||
set_fn: impl Fn(&mut A, B, T) -> RhaiResultOf<()> + SendSync + 'static,
|
set_fn: impl RegisterNativeFunction<(Mut<A>, B, T), (), RhaiResultOf<S2>> + SendSync + 'static,
|
||||||
) -> (u64, u64)
|
) -> (u64, u64)
|
||||||
where
|
where
|
||||||
A: Variant + Clone,
|
A: Variant + Clone,
|
||||||
@ -2016,7 +2049,7 @@ impl Module {
|
|||||||
if let Some(fn_ptr) = value.downcast_ref::<crate::FnPtr>() {
|
if let Some(fn_ptr) = value.downcast_ref::<crate::FnPtr>() {
|
||||||
if ast.iter_fn_def().any(|f| f.name == fn_ptr.fn_name()) {
|
if ast.iter_fn_def().any(|f| f.name == fn_ptr.fn_name()) {
|
||||||
return Err(crate::ERR::ErrorMismatchDataType(
|
return Err(crate::ERR::ErrorMismatchDataType(
|
||||||
"".to_string(),
|
String::new(),
|
||||||
if fn_ptr.is_anonymous() {
|
if fn_ptr.is_anonymous() {
|
||||||
format!("cannot export closure in variable {_name}")
|
format!("cannot export closure in variable {_name}")
|
||||||
} else {
|
} else {
|
||||||
@ -2217,29 +2250,23 @@ impl Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set a type iterator into the [`Module`].
|
/// Set a type iterator into the [`Module`].
|
||||||
#[cfg(not(feature = "sync"))]
|
#[inline(always)]
|
||||||
#[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]
|
|
||||||
pub fn set_iter(
|
pub fn set_iter(
|
||||||
&mut self,
|
&mut self,
|
||||||
type_id: TypeId,
|
type_id: TypeId,
|
||||||
func: impl Fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>> + SendSync + 'static,
|
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 {
|
) -> &mut Self {
|
||||||
let func = Shared::new(func);
|
let func = Shared::new(func);
|
||||||
if self.indexed {
|
if self.indexed {
|
||||||
@ -2251,7 +2278,7 @@ impl Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set a type iterator into the [`Module`].
|
/// Set a type iterator into the [`Module`].
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
pub fn set_iterable<T>(&mut self) -> &mut Self
|
pub fn set_iterable<T>(&mut self) -> &mut Self
|
||||||
where
|
where
|
||||||
T: Variant + Clone + IntoIterator,
|
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.
|
/// Set an iterator type into the [`Module`] as a type iterator.
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
pub fn set_iterator<T>(&mut self) -> &mut Self
|
pub fn set_iterator<T>(&mut self) -> &mut Self
|
||||||
where
|
where
|
||||||
T: Variant + Clone + Iterator,
|
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.
|
/// Get the specified type iterator.
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -2051,12 +2051,12 @@ impl Engine {
|
|||||||
Ok(Stmt::Assignment((op_info, (lhs, rhs).into()).into()))
|
Ok(Stmt::Assignment((op_info, (lhs, rhs).into()).into()))
|
||||||
}
|
}
|
||||||
// expr[???] = rhs, expr.??? = rhs
|
// expr[???] = rhs, expr.??? = rhs
|
||||||
ref expr => Err(PERR::AssignmentToInvalidLHS("".to_string())
|
ref expr => Err(PERR::AssignmentToInvalidLHS(String::new())
|
||||||
.into_err(expr.position())),
|
.into_err(expr.position())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(err_pos) => {
|
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)),
|
.into_err(op_pos)),
|
||||||
// expr = rhs
|
// 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::Pipe, ..) => break,
|
||||||
(Token::Identifier(s), pos) => {
|
(Token::Identifier(s), pos) => {
|
||||||
if params_list.iter().any(|p| p.as_str() == &*s) {
|
if params_list.iter().any(|p| p.as_str() == &*s) {
|
||||||
return Err(PERR::FnDuplicatedParam("".to_string(), s.to_string())
|
return Err(
|
||||||
.into_err(pos));
|
PERR::FnDuplicatedParam(String::new(), s.to_string()).into_err(pos)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
let s = state.get_interned_string(s);
|
let s = state.get_interned_string(s);
|
||||||
state.stack.push(s.clone(), ());
|
state.stack.push(s.clone(), ());
|
||||||
|
@ -51,8 +51,7 @@ impl fmt::Display for LexError {
|
|||||||
Self::ImproperSymbol(s, d) if d.is_empty() => {
|
Self::ImproperSymbol(s, d) if d.is_empty() => {
|
||||||
write!(f, "Invalid symbol encountered: '{}'", s)
|
write!(f, "Invalid symbol encountered: '{}'", s)
|
||||||
}
|
}
|
||||||
Self::ImproperSymbol(s, d) if s.is_empty() => f.write_str(d),
|
Self::ImproperSymbol(.., d) => f.write_str(d),
|
||||||
Self::ImproperSymbol(s, d) => write!(f, "{}: '{}'", d, s),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,28 +25,28 @@ fn test_assignments_bad_lhs() -> Result<(), Box<EvalAltResult>> {
|
|||||||
.compile("(x+y) = 42;")
|
.compile("(x+y) = 42;")
|
||||||
.expect_err("should error")
|
.expect_err("should error")
|
||||||
.err_type(),
|
.err_type(),
|
||||||
ParseErrorType::AssignmentToInvalidLHS("".to_string())
|
ParseErrorType::AssignmentToInvalidLHS(String::new())
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
*engine
|
*engine
|
||||||
.compile("foo(x) = 42;")
|
.compile("foo(x) = 42;")
|
||||||
.expect_err("should error")
|
.expect_err("should error")
|
||||||
.err_type(),
|
.err_type(),
|
||||||
ParseErrorType::AssignmentToInvalidLHS("".to_string())
|
ParseErrorType::AssignmentToInvalidLHS(String::new())
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
*engine
|
*engine
|
||||||
.compile("true = 42;")
|
.compile("true = 42;")
|
||||||
.expect_err("should error")
|
.expect_err("should error")
|
||||||
.err_type(),
|
.err_type(),
|
||||||
ParseErrorType::AssignmentToConstant("".to_string())
|
ParseErrorType::AssignmentToConstant(String::new())
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
*engine
|
*engine
|
||||||
.compile("123 = 42;")
|
.compile("123 = 42;")
|
||||||
.expect_err("should error")
|
.expect_err("should error")
|
||||||
.err_type(),
|
.err_type(),
|
||||||
ParseErrorType::AssignmentToConstant("".to_string())
|
ParseErrorType::AssignmentToConstant(String::new())
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
@ -56,21 +56,21 @@ fn test_assignments_bad_lhs() -> Result<(), Box<EvalAltResult>> {
|
|||||||
.compile("x.foo() = 42;")
|
.compile("x.foo() = 42;")
|
||||||
.expect_err("should error")
|
.expect_err("should error")
|
||||||
.err_type(),
|
.err_type(),
|
||||||
ParseErrorType::AssignmentToInvalidLHS("".to_string())
|
ParseErrorType::AssignmentToInvalidLHS(String::new())
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
*engine
|
*engine
|
||||||
.compile("x.foo().x.y = 42;")
|
.compile("x.foo().x.y = 42;")
|
||||||
.expect_err("should error")
|
.expect_err("should error")
|
||||||
.err_type(),
|
.err_type(),
|
||||||
ParseErrorType::AssignmentToInvalidLHS("".to_string())
|
ParseErrorType::AssignmentToInvalidLHS(String::new())
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
*engine
|
*engine
|
||||||
.compile("x.y.z.foo() = 42;")
|
.compile("x.y.z.foo() = 42;")
|
||||||
.expect_err("should error")
|
.expect_err("should error")
|
||||||
.err_type(),
|
.err_type(),
|
||||||
ParseErrorType::AssignmentToInvalidLHS("".to_string())
|
ParseErrorType::AssignmentToInvalidLHS(String::new())
|
||||||
);
|
);
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -78,7 +78,7 @@ fn test_assignments_bad_lhs() -> Result<(), Box<EvalAltResult>> {
|
|||||||
.compile("x.foo()[0] = 42;")
|
.compile("x.foo()[0] = 42;")
|
||||||
.expect_err("should error")
|
.expect_err("should error")
|
||||||
.err_type(),
|
.err_type(),
|
||||||
ParseErrorType::AssignmentToInvalidLHS("".to_string())
|
ParseErrorType::AssignmentToInvalidLHS(String::new())
|
||||||
);
|
);
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -86,7 +86,7 @@ fn test_assignments_bad_lhs() -> Result<(), Box<EvalAltResult>> {
|
|||||||
.compile("x[y].z.foo() = 42;")
|
.compile("x[y].z.foo() = 42;")
|
||||||
.expect_err("should error")
|
.expect_err("should error")
|
||||||
.err_type(),
|
.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")
|
.compile("hello hey")
|
||||||
.expect_err("should error")
|
.expect_err("should error")
|
||||||
.err_type(),
|
.err_type(),
|
||||||
ParseErrorType::BadInput(LexError::ImproperSymbol("hey".to_string(), "".to_string()))
|
ParseErrorType::BadInput(LexError::ImproperSymbol("hey".to_string(), String::new()))
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#![cfg(not(feature = "no_object"))]
|
#![cfg(not(feature = "no_object"))]
|
||||||
|
|
||||||
use rhai::{Engine, EvalAltResult, Scope, INT};
|
use rhai::{Engine, EvalAltResult, NativeCallContext, Scope, INT};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_set() -> Result<(), Box<EvalAltResult>> {
|
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(
|
.register_get_set(
|
||||||
"value",
|
"value",
|
||||||
|t: &mut Inner| t.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_type::<Outer>()
|
||||||
.register_get_set(
|
.register_get_set(
|
||||||
"inner",
|
"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),
|
|_: &mut Outer, new: Inner| panic!("Outer::inner setter called with {:?}", new),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user