commit
e98e9f9b78
@ -24,7 +24,7 @@ categories = [ "no-std", "embedded", "wasm", "parser-implementations" ]
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
smallvec = { version = "1.4.2", default-features = false }
|
smallvec = { version = "1.4.2", default-features = false }
|
||||||
rhai_codegen = { version = "0.2", path = "codegen" }
|
rhai_codegen = { version = "0.3", path = "codegen" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
|
@ -6,11 +6,16 @@ Version 0.19.6
|
|||||||
|
|
||||||
This version adds the `switch` statement.
|
This version adds the `switch` statement.
|
||||||
|
|
||||||
|
It also allows exposing selected module functions (usually methods) to the global namespace.
|
||||||
|
|
||||||
New features
|
New features
|
||||||
------------
|
------------
|
||||||
|
|
||||||
* `switch` statement.
|
* `switch` statement.
|
||||||
* `Engine::register_module` to register a module as a sub-module in the global namespace, while at the same time exposing its method functions globally. This is convenient when registering an API for a custom type.
|
* `Engine::register_module` to register a module as a sub-module in the global namespace.
|
||||||
|
* `Module::get_fn_namespace` and `Module::set_fn_namespace` can expose a module function to the global namespace. This is convenient when registering an API for a custom type.
|
||||||
|
* `set_exported_global_fn!` macro to register a plugin function and expose it to the global namespace.
|
||||||
|
* `#[rhai_fn(gobal)]` and `#[rhai_fn(internal)]` attributes to determine whether a function defined in a plugin module should be exposed to the global namespace. This is convenient when defining an API for a custom type.
|
||||||
|
|
||||||
Enhancements
|
Enhancements
|
||||||
------------
|
------------
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
///! Test evaluating with scope
|
///! Test evaluating with scope
|
||||||
extern crate test;
|
extern crate test;
|
||||||
|
|
||||||
use rhai::{module_resolvers::StaticModuleResolver, Engine, Module, OptimizationLevel};
|
use rhai::{Engine, Module, OptimizationLevel};
|
||||||
use test::Bencher;
|
use test::Bencher;
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
@ -20,9 +20,7 @@ fn bench_eval_module(bench: &mut Bencher) {
|
|||||||
|
|
||||||
let module = Module::eval_ast_as_new(Default::default(), &ast, &engine).unwrap();
|
let module = Module::eval_ast_as_new(Default::default(), &ast, &engine).unwrap();
|
||||||
|
|
||||||
let mut resolver = StaticModuleResolver::new();
|
engine.register_module("testing", module);
|
||||||
resolver.insert("testing", module);
|
|
||||||
engine.set_module_resolver(Some(resolver));
|
|
||||||
|
|
||||||
let ast = engine
|
let ast = engine
|
||||||
.compile(
|
.compile(
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rhai_codegen"
|
name = "rhai_codegen"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
authors = ["jhwgh1968"]
|
authors = ["jhwgh1968"]
|
||||||
description = "Procedural macro support package for Rhai, a scripting language for Rust"
|
description = "Procedural macro support package for Rhai, a scripting language for Rust"
|
||||||
|
@ -20,6 +20,12 @@ use syn::{
|
|||||||
|
|
||||||
use crate::attrs::{ExportInfo, ExportScope, ExportedParams};
|
use crate::attrs::{ExportInfo, ExportScope, ExportedParams};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, Copy, Hash)]
|
||||||
|
pub enum FnNamespaceAccess {
|
||||||
|
Global,
|
||||||
|
Internal,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub enum Index {
|
pub enum Index {
|
||||||
Get,
|
Get,
|
||||||
@ -82,8 +88,9 @@ pub(crate) struct ExportedFnParams {
|
|||||||
pub name: Option<Vec<String>>,
|
pub name: Option<Vec<String>>,
|
||||||
pub return_raw: bool,
|
pub return_raw: bool,
|
||||||
pub skip: bool,
|
pub skip: bool,
|
||||||
pub span: Option<proc_macro2::Span>,
|
|
||||||
pub special: FnSpecialAccess,
|
pub special: FnSpecialAccess,
|
||||||
|
pub namespace: Option<FnNamespaceAccess>,
|
||||||
|
pub span: Option<proc_macro2::Span>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const FN_GET: &str = "get$";
|
pub const FN_GET: &str = "get$";
|
||||||
@ -119,6 +126,7 @@ impl ExportedParams for ExportedFnParams {
|
|||||||
let mut name = Vec::new();
|
let mut name = Vec::new();
|
||||||
let mut return_raw = false;
|
let mut return_raw = false;
|
||||||
let mut skip = false;
|
let mut skip = false;
|
||||||
|
let mut namespace = None;
|
||||||
let mut special = FnSpecialAccess::None;
|
let mut special = FnSpecialAccess::None;
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
let crate::attrs::AttrItem {
|
let crate::attrs::AttrItem {
|
||||||
@ -194,12 +202,30 @@ impl ExportedParams for ExportedFnParams {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
("return_raw", None) => return_raw = true,
|
|
||||||
("index_get", Some(s)) | ("index_set", Some(s)) | ("return_raw", Some(s)) => {
|
("index_get", Some(s)) | ("index_set", Some(s)) | ("return_raw", Some(s)) => {
|
||||||
return Err(syn::Error::new(s.span(), "extraneous value"))
|
return Err(syn::Error::new(s.span(), "extraneous value"))
|
||||||
}
|
}
|
||||||
|
("return_raw", None) => return_raw = true,
|
||||||
|
("return_raw", Some(s)) => {
|
||||||
|
return Err(syn::Error::new(s.span(), "extraneous value"))
|
||||||
|
}
|
||||||
("skip", None) => skip = true,
|
("skip", None) => skip = true,
|
||||||
("skip", Some(s)) => return Err(syn::Error::new(s.span(), "extraneous value")),
|
("skip", Some(s)) => return Err(syn::Error::new(s.span(), "extraneous value")),
|
||||||
|
("global", Some(s)) | ("internal", Some(s)) => {
|
||||||
|
return Err(syn::Error::new(s.span(), "extraneous value"))
|
||||||
|
}
|
||||||
|
("global", None) => {
|
||||||
|
if namespace.is_some() {
|
||||||
|
return Err(syn::Error::new(key.span(), "conflicting namespace"));
|
||||||
|
}
|
||||||
|
namespace = Some(FnNamespaceAccess::Global);
|
||||||
|
}
|
||||||
|
("internal", None) => {
|
||||||
|
if namespace.is_some() {
|
||||||
|
return Err(syn::Error::new(key.span(), "conflicting namespace"));
|
||||||
|
}
|
||||||
|
namespace = Some(FnNamespaceAccess::Internal);
|
||||||
|
}
|
||||||
(attr, _) => {
|
(attr, _) => {
|
||||||
return Err(syn::Error::new(
|
return Err(syn::Error::new(
|
||||||
key.span(),
|
key.span(),
|
||||||
@ -214,6 +240,7 @@ impl ExportedParams for ExportedFnParams {
|
|||||||
return_raw,
|
return_raw,
|
||||||
skip,
|
skip,
|
||||||
special,
|
special,
|
||||||
|
namespace,
|
||||||
span: Some(span),
|
span: Some(span),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
|
@ -339,7 +339,48 @@ pub fn set_exported_fn(args: proc_macro::TokenStream) -> proc_macro::TokenStream
|
|||||||
};
|
};
|
||||||
let gen_mod_path = crate::register::generated_module_path(&rust_modpath);
|
let gen_mod_path = crate::register::generated_module_path(&rust_modpath);
|
||||||
let tokens = quote! {
|
let tokens = quote! {
|
||||||
#module_expr.set_fn(#export_name, FnAccess::Public,
|
#module_expr.set_fn(#export_name, FnNamespace::Internal, FnAccess::Public,
|
||||||
|
#gen_mod_path::token_input_types().as_ref(),
|
||||||
|
#gen_mod_path::token_callable());
|
||||||
|
};
|
||||||
|
proc_macro::TokenStream::from(tokens)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Macro to register a _plugin function_ into a Rhai `Module` and expose it globally.
|
||||||
|
///
|
||||||
|
/// # Usage
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use rhai::{Engine, EvalAltResult};
|
||||||
|
/// use rhai::plugin::*;
|
||||||
|
///
|
||||||
|
/// #[export_fn]
|
||||||
|
/// fn my_plugin_function(x: i64) -> i64 {
|
||||||
|
/// x * 2
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// # fn main() -> Result<(), Box<EvalAltResult>> {
|
||||||
|
/// let mut engine = Engine::new();
|
||||||
|
///
|
||||||
|
/// let mut module = Module::new();
|
||||||
|
/// set_exported_global_fn!(module, "func", my_plugin_function);
|
||||||
|
///
|
||||||
|
/// engine.register_module("test", module);
|
||||||
|
///
|
||||||
|
/// assert_eq!(engine.eval::<i64>("func(21)")?, 42);
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
#[proc_macro]
|
||||||
|
pub fn set_exported_global_fn(args: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
|
let (module_expr, export_name, rust_modpath) = match crate::register::parse_register_macro(args)
|
||||||
|
{
|
||||||
|
Ok(triple) => triple,
|
||||||
|
Err(e) => return e.to_compile_error().into(),
|
||||||
|
};
|
||||||
|
let gen_mod_path = crate::register::generated_module_path(&rust_modpath);
|
||||||
|
let tokens = quote! {
|
||||||
|
#module_expr.set_fn(#export_name, FnNamespace::Global, FnAccess::Public,
|
||||||
#gen_mod_path::token_input_types().as_ref(),
|
#gen_mod_path::token_input_types().as_ref(),
|
||||||
#gen_mod_path::token_callable());
|
#gen_mod_path::token_callable());
|
||||||
};
|
};
|
||||||
|
@ -4,7 +4,7 @@ use quote::{quote, ToTokens};
|
|||||||
|
|
||||||
use crate::attrs::ExportScope;
|
use crate::attrs::ExportScope;
|
||||||
use crate::function::flatten_type_groups;
|
use crate::function::flatten_type_groups;
|
||||||
use crate::function::{ExportedFn, FnSpecialAccess};
|
use crate::function::{ExportedFn, FnNamespaceAccess, FnSpecialAccess};
|
||||||
use crate::module::Module;
|
use crate::module::Module;
|
||||||
|
|
||||||
pub(crate) type ExportedConst = (String, Box<syn::Type>, syn::Expr);
|
pub(crate) type ExportedConst = (String, Box<syn::Type>, syn::Expr);
|
||||||
@ -80,6 +80,7 @@ pub(crate) fn generate_body(
|
|||||||
function.name().span(),
|
function.name().span(),
|
||||||
);
|
);
|
||||||
let reg_names = function.exported_names();
|
let reg_names = function.exported_names();
|
||||||
|
let mut namespace = FnNamespaceAccess::Internal;
|
||||||
|
|
||||||
let fn_input_types: Vec<syn::Expr> = function
|
let fn_input_types: Vec<syn::Expr> = function
|
||||||
.arg_list()
|
.arg_list()
|
||||||
@ -123,12 +124,22 @@ pub(crate) fn generate_body(
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
if let Some(ns) = function.params().namespace {
|
||||||
|
namespace = ns;
|
||||||
|
}
|
||||||
|
|
||||||
for fn_literal in reg_names {
|
for fn_literal in reg_names {
|
||||||
set_fn_stmts.push(
|
set_fn_stmts.push(
|
||||||
syn::parse2::<syn::Stmt>(quote! {
|
match namespace {
|
||||||
m.set_fn(#fn_literal, FnAccess::Public, &[#(#fn_input_types),*],
|
FnNamespaceAccess::Global => syn::parse2::<syn::Stmt>(quote! {
|
||||||
#fn_token_name().into());
|
m.set_fn(#fn_literal, FnNamespace::Global, FnAccess::Public, &[#(#fn_input_types),*],
|
||||||
})
|
#fn_token_name().into());
|
||||||
|
}),
|
||||||
|
FnNamespaceAccess::Internal => syn::parse2::<syn::Stmt>(quote! {
|
||||||
|
m.set_fn(#fn_literal, FnNamespace::Internal, FnAccess::Public, &[#(#fn_input_types),*],
|
||||||
|
#fn_token_name().into());
|
||||||
|
}),
|
||||||
|
}
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -295,7 +295,7 @@ mod generate_tests {
|
|||||||
}
|
}
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
||||||
m.set_fn("get_mystic_number", FnAccess::Public, &[],
|
m.set_fn("get_mystic_number", FnNamespace::Internal, FnAccess::Public, &[],
|
||||||
get_mystic_number_token().into());
|
get_mystic_number_token().into());
|
||||||
if flatten {} else {}
|
if flatten {} else {}
|
||||||
}
|
}
|
||||||
@ -330,6 +330,68 @@ mod generate_tests {
|
|||||||
assert_streams_eq(item_mod.generate(), expected_tokens);
|
assert_streams_eq(item_mod.generate(), expected_tokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn one_single_arg_global_fn_module() {
|
||||||
|
let input_tokens: TokenStream = quote! {
|
||||||
|
pub mod one_global_fn {
|
||||||
|
#[rhai_fn(global)]
|
||||||
|
pub fn add_one_to(x: INT) -> INT {
|
||||||
|
x + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let expected_tokens = quote! {
|
||||||
|
pub mod one_global_fn {
|
||||||
|
pub fn add_one_to(x: INT) -> INT {
|
||||||
|
x + 1
|
||||||
|
}
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub fn rhai_module_generate() -> Module {
|
||||||
|
let mut m = Module::new();
|
||||||
|
rhai_generate_into_module(&mut m, false);
|
||||||
|
m
|
||||||
|
}
|
||||||
|
#[allow(unused_mut)]
|
||||||
|
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
||||||
|
m.set_fn("add_one_to", FnNamespace::Global, FnAccess::Public, &[core::any::TypeId::of::<INT>()],
|
||||||
|
add_one_to_token().into());
|
||||||
|
if flatten {} else {}
|
||||||
|
}
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
struct add_one_to_token();
|
||||||
|
impl PluginFunction for add_one_to_token {
|
||||||
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
|
debug_assert_eq!(args.len(), 1usize,
|
||||||
|
"wrong arg count: {} != {}", args.len(), 1usize);
|
||||||
|
let arg0 = mem::take(args[0usize]).cast::<INT>();
|
||||||
|
Ok(Dynamic::from(add_one_to(arg0)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_method_call(&self) -> bool { false }
|
||||||
|
fn is_variadic(&self) -> bool { false }
|
||||||
|
fn clone_boxed(&self) -> Box<dyn PluginFunction> {
|
||||||
|
Box::new(add_one_to_token())
|
||||||
|
}
|
||||||
|
fn input_types(&self) -> Box<[TypeId]> {
|
||||||
|
new_vec![TypeId::of::<INT>()].into_boxed_slice()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn add_one_to_token_callable() -> CallableFunction {
|
||||||
|
add_one_to_token().into()
|
||||||
|
}
|
||||||
|
pub fn add_one_to_token_input_types() -> Box<[TypeId]> {
|
||||||
|
add_one_to_token().input_types()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let item_mod = syn::parse2::<Module>(input_tokens).unwrap();
|
||||||
|
assert_streams_eq(item_mod.generate(), expected_tokens);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn one_single_arg_fn_module() {
|
fn one_single_arg_fn_module() {
|
||||||
let input_tokens: TokenStream = quote! {
|
let input_tokens: TokenStream = quote! {
|
||||||
@ -355,7 +417,7 @@ mod generate_tests {
|
|||||||
}
|
}
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
||||||
m.set_fn("add_one_to", FnAccess::Public, &[core::any::TypeId::of::<INT>()],
|
m.set_fn("add_one_to", FnNamespace::Internal, FnAccess::Public, &[core::any::TypeId::of::<INT>()],
|
||||||
add_one_to_token().into());
|
add_one_to_token().into());
|
||||||
if flatten {} else {}
|
if flatten {} else {}
|
||||||
}
|
}
|
||||||
@ -427,10 +489,10 @@ mod generate_tests {
|
|||||||
}
|
}
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
||||||
m.set_fn("add_n", FnAccess::Public, &[core::any::TypeId::of::<INT>()],
|
m.set_fn("add_n", FnNamespace::Internal, FnAccess::Public, &[core::any::TypeId::of::<INT>()],
|
||||||
add_one_to_token().into());
|
add_one_to_token().into());
|
||||||
m.set_fn("add_n", FnAccess::Public, &[core::any::TypeId::of::<INT>(),
|
m.set_fn("add_n", FnNamespace::Internal, FnAccess::Public, &[core::any::TypeId::of::<INT>(),
|
||||||
core::any::TypeId::of::<INT>()],
|
core::any::TypeId::of::<INT>()],
|
||||||
add_n_to_token().into());
|
add_n_to_token().into());
|
||||||
if flatten {} else {}
|
if flatten {} else {}
|
||||||
}
|
}
|
||||||
@ -519,8 +581,8 @@ mod generate_tests {
|
|||||||
}
|
}
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
||||||
m.set_fn("add_together", FnAccess::Public, &[core::any::TypeId::of::<INT>(),
|
m.set_fn("add_together", FnNamespace::Internal, FnAccess::Public, &[core::any::TypeId::of::<INT>(),
|
||||||
core::any::TypeId::of::<INT>()],
|
core::any::TypeId::of::<INT>()],
|
||||||
add_together_token().into());
|
add_together_token().into());
|
||||||
if flatten {} else {}
|
if flatten {} else {}
|
||||||
}
|
}
|
||||||
@ -584,14 +646,14 @@ mod generate_tests {
|
|||||||
}
|
}
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
||||||
m.set_fn("add", FnAccess::Public, &[core::any::TypeId::of::<INT>(),
|
m.set_fn("add", FnNamespace::Internal, FnAccess::Public, &[core::any::TypeId::of::<INT>(),
|
||||||
core::any::TypeId::of::<INT>()],
|
core::any::TypeId::of::<INT>()],
|
||||||
add_together_token().into());
|
add_together_token().into());
|
||||||
m.set_fn("+", FnAccess::Public, &[core::any::TypeId::of::<INT>(),
|
m.set_fn("+", FnNamespace::Internal, FnAccess::Public, &[core::any::TypeId::of::<INT>(),
|
||||||
core::any::TypeId::of::<INT>()],
|
core::any::TypeId::of::<INT>()],
|
||||||
add_together_token().into());
|
add_together_token().into());
|
||||||
m.set_fn("add_together", FnAccess::Public, &[core::any::TypeId::of::<INT>(),
|
m.set_fn("add_together", FnNamespace::Internal, FnAccess::Public, &[core::any::TypeId::of::<INT>(),
|
||||||
core::any::TypeId::of::<INT>()],
|
core::any::TypeId::of::<INT>()],
|
||||||
add_together_token().into());
|
add_together_token().into());
|
||||||
if flatten {} else {}
|
if flatten {} else {}
|
||||||
}
|
}
|
||||||
@ -831,7 +893,7 @@ mod generate_tests {
|
|||||||
}
|
}
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
||||||
m.set_fn("get_mystic_number", FnAccess::Public, &[],
|
m.set_fn("get_mystic_number", FnNamespace::Internal, FnAccess::Public, &[],
|
||||||
get_mystic_number_token().into());
|
get_mystic_number_token().into());
|
||||||
if flatten {} else {}
|
if flatten {} else {}
|
||||||
}
|
}
|
||||||
@ -921,7 +983,7 @@ mod generate_tests {
|
|||||||
}
|
}
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
||||||
m.set_fn("print_out_to", FnAccess::Public,
|
m.set_fn("print_out_to", FnNamespace::Internal, FnAccess::Public,
|
||||||
&[core::any::TypeId::of::<ImmutableString>()],
|
&[core::any::TypeId::of::<ImmutableString>()],
|
||||||
print_out_to_token().into());
|
print_out_to_token().into());
|
||||||
if flatten {} else {}
|
if flatten {} else {}
|
||||||
@ -983,7 +1045,7 @@ mod generate_tests {
|
|||||||
}
|
}
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
||||||
m.set_fn("print_out_to", FnAccess::Public,
|
m.set_fn("print_out_to", FnNamespace::Internal, FnAccess::Public,
|
||||||
&[core::any::TypeId::of::<ImmutableString>()],
|
&[core::any::TypeId::of::<ImmutableString>()],
|
||||||
print_out_to_token().into());
|
print_out_to_token().into());
|
||||||
if flatten {} else {}
|
if flatten {} else {}
|
||||||
@ -1045,7 +1107,7 @@ mod generate_tests {
|
|||||||
}
|
}
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
||||||
m.set_fn("increment", FnAccess::Public,
|
m.set_fn("increment", FnNamespace::Internal, FnAccess::Public,
|
||||||
&[core::any::TypeId::of::<FLOAT>()],
|
&[core::any::TypeId::of::<FLOAT>()],
|
||||||
increment_token().into());
|
increment_token().into());
|
||||||
if flatten {} else {}
|
if flatten {} else {}
|
||||||
@ -1110,7 +1172,7 @@ mod generate_tests {
|
|||||||
}
|
}
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
||||||
m.set_fn("increment", FnAccess::Public,
|
m.set_fn("increment", FnNamespace::Internal, FnAccess::Public,
|
||||||
&[core::any::TypeId::of::<FLOAT>()],
|
&[core::any::TypeId::of::<FLOAT>()],
|
||||||
increment_token().into());
|
increment_token().into());
|
||||||
if flatten {} else {}
|
if flatten {} else {}
|
||||||
@ -1195,7 +1257,7 @@ mod generate_tests {
|
|||||||
}
|
}
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
||||||
m.set_fn("increment", FnAccess::Public,
|
m.set_fn("increment", FnNamespace::Internal, FnAccess::Public,
|
||||||
&[core::any::TypeId::of::<FLOAT>()],
|
&[core::any::TypeId::of::<FLOAT>()],
|
||||||
increment_token().into());
|
increment_token().into());
|
||||||
if flatten {} else {}
|
if flatten {} else {}
|
||||||
@ -1279,7 +1341,7 @@ mod generate_tests {
|
|||||||
}
|
}
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
||||||
m.set_fn("get$square", FnAccess::Public, &[core::any::TypeId::of::<u64>()],
|
m.set_fn("get$square", FnNamespace::Internal, FnAccess::Public, &[core::any::TypeId::of::<u64>()],
|
||||||
int_foo_token().into());
|
int_foo_token().into());
|
||||||
if flatten {} else {}
|
if flatten {} else {}
|
||||||
}
|
}
|
||||||
@ -1341,9 +1403,9 @@ mod generate_tests {
|
|||||||
}
|
}
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
||||||
m.set_fn("square", FnAccess::Public, &[core::any::TypeId::of::<u64>()],
|
m.set_fn("square", FnNamespace::Internal, FnAccess::Public, &[core::any::TypeId::of::<u64>()],
|
||||||
int_foo_token().into());
|
int_foo_token().into());
|
||||||
m.set_fn("get$square", FnAccess::Public, &[core::any::TypeId::of::<u64>()],
|
m.set_fn("get$square", FnNamespace::Internal, FnAccess::Public, &[core::any::TypeId::of::<u64>()],
|
||||||
int_foo_token().into());
|
int_foo_token().into());
|
||||||
if flatten {} else {}
|
if flatten {} else {}
|
||||||
}
|
}
|
||||||
@ -1405,7 +1467,7 @@ mod generate_tests {
|
|||||||
}
|
}
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
||||||
m.set_fn("set$squared", FnAccess::Public,
|
m.set_fn("set$squared", FnNamespace::Internal, FnAccess::Public,
|
||||||
&[core::any::TypeId::of::<u64>(),
|
&[core::any::TypeId::of::<u64>(),
|
||||||
core::any::TypeId::of::<u64>()],
|
core::any::TypeId::of::<u64>()],
|
||||||
int_foo_token().into());
|
int_foo_token().into());
|
||||||
@ -1470,11 +1532,11 @@ mod generate_tests {
|
|||||||
}
|
}
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
||||||
m.set_fn("set_sq", FnAccess::Public,
|
m.set_fn("set_sq", FnNamespace::Internal, FnAccess::Public,
|
||||||
&[core::any::TypeId::of::<u64>(),
|
&[core::any::TypeId::of::<u64>(),
|
||||||
core::any::TypeId::of::<u64>()],
|
core::any::TypeId::of::<u64>()],
|
||||||
int_foo_token().into());
|
int_foo_token().into());
|
||||||
m.set_fn("set$squared", FnAccess::Public,
|
m.set_fn("set$squared", FnNamespace::Internal, FnAccess::Public,
|
||||||
&[core::any::TypeId::of::<u64>(),
|
&[core::any::TypeId::of::<u64>(),
|
||||||
core::any::TypeId::of::<u64>()],
|
core::any::TypeId::of::<u64>()],
|
||||||
int_foo_token().into());
|
int_foo_token().into());
|
||||||
@ -1539,7 +1601,7 @@ mod generate_tests {
|
|||||||
}
|
}
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
||||||
m.set_fn("index$get$", FnAccess::Public,
|
m.set_fn("index$get$", FnNamespace::Internal, FnAccess::Public,
|
||||||
&[core::any::TypeId::of::<MyCollection>(),
|
&[core::any::TypeId::of::<MyCollection>(),
|
||||||
core::any::TypeId::of::<u64>()],
|
core::any::TypeId::of::<u64>()],
|
||||||
get_by_index_token().into());
|
get_by_index_token().into());
|
||||||
@ -1605,11 +1667,11 @@ mod generate_tests {
|
|||||||
}
|
}
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
||||||
m.set_fn("get", FnAccess::Public,
|
m.set_fn("get", FnNamespace::Internal, FnAccess::Public,
|
||||||
&[core::any::TypeId::of::<MyCollection>(),
|
&[core::any::TypeId::of::<MyCollection>(),
|
||||||
core::any::TypeId::of::<u64>()],
|
core::any::TypeId::of::<u64>()],
|
||||||
get_by_index_token().into());
|
get_by_index_token().into());
|
||||||
m.set_fn("index$get$", FnAccess::Public,
|
m.set_fn("index$get$", FnNamespace::Internal, FnAccess::Public,
|
||||||
&[core::any::TypeId::of::<MyCollection>(),
|
&[core::any::TypeId::of::<MyCollection>(),
|
||||||
core::any::TypeId::of::<u64>()],
|
core::any::TypeId::of::<u64>()],
|
||||||
get_by_index_token().into());
|
get_by_index_token().into());
|
||||||
@ -1675,7 +1737,7 @@ mod generate_tests {
|
|||||||
}
|
}
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
||||||
m.set_fn("index$set$", FnAccess::Public,
|
m.set_fn("index$set$", FnNamespace::Internal, FnAccess::Public,
|
||||||
&[core::any::TypeId::of::<MyCollection>(),
|
&[core::any::TypeId::of::<MyCollection>(),
|
||||||
core::any::TypeId::of::<u64>(),
|
core::any::TypeId::of::<u64>(),
|
||||||
core::any::TypeId::of::<FLOAT>()],
|
core::any::TypeId::of::<FLOAT>()],
|
||||||
@ -1744,12 +1806,12 @@ mod generate_tests {
|
|||||||
}
|
}
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
||||||
m.set_fn("set", FnAccess::Public,
|
m.set_fn("set", FnNamespace::Internal, FnAccess::Public,
|
||||||
&[core::any::TypeId::of::<MyCollection>(),
|
&[core::any::TypeId::of::<MyCollection>(),
|
||||||
core::any::TypeId::of::<u64>(),
|
core::any::TypeId::of::<u64>(),
|
||||||
core::any::TypeId::of::<FLOAT>()],
|
core::any::TypeId::of::<FLOAT>()],
|
||||||
set_by_index_token().into());
|
set_by_index_token().into());
|
||||||
m.set_fn("index$set$", FnAccess::Public,
|
m.set_fn("index$set$", FnNamespace::Internal, FnAccess::Public,
|
||||||
&[core::any::TypeId::of::<MyCollection>(),
|
&[core::any::TypeId::of::<MyCollection>(),
|
||||||
core::any::TypeId::of::<u64>(),
|
core::any::TypeId::of::<u64>(),
|
||||||
core::any::TypeId::of::<FLOAT>()],
|
core::any::TypeId::of::<FLOAT>()],
|
||||||
|
28
codegen/ui_tests/rhai_fn_global_multiple.rs
Normal file
28
codegen/ui_tests/rhai_fn_global_multiple.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
use rhai::plugin::*;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Point {
|
||||||
|
x: f32,
|
||||||
|
y: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[export_module]
|
||||||
|
pub mod test_module {
|
||||||
|
pub use super::Point;
|
||||||
|
#[rhai_fn(global, global)]
|
||||||
|
pub fn test_fn(input: Point) -> bool {
|
||||||
|
input.x > input.y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let n = Point {
|
||||||
|
x: 0.0,
|
||||||
|
y: 10.0
|
||||||
|
};
|
||||||
|
if test_module::test_fn(n) {
|
||||||
|
println!("yes");
|
||||||
|
} else {
|
||||||
|
println!("no");
|
||||||
|
}
|
||||||
|
}
|
11
codegen/ui_tests/rhai_fn_global_multiple.stderr
Normal file
11
codegen/ui_tests/rhai_fn_global_multiple.stderr
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
error: conflicting namespace
|
||||||
|
--> $DIR/rhai_fn_global_multiple.rs:12:23
|
||||||
|
|
|
||||||
|
12 | #[rhai_fn(global, global)]
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
error[E0433]: failed to resolve: use of undeclared crate or module `test_module`
|
||||||
|
--> $DIR/rhai_fn_global_multiple.rs:23:8
|
||||||
|
|
|
||||||
|
23 | if test_module::test_fn(n) {
|
||||||
|
| ^^^^^^^^^^^ use of undeclared crate or module `test_module`
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
{{#include ../links.md}}
|
{{#include ../links.md}}
|
||||||
|
|
||||||
Iterating through a range or an [array], or any type with a registered _iterator_,
|
Iterating through a range or an [array], or any type with a registered _type iterator_,
|
||||||
is provided by the `for` ... `in` loop.
|
is provided by the `for` ... `in` loop.
|
||||||
|
|
||||||
Like C, `continue` can be used to skip to the next iteration, by-passing all following statements;
|
Like C, `continue` can be used to skip to the next iteration, by-passing all following statements;
|
||||||
|
@ -6,7 +6,7 @@ Modules
|
|||||||
Rhai allows organizing code (functions, both Rust-based or script-based, and variables) into _modules_.
|
Rhai allows organizing code (functions, both Rust-based or script-based, and variables) into _modules_.
|
||||||
Modules can be disabled via the [`no_module`] feature.
|
Modules can be disabled via the [`no_module`] feature.
|
||||||
|
|
||||||
A module is of the type `Module` and holds a collection of functions, variables, iterators and sub-modules.
|
A module is of the type `Module` and holds a collection of functions, variables, type iterators and sub-modules.
|
||||||
It may be created entirely from Rust functions, or it may encapsulate a Rhai script together with the functions
|
It may be created entirely from Rust functions, or it may encapsulate a Rhai script together with the functions
|
||||||
and variables defined by that script.
|
and variables defined by that script.
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ Many script-oriented exceptions can be caught via `try` ... `catch`:
|
|||||||
| [Array]/[string] indexing out-of-bounds | error message [string] |
|
| [Array]/[string] indexing out-of-bounds | error message [string] |
|
||||||
| Indexing with an inappropriate data type | error message [string] |
|
| Indexing with an inappropriate data type | error message [string] |
|
||||||
| Error in a dot expression | error message [string] |
|
| Error in a dot expression | error message [string] |
|
||||||
| `for` statement without an iterator | error message [string] |
|
| `for` statement without an type iterator | error message [string] |
|
||||||
| Error in an `in` expression | error message [string] |
|
| Error in an `in` expression | error message [string] |
|
||||||
| Data race detected | error message [string] |
|
| Data race detected | error message [string] |
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ mod MyEnumModule {
|
|||||||
MyEnum::Baz(val1, val2)
|
MyEnum::Baz(val1, val2)
|
||||||
}
|
}
|
||||||
// Access to fields
|
// Access to fields
|
||||||
#[rhai_fn(get = "enum_type")]
|
#[rhai_fn(global, get = "enum_type")]
|
||||||
pub fn get_type(a: &mut MyEnum) -> String {
|
pub fn get_type(a: &mut MyEnum) -> String {
|
||||||
match a {
|
match a {
|
||||||
MyEnum::Foo => "Foo".to_string(),
|
MyEnum::Foo => "Foo".to_string(),
|
||||||
@ -45,7 +45,7 @@ mod MyEnumModule {
|
|||||||
MyEnum::Baz(_, _) => "Baz".to_string()
|
MyEnum::Baz(_, _) => "Baz".to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[rhai_fn(get = "field_0")]
|
#[rhai_fn(global, get = "field_0")]
|
||||||
pub fn get_field_0(a: &mut MyEnum) -> Dynamic {
|
pub fn get_field_0(a: &mut MyEnum) -> Dynamic {
|
||||||
match a {
|
match a {
|
||||||
MyEnum::Foo => Dynamic::UNIT,
|
MyEnum::Foo => Dynamic::UNIT,
|
||||||
@ -53,7 +53,7 @@ mod MyEnumModule {
|
|||||||
MyEnum::Baz(x, _) => Dynamic::from(x)
|
MyEnum::Baz(x, _) => Dynamic::from(x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[rhai_fn(get = "field_1")]
|
#[rhai_fn(global, get = "field_1")]
|
||||||
pub fn get_field_1(a: &mut MyEnum) -> Dynamic {
|
pub fn get_field_1(a: &mut MyEnum) -> Dynamic {
|
||||||
match a {
|
match a {
|
||||||
MyEnum::Foo | MyEnum::Bar(_) => Dynamic::UNIT,
|
MyEnum::Foo | MyEnum::Bar(_) => Dynamic::UNIT,
|
||||||
@ -61,41 +61,41 @@ mod MyEnumModule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Printing
|
// Printing
|
||||||
#[rhai(name = "to_string", name = "print", name = "debug")]
|
#[rhai(global, name = "to_string", name = "print", name = "debug")]
|
||||||
pub fn to_string(a: &mut MyEnum) -> String {
|
pub fn to_string(a: &mut MyEnum) -> String {
|
||||||
format!("{:?}", a))
|
format!("{:?}", a))
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "+")]
|
#[rhai_fn(global, name = "+")]
|
||||||
pub fn add_to_str(s: &str, a: MyEnum) -> String {
|
pub fn add_to_str(s: &str, a: MyEnum) -> String {
|
||||||
format!("{}{:?}", s, a))
|
format!("{}{:?}", s, a))
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "+")]
|
#[rhai_fn(global, name = "+")]
|
||||||
pub fn add_str(a: &mut MyEnum, s: &str) -> String {
|
pub fn add_str(a: &mut MyEnum, s: &str) -> String {
|
||||||
format!("{:?}", a).push_str(s))
|
format!("{:?}", a).push_str(s))
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "+=")]
|
#[rhai_fn(global, name = "+=")]
|
||||||
pub fn append_to_str(s: &mut ImmutableString, a: MyEnum) -> String {
|
pub fn append_to_str(s: &mut ImmutableString, a: MyEnum) -> String {
|
||||||
s += a.to_string())
|
s += a.to_string())
|
||||||
}
|
}
|
||||||
// '==' and '!=' operators
|
// '==' and '!=' operators
|
||||||
#[rhai_fn(name = "==")]
|
#[rhai_fn(global, name = "==")]
|
||||||
pub fn eq(a: &mut MyEnum, b: MyEnum) -> bool {
|
pub fn eq(a: &mut MyEnum, b: MyEnum) -> bool {
|
||||||
a == &b
|
a == &b
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "!=")]
|
#[rhai_fn(global, name = "!=")]
|
||||||
pub fn neq(a: &mut MyEnum, b: MyEnum) -> bool {
|
pub fn neq(a: &mut MyEnum, b: MyEnum) -> bool {
|
||||||
a != &b
|
a != &b
|
||||||
}
|
}
|
||||||
// Array functions
|
// Array functions
|
||||||
#[rhai_fn(name = "push")]
|
#[rhai_fn(global, name = "push")]
|
||||||
pub fn append_to_array(list: &mut Array, item: MyEnum) {
|
pub fn append_to_array(list: &mut Array, item: MyEnum) {
|
||||||
list.push(Dynamic::from(item)));
|
list.push(Dynamic::from(item)));
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "+=")]
|
#[rhai_fn(global, name = "+=")]
|
||||||
pub fn append_to_array_op(list: &mut Array, item: MyEnum) {
|
pub fn append_to_array_op(list: &mut Array, item: MyEnum) {
|
||||||
list.push(Dynamic::from(item)));
|
list.push(Dynamic::from(item)));
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "insert")]
|
#[rhai_fn(global, name = "insert")]
|
||||||
pub fn insert_to_array(list: &mut Array, position: i64, item: MyEnum) {
|
pub fn insert_to_array(list: &mut Array, position: i64, item: MyEnum) {
|
||||||
if position <= 0 {
|
if position <= 0 {
|
||||||
list.insert(0, Dynamic::from(item));
|
list.insert(0, Dynamic::from(item));
|
||||||
@ -105,7 +105,7 @@ mod MyEnumModule {
|
|||||||
list.insert(position as usize, Dynamic::from(item));
|
list.insert(position as usize, Dynamic::from(item));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "pad")]
|
#[rhai_fn(global, name = "pad")]
|
||||||
pub fn pad_array(list: &mut Array, len: i64, item: MyEnum) {
|
pub fn pad_array(list: &mut Array, len: i64, item: MyEnum) {
|
||||||
if len as usize > list.len() { list.resize(len as usize, item); }
|
if len as usize > list.len() { list.resize(len as usize, item); }
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,12 @@ individual functions instead of a full-blown [plugin module].
|
|||||||
Macros
|
Macros
|
||||||
------
|
------
|
||||||
|
|
||||||
| Macro | Signature | Description |
|
| Macro | Signature | Description |
|
||||||
| ----------------------- | ------------------------------------------------------------------ | --------------------------------------------------------------- |
|
| ------------------------- | -------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
|
||||||
| `#[export_fn]` | apply to rust function defined in a Rust module | exports the function |
|
| `#[export_fn]` | apply to rust function defined in a Rust module | exports the function |
|
||||||
| `register_exported_fn!` | `register_exported_fn!(&mut `_engine_`, "`_name_`", `_function_`)` | registers the function into an [`Engine`] under a specific name |
|
| `register_exported_fn!` | `register_exported_fn!(&mut `_engine_`, "`_name_`", `_function_`)` | registers the function into an [`Engine`] under a specific name |
|
||||||
| `set_exported_fn!` | `set_exported_fn!(&mut `_module_`, "`_name_`", `_function_`)` | registers the function into a [`Module`] under a specific name |
|
| `set_exported_fn!` | `set_exported_fn!(&mut `_module_`, "`_name_`", `_function_`)` | registers the function into a [`Module`] under a specific name |
|
||||||
|
| `set_exported_global_fn!` | `set_exported_global_fn!(&mut `_module_`, "`_name_`", `_function_`)` | registers the function into a [`Module`] under a specific name, exposing it to the global namespace |
|
||||||
|
|
||||||
|
|
||||||
`#[export_fn]` and `register_exported_fn!`
|
`#[export_fn]` and `register_exported_fn!`
|
||||||
|
@ -54,6 +54,8 @@ mod my_module {
|
|||||||
mystic_number()
|
mystic_number()
|
||||||
}
|
}
|
||||||
// This function will be registered as 'increment'.
|
// This function will be registered as 'increment'.
|
||||||
|
// It will also be exposed to the global namespace since 'global' is set.
|
||||||
|
#[rhai_fn(global)]
|
||||||
pub fn increment(num: &mut i64) {
|
pub fn increment(num: &mut i64) {
|
||||||
*num += 1;
|
*num += 1;
|
||||||
}
|
}
|
||||||
@ -159,10 +161,13 @@ service::increment(x);
|
|||||||
x == 43;
|
x == 43;
|
||||||
```
|
```
|
||||||
|
|
||||||
`Engine::register_module` also exposes all _methods_ and _iterators_ from the module to the
|
All functions (usually _methods_) defined in the module and marked with `#[rhai_fn(global)]`,
|
||||||
_global_ namespace, so [getters/setters] and [indexers] for [custom types] work as expected.
|
as well as all _type iterators_, are automatically exposed to the _global_ namespace, so
|
||||||
|
[iteration]({{rootUrl}}/language/for.md), [getters/setters] and [indexers] for [custom types]
|
||||||
|
can work as expected.
|
||||||
|
|
||||||
Therefore, in the example able, `increment` works fine when called in method-call style:
|
Therefore, in the example above, the `increment` method (defined with `#[rhai_fn(global)]`)
|
||||||
|
works fine when called in method-call style:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let x = 42;
|
let x = 42;
|
||||||
@ -481,12 +486,14 @@ Inner attributes can be applied to the inner items of a module to tweak the expo
|
|||||||
|
|
||||||
Parameters should be set on inner attributes to specify the desired behavior.
|
Parameters should be set on inner attributes to specify the desired behavior.
|
||||||
|
|
||||||
| Attribute Parameter | Use with | Apply to | Description |
|
| Attribute Parameter | Use with | Apply to | Description |
|
||||||
| ------------------- | --------------------------- | ----------------------------------------------------- | ------------------------------------------------------ |
|
| ------------------- | --------------------------- | ----------------------------------------------------- | ------------------------------------------------------- |
|
||||||
| `skip` | `#[rhai_fn]`, `#[rhai_mod]` | function or sub-module | do not export this function/sub-module |
|
| `skip` | `#[rhai_fn]`, `#[rhai_mod]` | function or sub-module | do not export this function/sub-module |
|
||||||
| `name = "..."` | `#[rhai_fn]`, `#[rhai_mod]` | function or sub-module | registers function/sub-module under the specified name |
|
| `global` | `#[rhai_fn]` | function | expose this function to the global namespace |
|
||||||
| `get = "..."` | `#[rhai_fn]` | `pub fn (&mut Type) -> Value` | registers a getter for the named property |
|
| `internal` | `#[rhai_fn]` | function | keep this function within the internal module namespace |
|
||||||
| `set = "..."` | `#[rhai_fn]` | `pub fn (&mut Type, Value)` | registers a setter for the named property |
|
| `name = "..."` | `#[rhai_fn]`, `#[rhai_mod]` | function or sub-module | registers function/sub-module under the specified name |
|
||||||
| `index_get` | `#[rhai_fn]` | `pub fn (&mut Type, INT) -> Value` | registers an index getter |
|
| `get = "..."` | `#[rhai_fn]` | `pub fn (&mut Type) -> Value` | registers a getter for the named property |
|
||||||
| `index_set` | `#[rhai_fn]` | `pub fn (&mut Type, INT, Value)` | registers an index setter |
|
| `set = "..."` | `#[rhai_fn]` | `pub fn (&mut Type, Value)` | registers a setter for the named property |
|
||||||
| `return_raw` | `#[rhai_fn]` | `pub fn (...) -> Result<Dynamic, Box<EvalAltResult>>` | marks this as a [fallible function] |
|
| `index_get` | `#[rhai_fn]` | `pub fn (&mut Type, INT) -> Value` | registers an index getter |
|
||||||
|
| `index_set` | `#[rhai_fn]` | `pub fn (&mut Type, INT, Value)` | registers an index setter |
|
||||||
|
| `return_raw` | `#[rhai_fn]` | `pub fn (...) -> Result<Dynamic, Box<EvalAltResult>>` | marks this as a [fallible function] |
|
||||||
|
@ -60,17 +60,22 @@ engine.register_module("calc", module);
|
|||||||
engine.eval::<i64>("calc::inc(41)")? == 42; // refer to the 'Calc' module
|
engine.eval::<i64>("calc::inc(41)")? == 42; // refer to the 'Calc' module
|
||||||
```
|
```
|
||||||
|
|
||||||
`Engine::register_module` also exposes all _methods_ and _iterators_ from the module to the
|
`Module::set_fn_namespace` can expose functions (usually _methods_) in the module
|
||||||
_global_ namespace, so [getters/setters] and [indexers] for [custom types] work as expected.
|
to the _global_ namespace, so [getters/setters] and [indexers] for [custom types] can work as expected.
|
||||||
|
|
||||||
|
Type iterators, because of their special nature, are always exposed to the _global_ namespace.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use rhai::{Engine, Module};
|
use rhai::{Engine, Module, FnNamespace};
|
||||||
|
|
||||||
let mut module = Module::new(); // new module
|
let mut module = Module::new(); // new module
|
||||||
module.set_fn_1_mut("inc", // add new method
|
let hash = module.set_fn_1_mut("inc", // add new method
|
||||||
|x: &mut i64| Ok(x+1)
|
|x: &mut i64| Ok(x+1)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Expose 'inc' to the global namespace (default is 'Internal')
|
||||||
|
module.set_fn_namespace(hash, FnNamespace::Global);
|
||||||
|
|
||||||
// Load the module into the Engine as a sub-module named 'calc'
|
// Load the module into the Engine as a sub-module named 'calc'
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
engine.register_module("calc", module);
|
engine.register_module("calc", module);
|
||||||
|
@ -6,7 +6,7 @@ Modules
|
|||||||
Rhai allows organizing code (functions, both Rust-based or script-based, and variables) into _modules_.
|
Rhai allows organizing code (functions, both Rust-based or script-based, and variables) into _modules_.
|
||||||
Modules can be disabled via the [`no_module`] feature.
|
Modules can be disabled via the [`no_module`] feature.
|
||||||
|
|
||||||
A module is of the type `Module` and holds a collection of functions, variables, iterators and sub-modules.
|
A module is of the type `Module` and holds a collection of functions, variables, type iterators and sub-modules.
|
||||||
It may be created entirely from Rust functions, or it may encapsulate a Rhai script together with the functions
|
It may be created entirely from Rust functions, or it may encapsulate a Rhai script together with the functions
|
||||||
and variables defined by that script.
|
and variables defined by that script.
|
||||||
|
|
||||||
|
94
src/ast.rs
94
src/ast.rs
@ -1,23 +1,7 @@
|
|||||||
//! Module defining the AST (abstract syntax tree).
|
//! Module defining the AST (abstract syntax tree).
|
||||||
|
|
||||||
use crate::dynamic::{Dynamic, Union};
|
use crate::dynamic::Union;
|
||||||
use crate::fn_native::{FnPtr, Shared};
|
use crate::module::NamespaceRef;
|
||||||
use crate::module::{Module, NamespaceRef};
|
|
||||||
use crate::syntax::FnCustomSyntaxEval;
|
|
||||||
use crate::token::{Position, Token, NO_POS};
|
|
||||||
use crate::utils::{ImmutableString, StraightHasherBuilder};
|
|
||||||
use crate::StaticVec;
|
|
||||||
use crate::INT;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
|
||||||
use crate::FLOAT;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
|
||||||
use crate::Array;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
|
||||||
use crate::Map;
|
|
||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
@ -30,14 +14,23 @@ use crate::stdlib::{
|
|||||||
vec,
|
vec,
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
|
use crate::syntax::FnCustomSyntaxEval;
|
||||||
|
use crate::token::Token;
|
||||||
|
use crate::utils::StraightHasherBuilder;
|
||||||
|
use crate::{
|
||||||
|
Dynamic, FnNamespace, FnPtr, ImmutableString, Module, Position, Shared, StaticVec, INT, NO_POS,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
use crate::stdlib::collections::HashSet;
|
use crate::FLOAT;
|
||||||
|
|
||||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
use crate::stdlib::cmp::max;
|
use crate::Array;
|
||||||
|
|
||||||
/// A type representing the access mode of a scripted function.
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
use crate::Map;
|
||||||
|
|
||||||
|
/// A type representing the access mode of a function.
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||||
pub enum FnAccess {
|
pub enum FnAccess {
|
||||||
/// Public function.
|
/// Public function.
|
||||||
@ -46,31 +39,21 @@ pub enum FnAccess {
|
|||||||
Private,
|
Private,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for FnAccess {
|
|
||||||
#[inline(always)]
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::Private => write!(f, "private"),
|
|
||||||
Self::Public => write!(f, "public"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FnAccess {
|
impl FnAccess {
|
||||||
/// Is this access mode private?
|
/// Is this access mode private?
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn is_private(self) -> bool {
|
pub fn is_private(self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::Public => false,
|
|
||||||
Self::Private => true,
|
Self::Private => true,
|
||||||
|
Self::Public => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Is this access mode public?
|
/// Is this access mode public?
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn is_public(self) -> bool {
|
pub fn is_public(self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::Public => true,
|
|
||||||
Self::Private => false,
|
Self::Private => false,
|
||||||
|
Self::Public => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -98,7 +81,7 @@ pub struct ScriptFnDef {
|
|||||||
pub params: StaticVec<ImmutableString>,
|
pub params: StaticVec<ImmutableString>,
|
||||||
/// Access to external variables.
|
/// Access to external variables.
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
pub externals: HashSet<ImmutableString>,
|
pub externals: crate::stdlib::collections::HashSet<ImmutableString>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for ScriptFnDef {
|
impl fmt::Display for ScriptFnDef {
|
||||||
@ -187,7 +170,7 @@ impl AST {
|
|||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn clone_functions_only(&self) -> Self {
|
pub fn clone_functions_only(&self) -> Self {
|
||||||
self.clone_functions_only_filtered(|_, _, _| true)
|
self.clone_functions_only_filtered(|_, _, _, _, _| true)
|
||||||
}
|
}
|
||||||
/// Clone the `AST`'s functions into a new `AST` based on a filter predicate.
|
/// Clone the `AST`'s functions into a new `AST` based on a filter predicate.
|
||||||
/// No statements are cloned.
|
/// No statements are cloned.
|
||||||
@ -197,7 +180,7 @@ impl AST {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn clone_functions_only_filtered(
|
pub fn clone_functions_only_filtered(
|
||||||
&self,
|
&self,
|
||||||
mut filter: impl FnMut(FnAccess, &str, usize) -> bool,
|
mut filter: impl FnMut(FnNamespace, FnAccess, bool, &str, usize) -> bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut functions: Module = Default::default();
|
let mut functions: Module = Default::default();
|
||||||
functions.merge_filtered(&self.1, &mut filter);
|
functions.merge_filtered(&self.1, &mut filter);
|
||||||
@ -260,7 +243,7 @@ impl AST {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn merge(&self, other: &Self) -> Self {
|
pub fn merge(&self, other: &Self) -> Self {
|
||||||
self.merge_filtered(other, |_, _, _| true)
|
self.merge_filtered(other, |_, _, _, _, _| true)
|
||||||
}
|
}
|
||||||
/// Combine one `AST` with another. The second `AST` is consumed.
|
/// Combine one `AST` with another. The second `AST` is consumed.
|
||||||
///
|
///
|
||||||
@ -312,7 +295,7 @@ impl AST {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn combine(&mut self, other: Self) -> &mut Self {
|
pub fn combine(&mut self, other: Self) -> &mut Self {
|
||||||
self.combine_filtered(other, |_, _, _| true)
|
self.combine_filtered(other, |_, _, _, _, _| true)
|
||||||
}
|
}
|
||||||
/// Merge two `AST` into one. Both `AST`'s are untouched and a new, merged, version
|
/// Merge two `AST` into one. Both `AST`'s are untouched and a new, merged, version
|
||||||
/// is returned.
|
/// is returned.
|
||||||
@ -348,7 +331,8 @@ impl AST {
|
|||||||
/// "#)?;
|
/// "#)?;
|
||||||
///
|
///
|
||||||
/// // Merge 'ast2', picking only 'error()' but not 'foo(_)', into 'ast1'
|
/// // Merge 'ast2', picking only 'error()' but not 'foo(_)', into 'ast1'
|
||||||
/// let ast = ast1.merge_filtered(&ast2, |_, name, params| name == "error" && params == 0);
|
/// let ast = ast1.merge_filtered(&ast2, |_, _, script, name, params|
|
||||||
|
/// script && name == "error" && params == 0);
|
||||||
///
|
///
|
||||||
/// // 'ast' is essentially:
|
/// // 'ast' is essentially:
|
||||||
/// //
|
/// //
|
||||||
@ -369,7 +353,7 @@ impl AST {
|
|||||||
pub fn merge_filtered(
|
pub fn merge_filtered(
|
||||||
&self,
|
&self,
|
||||||
other: &Self,
|
other: &Self,
|
||||||
mut filter: impl FnMut(FnAccess, &str, usize) -> bool,
|
mut filter: impl FnMut(FnNamespace, FnAccess, bool, &str, usize) -> bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let Self(statements, functions) = self;
|
let Self(statements, functions) = self;
|
||||||
|
|
||||||
@ -422,7 +406,8 @@ impl AST {
|
|||||||
/// "#)?;
|
/// "#)?;
|
||||||
///
|
///
|
||||||
/// // Combine 'ast2', picking only 'error()' but not 'foo(_)', into 'ast1'
|
/// // Combine 'ast2', picking only 'error()' but not 'foo(_)', into 'ast1'
|
||||||
/// ast1.combine_filtered(ast2, |_, name, params| name == "error" && params == 0);
|
/// ast1.combine_filtered(ast2, |_, _, script, name, params|
|
||||||
|
/// script && name == "error" && params == 0);
|
||||||
///
|
///
|
||||||
/// // 'ast1' is essentially:
|
/// // 'ast1' is essentially:
|
||||||
/// //
|
/// //
|
||||||
@ -443,7 +428,7 @@ impl AST {
|
|||||||
pub fn combine_filtered(
|
pub fn combine_filtered(
|
||||||
&mut self,
|
&mut self,
|
||||||
other: Self,
|
other: Self,
|
||||||
mut filter: impl FnMut(FnAccess, &str, usize) -> bool,
|
mut filter: impl FnMut(FnNamespace, FnAccess, bool, &str, usize) -> bool,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
let Self(ref mut statements, ref mut functions) = self;
|
let Self(ref mut statements, ref mut functions) = self;
|
||||||
statements.extend(other.0.into_iter());
|
statements.extend(other.0.into_iter());
|
||||||
@ -468,22 +453,25 @@ impl AST {
|
|||||||
/// "#)?;
|
/// "#)?;
|
||||||
///
|
///
|
||||||
/// // Remove all functions except 'foo(_)'
|
/// // Remove all functions except 'foo(_)'
|
||||||
/// ast.retain_functions(|_, name, params| name == "foo" && params == 1);
|
/// ast.retain_functions(|_, _, name, params| name == "foo" && params == 1);
|
||||||
/// # }
|
/// # }
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn retain_functions(&mut self, filter: impl FnMut(FnAccess, &str, usize) -> bool) {
|
pub fn retain_functions(
|
||||||
self.1.retain_functions(filter);
|
&mut self,
|
||||||
|
filter: impl FnMut(FnNamespace, FnAccess, &str, usize) -> bool,
|
||||||
|
) {
|
||||||
|
self.1.retain_script_functions(filter);
|
||||||
}
|
}
|
||||||
/// Iterate through all functions
|
/// Iterate through all functions
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn iter_functions<'a>(
|
pub fn iter_functions<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
) -> impl Iterator<Item = (FnAccess, &str, usize, Shared<ScriptFnDef>)> + 'a {
|
) -> impl Iterator<Item = (FnNamespace, FnAccess, &str, usize, Shared<ScriptFnDef>)> + 'a {
|
||||||
self.1.iter_script_fn()
|
self.1.iter_script_fn()
|
||||||
}
|
}
|
||||||
/// Clear all function definitions in the `AST`.
|
/// Clear all function definitions in the `AST`.
|
||||||
@ -940,14 +928,20 @@ impl Expr {
|
|||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Self::Array(x, _) if self.is_constant() => {
|
Self::Array(x, _) if self.is_constant() => {
|
||||||
let mut arr = Array::with_capacity(max(crate::engine::TYPICAL_ARRAY_SIZE, x.len()));
|
let mut arr = Array::with_capacity(crate::stdlib::cmp::max(
|
||||||
|
crate::engine::TYPICAL_ARRAY_SIZE,
|
||||||
|
x.len(),
|
||||||
|
));
|
||||||
arr.extend(x.iter().map(|v| v.get_constant_value().unwrap()));
|
arr.extend(x.iter().map(|v| v.get_constant_value().unwrap()));
|
||||||
Dynamic(Union::Array(Box::new(arr)))
|
Dynamic(Union::Array(Box::new(arr)))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Self::Map(x, _) if self.is_constant() => {
|
Self::Map(x, _) if self.is_constant() => {
|
||||||
let mut map = Map::with_capacity(max(crate::engine::TYPICAL_MAP_SIZE, x.len()));
|
let mut map = Map::with_capacity(crate::stdlib::cmp::max(
|
||||||
|
crate::engine::TYPICAL_MAP_SIZE,
|
||||||
|
x.len(),
|
||||||
|
));
|
||||||
map.extend(
|
map.extend(
|
||||||
x.iter()
|
x.iter()
|
||||||
.map(|(k, v)| (k.name.clone(), v.get_constant_value().unwrap())),
|
.map(|(k, v)| (k.name.clone(), v.get_constant_value().unwrap())),
|
||||||
|
@ -1,19 +1,7 @@
|
|||||||
//! Helper module which defines the `Any` trait to to allow dynamic value handling.
|
//! Helper module which defines the `Any` trait to to allow dynamic value handling.
|
||||||
|
|
||||||
use crate::fn_native::{FnPtr, SendSync};
|
use crate::fn_native::SendSync;
|
||||||
use crate::r#unsafe::{unsafe_cast_box, unsafe_try_cast};
|
use crate::r#unsafe::{unsafe_cast_box, unsafe_try_cast};
|
||||||
use crate::utils::ImmutableString;
|
|
||||||
use crate::INT;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
|
||||||
use crate::FLOAT;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
|
||||||
use crate::Array;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
|
||||||
use crate::Map;
|
|
||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
any::{type_name, Any, TypeId},
|
any::{type_name, Any, TypeId},
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
@ -23,6 +11,16 @@ use crate::stdlib::{
|
|||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
};
|
};
|
||||||
|
use crate::{FnPtr, ImmutableString, INT};
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
use crate::FLOAT;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_index"))]
|
||||||
|
use crate::Array;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
use crate::Map;
|
||||||
|
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
@ -1,20 +1,14 @@
|
|||||||
//! Main module defining the script evaluation `Engine`.
|
//! Main module defining the script evaluation `Engine`.
|
||||||
|
|
||||||
use crate::ast::{Expr, FnCallExpr, Ident, IdentX, ReturnType, Stmt};
|
use crate::ast::{Expr, FnCallExpr, Ident, IdentX, ReturnType, Stmt};
|
||||||
use crate::dynamic::{map_std_type_name, Dynamic, Union, Variant};
|
use crate::dynamic::{map_std_type_name, Union, Variant};
|
||||||
use crate::fn_call::run_builtin_op_assignment;
|
use crate::fn_call::run_builtin_op_assignment;
|
||||||
use crate::fn_native::{CallableFunction, Callback, FnPtr, IteratorFn, OnVarCallback, Shared};
|
use crate::fn_native::{CallableFunction, Callback, IteratorFn, OnVarCallback};
|
||||||
use crate::module::{Module, NamespaceRef};
|
use crate::module::NamespaceRef;
|
||||||
use crate::optimize::OptimizationLevel;
|
use crate::optimize::OptimizationLevel;
|
||||||
use crate::packages::{Package, PackagesCollection, StandardPackage};
|
use crate::packages::{Package, PackagesCollection, StandardPackage};
|
||||||
use crate::r#unsafe::unsafe_cast_var_name_to_lifetime;
|
use crate::r#unsafe::unsafe_cast_var_name_to_lifetime;
|
||||||
use crate::result::EvalAltResult;
|
use crate::scope::EntryType as ScopeEntryType;
|
||||||
use crate::scope::{EntryType as ScopeEntryType, Scope};
|
|
||||||
use crate::syntax::CustomSyntax;
|
|
||||||
use crate::token::{Position, NO_POS};
|
|
||||||
use crate::utils::{get_hasher, ImmutableString};
|
|
||||||
use crate::{calc_native_fn_hash, StaticVec};
|
|
||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
any::{type_name, TypeId},
|
any::{type_name, TypeId},
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
@ -27,21 +21,21 @@ use crate::stdlib::{
|
|||||||
ops::DerefMut,
|
ops::DerefMut,
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
};
|
};
|
||||||
|
use crate::syntax::CustomSyntax;
|
||||||
|
use crate::utils::get_hasher;
|
||||||
|
use crate::{
|
||||||
|
calc_native_fn_hash, Dynamic, EvalAltResult, FnPtr, ImmutableString, Module, Position, Scope,
|
||||||
|
Shared, StaticVec, NO_POS,
|
||||||
|
};
|
||||||
|
|
||||||
/// Variable-sized array of `Dynamic` values.
|
|
||||||
///
|
|
||||||
/// Not available under the `no_index` feature.
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
pub type Array = crate::stdlib::vec::Vec<Dynamic>;
|
use crate::Array;
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
pub const TYPICAL_ARRAY_SIZE: usize = 8; // Small arrays are typical
|
pub const TYPICAL_ARRAY_SIZE: usize = 8; // Small arrays are typical
|
||||||
|
|
||||||
/// Hash map of `Dynamic` values with `ImmutableString` keys.
|
|
||||||
///
|
|
||||||
/// Not available under the `no_object` feature.
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
pub type Map = HashMap<ImmutableString, Dynamic>;
|
use crate::Map;
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
pub const TYPICAL_MAP_SIZE: usize = 8; // Small maps are typical
|
pub const TYPICAL_MAP_SIZE: usize = 8; // Small maps are typical
|
||||||
@ -58,7 +52,7 @@ pub const TYPICAL_MAP_SIZE: usize = 8; // Small maps are typical
|
|||||||
// We cannot use &str or Cow<str> here because `eval` may load a module and the module name will live beyond
|
// We cannot use &str or Cow<str> here because `eval` may load a module and the module name will live beyond
|
||||||
// the AST of the eval script text. The best we can do is a shared reference.
|
// the AST of the eval script text. The best we can do is a shared reference.
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct Imports(StaticVec<(ImmutableString, bool, Shared<Module>)>);
|
pub struct Imports(StaticVec<(ImmutableString, Shared<Module>)>);
|
||||||
|
|
||||||
impl Imports {
|
impl Imports {
|
||||||
/// Get the length of this stack of imported modules.
|
/// Get the length of this stack of imported modules.
|
||||||
@ -71,7 +65,7 @@ impl Imports {
|
|||||||
}
|
}
|
||||||
/// Get the imported module at a particular index.
|
/// Get the imported module at a particular index.
|
||||||
pub fn get(&self, index: usize) -> Option<Shared<Module>> {
|
pub fn get(&self, index: usize) -> Option<Shared<Module>> {
|
||||||
self.0.get(index).map(|(_, _, m)| m).cloned()
|
self.0.get(index).map(|(_, m)| m).cloned()
|
||||||
}
|
}
|
||||||
/// Get the index of an imported module by name.
|
/// Get the index of an imported module by name.
|
||||||
pub fn find(&self, name: &str) -> Option<usize> {
|
pub fn find(&self, name: &str) -> Option<usize> {
|
||||||
@ -79,21 +73,12 @@ impl Imports {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.rev()
|
.rev()
|
||||||
.find(|(_, (key, _, _))| key.as_str() == name)
|
.find(|(_, (key, _))| key.as_str() == name)
|
||||||
.map(|(index, _)| index)
|
.map(|(index, _)| index)
|
||||||
}
|
}
|
||||||
/// Push an imported module onto the stack.
|
/// Push an imported module onto the stack.
|
||||||
pub fn push(&mut self, name: impl Into<ImmutableString>, module: impl Into<Shared<Module>>) {
|
pub fn push(&mut self, name: impl Into<ImmutableString>, module: impl Into<Shared<Module>>) {
|
||||||
self.0.push((name.into(), false, module.into()));
|
self.0.push((name.into(), module.into()));
|
||||||
}
|
|
||||||
/// Push a fixed module onto the stack.
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
pub(crate) fn push_fixed(
|
|
||||||
&mut self,
|
|
||||||
name: impl Into<ImmutableString>,
|
|
||||||
module: impl Into<Shared<Module>>,
|
|
||||||
) {
|
|
||||||
self.0.push((name.into(), true, module.into()));
|
|
||||||
}
|
}
|
||||||
/// Truncate the stack of imported modules to a particular length.
|
/// Truncate the stack of imported modules to a particular length.
|
||||||
pub fn truncate(&mut self, size: usize) {
|
pub fn truncate(&mut self, size: usize) {
|
||||||
@ -101,58 +86,49 @@ impl Imports {
|
|||||||
}
|
}
|
||||||
/// Get an iterator to this stack of imported modules.
|
/// Get an iterator to this stack of imported modules.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn iter(&self) -> impl Iterator<Item = (&str, bool, Shared<Module>)> {
|
pub fn iter(&self) -> impl Iterator<Item = (&str, Shared<Module>)> {
|
||||||
self.0
|
self.0
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(name, fixed, module)| (name.as_str(), *fixed, module.clone()))
|
.map(|(name, module)| (name.as_str(), module.clone()))
|
||||||
}
|
}
|
||||||
/// Get an iterator to this stack of imported modules.
|
/// Get an iterator to this stack of imported modules.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) fn iter_raw<'a>(
|
pub(crate) fn iter_raw<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
) -> impl Iterator<Item = (ImmutableString, bool, Shared<Module>)> + 'a {
|
) -> impl Iterator<Item = (ImmutableString, Shared<Module>)> + 'a {
|
||||||
self.0.iter().cloned()
|
self.0.iter().cloned()
|
||||||
}
|
}
|
||||||
/// Get a consuming iterator to this stack of imported modules.
|
/// Get a consuming iterator to this stack of imported modules.
|
||||||
pub fn into_iter(self) -> impl Iterator<Item = (ImmutableString, bool, Shared<Module>)> {
|
pub fn into_iter(self) -> impl Iterator<Item = (ImmutableString, Shared<Module>)> {
|
||||||
self.0.into_iter()
|
self.0.into_iter()
|
||||||
}
|
}
|
||||||
/// Add a stream of imported modules.
|
/// Add a stream of imported modules.
|
||||||
pub fn extend(
|
pub fn extend(&mut self, stream: impl Iterator<Item = (ImmutableString, Shared<Module>)>) {
|
||||||
&mut self,
|
|
||||||
stream: impl Iterator<Item = (ImmutableString, bool, Shared<Module>)>,
|
|
||||||
) {
|
|
||||||
self.0.extend(stream)
|
self.0.extend(stream)
|
||||||
}
|
}
|
||||||
/// Does the specified function hash key exist in this stack of imported modules?
|
/// Does the specified function hash key exist in this stack of imported modules?
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn contains_fn(&self, hash: u64) -> bool {
|
pub fn contains_fn(&self, hash: u64) -> bool {
|
||||||
self.0
|
self.0.iter().any(|(_, m)| m.contains_qualified_fn(hash))
|
||||||
.iter()
|
|
||||||
.any(|(_, fixed, m)| *fixed && m.contains_qualified_fn(hash))
|
|
||||||
}
|
}
|
||||||
/// Get specified function via its hash key.
|
/// Get specified function via its hash key.
|
||||||
pub fn get_fn(&self, hash: u64) -> Option<&CallableFunction> {
|
pub fn get_fn(&self, hash: u64) -> Option<&CallableFunction> {
|
||||||
self.0
|
self.0
|
||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
.filter(|&&(_, fixed, _)| fixed)
|
.find_map(|(_, m)| m.get_qualified_fn(hash))
|
||||||
.find_map(|(_, _, m)| m.get_qualified_fn(hash))
|
|
||||||
}
|
}
|
||||||
/// Does the specified TypeId iterator exist in this stack of imported modules?
|
/// Does the specified TypeId iterator exist in this stack of imported modules?
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn contains_iter(&self, id: TypeId) -> bool {
|
pub fn contains_iter(&self, id: TypeId) -> bool {
|
||||||
self.0
|
self.0.iter().any(|(_, m)| m.contains_qualified_iter(id))
|
||||||
.iter()
|
|
||||||
.any(|(_, fixed, m)| *fixed && m.contains_qualified_iter(id))
|
|
||||||
}
|
}
|
||||||
/// Get the specified TypeId iterator.
|
/// Get the specified TypeId iterator.
|
||||||
pub fn get_iter(&self, id: TypeId) -> Option<IteratorFn> {
|
pub fn get_iter(&self, id: TypeId) -> Option<IteratorFn> {
|
||||||
self.0
|
self.0
|
||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
.filter(|&&(_, fixed, _)| fixed)
|
.find_map(|(_, m)| m.get_qualified_iter(id))
|
||||||
.find_map(|(_, _, m)| m.get_qualified_iter(id))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,32 +1,26 @@
|
|||||||
//! Module that defines the extern API of `Engine`.
|
//! Module that defines the extern API of `Engine`.
|
||||||
|
|
||||||
use crate::ast::AST;
|
use crate::dynamic::Variant;
|
||||||
use crate::dynamic::{Dynamic, Variant};
|
use crate::engine::{EvalContext, Imports};
|
||||||
use crate::engine::{Engine, EvalContext, Imports};
|
use crate::fn_native::{FnCallArgs, SendSync};
|
||||||
use crate::fn_native::{FnCallArgs, NativeCallContext, SendSync};
|
|
||||||
use crate::optimize::OptimizationLevel;
|
use crate::optimize::OptimizationLevel;
|
||||||
use crate::parse_error::ParseError;
|
|
||||||
use crate::result::EvalAltResult;
|
|
||||||
use crate::scope::Scope;
|
|
||||||
use crate::token::NO_POS;
|
|
||||||
use crate::utils::get_hasher;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
|
||||||
use crate::Array;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
|
||||||
use crate::Map;
|
|
||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
any::{type_name, TypeId},
|
any::{type_name, TypeId},
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
string::String,
|
string::String,
|
||||||
};
|
};
|
||||||
|
use crate::utils::get_hasher;
|
||||||
|
use crate::{
|
||||||
|
scope::Scope, Dynamic, Engine, EvalAltResult, FnAccess, FnNamespace, NativeCallContext,
|
||||||
|
ParseError, AST, NO_POS,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
use crate::Array;
|
||||||
use crate::stdlib::{fs::File, io::prelude::*, path::PathBuf};
|
|
||||||
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
use crate::Map;
|
||||||
|
|
||||||
/// Calculate a unique hash for a script.
|
/// Calculate a unique hash for a script.
|
||||||
fn calc_hash_for_scripts<'a>(scripts: impl IntoIterator<Item = &'a &'a str>) -> u64 {
|
fn calc_hash_for_scripts<'a>(scripts: impl IntoIterator<Item = &'a &'a str>) -> u64 {
|
||||||
@ -62,7 +56,8 @@ impl Engine {
|
|||||||
+ SendSync
|
+ SendSync
|
||||||
+ 'static,
|
+ 'static,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
self.global_module.set_raw_fn(name, arg_types, func);
|
self.global_module
|
||||||
|
.set_raw_fn(name, FnNamespace::Global, FnAccess::Public, arg_types, func);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
/// Register a custom type for use with the `Engine`.
|
/// Register a custom type for use with the `Engine`.
|
||||||
@ -204,15 +199,11 @@ impl Engine {
|
|||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn register_get<T, U>(
|
pub fn register_get<T: Variant + Clone, U: Variant + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: &str,
|
name: &str,
|
||||||
callback: impl Fn(&mut T) -> U + SendSync + 'static,
|
callback: impl Fn(&mut T) -> U + SendSync + 'static,
|
||||||
) -> &mut Self
|
) -> &mut Self {
|
||||||
where
|
|
||||||
T: Variant + Clone,
|
|
||||||
U: Variant + Clone,
|
|
||||||
{
|
|
||||||
crate::RegisterFn::register_fn(self, &crate::engine::make_getter(name), callback)
|
crate::RegisterFn::register_fn(self, &crate::engine::make_getter(name), callback)
|
||||||
}
|
}
|
||||||
/// 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`.
|
||||||
@ -304,15 +295,11 @@ impl Engine {
|
|||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn register_set<T, U>(
|
pub fn register_set<T: Variant + Clone, U: Variant + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: &str,
|
name: &str,
|
||||||
callback: impl Fn(&mut T, U) + SendSync + 'static,
|
callback: impl Fn(&mut T, U) + SendSync + 'static,
|
||||||
) -> &mut Self
|
) -> &mut Self {
|
||||||
where
|
|
||||||
T: Variant + Clone,
|
|
||||||
U: Variant + Clone,
|
|
||||||
{
|
|
||||||
crate::RegisterFn::register_fn(self, &crate::engine::make_setter(name), callback)
|
crate::RegisterFn::register_fn(self, &crate::engine::make_setter(name), callback)
|
||||||
}
|
}
|
||||||
/// Register a setter function for a member of a registered type with the `Engine`.
|
/// Register a setter function for a member of a registered type with the `Engine`.
|
||||||
@ -357,15 +344,11 @@ impl Engine {
|
|||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn register_set_result<T, U>(
|
pub fn register_set_result<T: Variant + Clone, U: Variant + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: &str,
|
name: &str,
|
||||||
callback: impl Fn(&mut T, U) -> Result<(), Box<EvalAltResult>> + SendSync + 'static,
|
callback: impl Fn(&mut T, U) -> Result<(), Box<EvalAltResult>> + SendSync + 'static,
|
||||||
) -> &mut Self
|
) -> &mut Self {
|
||||||
where
|
|
||||||
T: Variant + Clone,
|
|
||||||
U: Variant + Clone,
|
|
||||||
{
|
|
||||||
crate::RegisterResultFn::register_result_fn(
|
crate::RegisterResultFn::register_result_fn(
|
||||||
self,
|
self,
|
||||||
&crate::engine::make_setter(name),
|
&crate::engine::make_setter(name),
|
||||||
@ -412,16 +395,12 @@ impl Engine {
|
|||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn register_get_set<T, U>(
|
pub fn register_get_set<T: Variant + Clone, U: Variant + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: &str,
|
name: &str,
|
||||||
get_fn: impl Fn(&mut T) -> U + SendSync + 'static,
|
get_fn: impl Fn(&mut T) -> U + SendSync + 'static,
|
||||||
set_fn: impl Fn(&mut T, U) + SendSync + 'static,
|
set_fn: impl Fn(&mut T, U) + SendSync + 'static,
|
||||||
) -> &mut Self
|
) -> &mut Self {
|
||||||
where
|
|
||||||
T: Variant + Clone,
|
|
||||||
U: Variant + Clone,
|
|
||||||
{
|
|
||||||
self.register_get(name, get_fn).register_set(name, set_fn)
|
self.register_get(name, get_fn).register_set(name, set_fn)
|
||||||
}
|
}
|
||||||
/// Register an index getter for a custom type with the `Engine`.
|
/// Register an index getter for a custom type with the `Engine`.
|
||||||
@ -467,15 +446,10 @@ impl Engine {
|
|||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn register_indexer_get<T, X, U>(
|
pub fn register_indexer_get<T: Variant + Clone, X: Variant + Clone, U: Variant + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
callback: impl Fn(&mut T, X) -> U + SendSync + 'static,
|
callback: impl Fn(&mut T, X) -> U + SendSync + 'static,
|
||||||
) -> &mut Self
|
) -> &mut Self {
|
||||||
where
|
|
||||||
T: Variant + Clone,
|
|
||||||
U: Variant + Clone,
|
|
||||||
X: Variant + Clone,
|
|
||||||
{
|
|
||||||
if TypeId::of::<T>() == TypeId::of::<Array>() {
|
if TypeId::of::<T>() == TypeId::of::<Array>() {
|
||||||
panic!("Cannot register indexer for arrays.");
|
panic!("Cannot register indexer for arrays.");
|
||||||
}
|
}
|
||||||
@ -538,14 +512,10 @@ impl Engine {
|
|||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn register_indexer_get_result<T, X>(
|
pub fn register_indexer_get_result<T: Variant + Clone, X: Variant + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
callback: impl Fn(&mut T, X) -> Result<Dynamic, Box<EvalAltResult>> + SendSync + 'static,
|
callback: impl Fn(&mut T, X) -> Result<Dynamic, Box<EvalAltResult>> + SendSync + 'static,
|
||||||
) -> &mut Self
|
) -> &mut Self {
|
||||||
where
|
|
||||||
T: Variant + Clone,
|
|
||||||
X: Variant + Clone,
|
|
||||||
{
|
|
||||||
if TypeId::of::<T>() == TypeId::of::<Array>() {
|
if TypeId::of::<T>() == TypeId::of::<Array>() {
|
||||||
panic!("Cannot register indexer for arrays.");
|
panic!("Cannot register indexer for arrays.");
|
||||||
}
|
}
|
||||||
@ -605,15 +575,10 @@ impl Engine {
|
|||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn register_indexer_set<T, X, U>(
|
pub fn register_indexer_set<T: Variant + Clone, X: Variant + Clone, U: Variant + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
callback: impl Fn(&mut T, X, U) + SendSync + 'static,
|
callback: impl Fn(&mut T, X, U) + SendSync + 'static,
|
||||||
) -> &mut Self
|
) -> &mut Self {
|
||||||
where
|
|
||||||
T: Variant + Clone,
|
|
||||||
U: Variant + Clone,
|
|
||||||
X: Variant + Clone,
|
|
||||||
{
|
|
||||||
if TypeId::of::<T>() == TypeId::of::<Array>() {
|
if TypeId::of::<T>() == TypeId::of::<Array>() {
|
||||||
panic!("Cannot register indexer for arrays.");
|
panic!("Cannot register indexer for arrays.");
|
||||||
}
|
}
|
||||||
@ -677,15 +642,14 @@ impl Engine {
|
|||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn register_indexer_set_result<T, X, U>(
|
pub fn register_indexer_set_result<
|
||||||
|
T: Variant + Clone,
|
||||||
|
X: Variant + Clone,
|
||||||
|
U: Variant + Clone,
|
||||||
|
>(
|
||||||
&mut self,
|
&mut self,
|
||||||
callback: impl Fn(&mut T, X, U) -> Result<(), Box<EvalAltResult>> + SendSync + 'static,
|
callback: impl Fn(&mut T, X, U) -> Result<(), Box<EvalAltResult>> + SendSync + 'static,
|
||||||
) -> &mut Self
|
) -> &mut Self {
|
||||||
where
|
|
||||||
T: Variant + Clone,
|
|
||||||
U: Variant + Clone,
|
|
||||||
X: Variant + Clone,
|
|
||||||
{
|
|
||||||
if TypeId::of::<T>() == TypeId::of::<Array>() {
|
if TypeId::of::<T>() == TypeId::of::<Array>() {
|
||||||
panic!("Cannot register indexer for arrays.");
|
panic!("Cannot register indexer for arrays.");
|
||||||
}
|
}
|
||||||
@ -748,20 +712,15 @@ impl Engine {
|
|||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn register_indexer_get_set<T, X, U>(
|
pub fn register_indexer_get_set<T: Variant + Clone, X: Variant + Clone, U: Variant + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
getter: impl Fn(&mut T, X) -> U + SendSync + 'static,
|
getter: impl Fn(&mut T, X) -> U + SendSync + 'static,
|
||||||
setter: impl Fn(&mut T, X, U) -> () + SendSync + 'static,
|
setter: impl Fn(&mut T, X, U) -> () + SendSync + 'static,
|
||||||
) -> &mut Self
|
) -> &mut Self {
|
||||||
where
|
|
||||||
T: Variant + Clone,
|
|
||||||
U: Variant + Clone,
|
|
||||||
X: Variant + Clone,
|
|
||||||
{
|
|
||||||
self.register_indexer_get(getter)
|
self.register_indexer_get(getter)
|
||||||
.register_indexer_set(setter)
|
.register_indexer_set(setter)
|
||||||
}
|
}
|
||||||
/// Register a `Module` as a sub-module with the `Engine`.
|
/// Register a `Module` as a fixed module namespace with the `Engine`.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
@ -775,7 +734,7 @@ impl Engine {
|
|||||||
/// let mut module = Module::new();
|
/// let mut module = Module::new();
|
||||||
/// module.set_fn_1("calc", |x: i64| Ok(x + 1));
|
/// module.set_fn_1("calc", |x: i64| Ok(x + 1));
|
||||||
///
|
///
|
||||||
/// // Register the module as a sub-module
|
/// // Register the module as a fixed sub-module
|
||||||
/// engine.register_module("CalcService", module);
|
/// engine.register_module("CalcService", module);
|
||||||
///
|
///
|
||||||
/// assert_eq!(engine.eval::<i64>("CalcService::calc(41)")?, 42);
|
/// assert_eq!(engine.eval::<i64>("CalcService::calc(41)")?, 42);
|
||||||
@ -794,9 +753,9 @@ impl Engine {
|
|||||||
// Index the module (making a clone copy if necessary) if it is not indexed
|
// Index the module (making a clone copy if necessary) if it is not indexed
|
||||||
let mut module = crate::fn_native::shared_take_or_clone(module);
|
let mut module = crate::fn_native::shared_take_or_clone(module);
|
||||||
module.build_index();
|
module.build_index();
|
||||||
self.global_sub_modules.push_fixed(name, module);
|
self.global_sub_modules.push(name, module);
|
||||||
} else {
|
} else {
|
||||||
self.global_sub_modules.push_fixed(name, module);
|
self.global_sub_modules.push(name, module);
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -935,8 +894,10 @@ impl Engine {
|
|||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn read_file(path: PathBuf) -> Result<String, Box<EvalAltResult>> {
|
fn read_file(path: crate::stdlib::path::PathBuf) -> Result<String, Box<EvalAltResult>> {
|
||||||
let mut f = File::open(path.clone()).map_err(|err| {
|
use crate::stdlib::io::Read;
|
||||||
|
|
||||||
|
let mut f = crate::stdlib::fs::File::open(path.clone()).map_err(|err| {
|
||||||
EvalAltResult::ErrorSystem(
|
EvalAltResult::ErrorSystem(
|
||||||
format!("Cannot open script file '{}'", path.to_string_lossy()),
|
format!("Cannot open script file '{}'", path.to_string_lossy()),
|
||||||
err.into(),
|
err.into(),
|
||||||
@ -977,7 +938,10 @@ impl Engine {
|
|||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn compile_file(&self, path: PathBuf) -> Result<AST, Box<EvalAltResult>> {
|
pub fn compile_file(
|
||||||
|
&self,
|
||||||
|
path: crate::stdlib::path::PathBuf,
|
||||||
|
) -> Result<AST, Box<EvalAltResult>> {
|
||||||
self.compile_file_with_scope(&Default::default(), path)
|
self.compile_file_with_scope(&Default::default(), path)
|
||||||
}
|
}
|
||||||
/// Compile a script file into an `AST` using own scope, which can be used later for evaluation.
|
/// Compile a script file into an `AST` using own scope, which can be used later for evaluation.
|
||||||
@ -1017,7 +981,7 @@ impl Engine {
|
|||||||
pub fn compile_file_with_scope(
|
pub fn compile_file_with_scope(
|
||||||
&self,
|
&self,
|
||||||
scope: &Scope,
|
scope: &Scope,
|
||||||
path: PathBuf,
|
path: crate::stdlib::path::PathBuf,
|
||||||
) -> Result<AST, Box<EvalAltResult>> {
|
) -> Result<AST, Box<EvalAltResult>> {
|
||||||
Self::read_file(path).and_then(|contents| Ok(self.compile_with_scope(scope, &contents)?))
|
Self::read_file(path).and_then(|contents| Ok(self.compile_with_scope(scope, &contents)?))
|
||||||
}
|
}
|
||||||
@ -1201,7 +1165,10 @@ impl Engine {
|
|||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn eval_file<T: Variant + Clone>(&self, path: PathBuf) -> Result<T, Box<EvalAltResult>> {
|
pub fn eval_file<T: Variant + Clone>(
|
||||||
|
&self,
|
||||||
|
path: crate::stdlib::path::PathBuf,
|
||||||
|
) -> Result<T, Box<EvalAltResult>> {
|
||||||
Self::read_file(path).and_then(|contents| self.eval::<T>(&contents))
|
Self::read_file(path).and_then(|contents| self.eval::<T>(&contents))
|
||||||
}
|
}
|
||||||
/// Evaluate a script file with own scope.
|
/// Evaluate a script file with own scope.
|
||||||
@ -1229,7 +1196,7 @@ impl Engine {
|
|||||||
pub fn eval_file_with_scope<T: Variant + Clone>(
|
pub fn eval_file_with_scope<T: Variant + Clone>(
|
||||||
&self,
|
&self,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
path: PathBuf,
|
path: crate::stdlib::path::PathBuf,
|
||||||
) -> Result<T, Box<EvalAltResult>> {
|
) -> Result<T, Box<EvalAltResult>> {
|
||||||
Self::read_file(path).and_then(|contents| self.eval_with_scope::<T>(scope, &contents))
|
Self::read_file(path).and_then(|contents| self.eval_with_scope::<T>(scope, &contents))
|
||||||
}
|
}
|
||||||
@ -1428,7 +1395,10 @@ impl Engine {
|
|||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn consume_file(&self, path: PathBuf) -> Result<(), Box<EvalAltResult>> {
|
pub fn consume_file(
|
||||||
|
&self,
|
||||||
|
path: crate::stdlib::path::PathBuf,
|
||||||
|
) -> Result<(), Box<EvalAltResult>> {
|
||||||
Self::read_file(path).and_then(|contents| self.consume(&contents))
|
Self::read_file(path).and_then(|contents| self.consume(&contents))
|
||||||
}
|
}
|
||||||
/// Evaluate a file with own scope, but throw away the result and only return error (if any).
|
/// Evaluate a file with own scope, but throw away the result and only return error (if any).
|
||||||
@ -1439,7 +1409,7 @@ impl Engine {
|
|||||||
pub fn consume_file_with_scope(
|
pub fn consume_file_with_scope(
|
||||||
&self,
|
&self,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
path: PathBuf,
|
path: crate::stdlib::path::PathBuf,
|
||||||
) -> Result<(), Box<EvalAltResult>> {
|
) -> Result<(), Box<EvalAltResult>> {
|
||||||
Self::read_file(path).and_then(|contents| self.consume_with_scope(scope, &contents))
|
Self::read_file(path).and_then(|contents| self.consume_with_scope(scope, &contents))
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
//! Configuration settings for `Engine`.
|
//! Configuration settings for `Engine`.
|
||||||
|
|
||||||
use crate::engine::Engine;
|
|
||||||
use crate::packages::PackageLibrary;
|
use crate::packages::PackageLibrary;
|
||||||
use crate::token::{is_valid_identifier, Token};
|
|
||||||
|
|
||||||
use crate::stdlib::{format, string::String};
|
use crate::stdlib::{format, string::String};
|
||||||
|
use crate::token::{is_valid_identifier, Token};
|
||||||
|
use crate::Engine;
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
use crate::stdlib::boxed::Box;
|
use crate::stdlib::boxed::Box;
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use crate::dynamic::{Dynamic, Variant};
|
use crate::dynamic::Variant;
|
||||||
use crate::StaticVec;
|
use crate::{Dynamic, StaticVec};
|
||||||
|
|
||||||
/// Trait that represents arguments to a function call.
|
/// Trait that represents arguments to a function call.
|
||||||
/// Any data type that can be converted into a `Vec<Dynamic>` can be used
|
/// Any data type that can be converted into a `Vec<Dynamic>` can be used
|
||||||
|
@ -1,29 +1,15 @@
|
|||||||
//! Implement function-calling mechanism for `Engine`.
|
//! Implement function-calling mechanism for `Engine`.
|
||||||
|
|
||||||
use crate::ast::{Expr, Stmt};
|
use crate::ast::{Expr, Stmt};
|
||||||
use crate::dynamic::Dynamic;
|
|
||||||
use crate::engine::{
|
use crate::engine::{
|
||||||
search_imports, Engine, Imports, State, KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_FN_PTR,
|
search_imports, Imports, State, KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_FN_PTR,
|
||||||
KEYWORD_FN_PTR_CALL, KEYWORD_FN_PTR_CURRY, KEYWORD_IS_DEF_FN, KEYWORD_IS_DEF_VAR,
|
KEYWORD_FN_PTR_CALL, KEYWORD_FN_PTR_CURRY, KEYWORD_IS_DEF_FN, KEYWORD_IS_DEF_VAR,
|
||||||
KEYWORD_PRINT, KEYWORD_TYPE_OF,
|
KEYWORD_PRINT, KEYWORD_TYPE_OF,
|
||||||
};
|
};
|
||||||
use crate::fn_native::{FnCallArgs, FnPtr};
|
use crate::fn_native::FnCallArgs;
|
||||||
use crate::module::{Module, NamespaceRef};
|
use crate::module::NamespaceRef;
|
||||||
use crate::optimize::OptimizationLevel;
|
use crate::optimize::OptimizationLevel;
|
||||||
use crate::parse_error::ParseErrorType;
|
use crate::scope::EntryType as ScopeEntryType;
|
||||||
use crate::result::EvalAltResult;
|
|
||||||
use crate::scope::{EntryType as ScopeEntryType, Scope};
|
|
||||||
use crate::stdlib::ops::Deref;
|
|
||||||
use crate::token::NO_POS;
|
|
||||||
use crate::utils::ImmutableString;
|
|
||||||
use crate::{calc_native_fn_hash, calc_script_fn_hash, StaticVec, INT};
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
|
||||||
use crate::FLOAT;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
|
||||||
use crate::Map;
|
|
||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
any::{type_name, TypeId},
|
any::{type_name, TypeId},
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
@ -31,34 +17,45 @@ use crate::stdlib::{
|
|||||||
format,
|
format,
|
||||||
iter::{empty, once},
|
iter::{empty, once},
|
||||||
mem,
|
mem,
|
||||||
|
ops::Deref,
|
||||||
string::ToString,
|
string::ToString,
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
|
use crate::{
|
||||||
|
calc_native_fn_hash, calc_script_fn_hash, Dynamic, Engine, EvalAltResult, FnPtr,
|
||||||
|
ImmutableString, Module, ParseErrorType, Scope, StaticVec, INT, NO_POS,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
use crate::FLOAT;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
use crate::Map;
|
||||||
|
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
use num_traits::float::Float;
|
use num_traits::float::Float;
|
||||||
|
|
||||||
/// Extract the property name from a getter function name.
|
/// Extract the property name from a getter function name.
|
||||||
|
#[cfg(not(feature = "no_object"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn extract_prop_from_getter(_fn_name: &str) -> Option<&str> {
|
fn extract_prop_from_getter(_fn_name: &str) -> Option<&str> {
|
||||||
#[cfg(not(feature = "no_object"))]
|
|
||||||
if _fn_name.starts_with(crate::engine::FN_GET) {
|
if _fn_name.starts_with(crate::engine::FN_GET) {
|
||||||
return Some(&_fn_name[crate::engine::FN_GET.len()..]);
|
Some(&_fn_name[crate::engine::FN_GET.len()..])
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extract the property name from a setter function name.
|
/// Extract the property name from a setter function name.
|
||||||
|
#[cfg(not(feature = "no_object"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn extract_prop_from_setter(_fn_name: &str) -> Option<&str> {
|
fn extract_prop_from_setter(_fn_name: &str) -> Option<&str> {
|
||||||
#[cfg(not(feature = "no_object"))]
|
|
||||||
if _fn_name.starts_with(crate::engine::FN_SET) {
|
if _fn_name.starts_with(crate::engine::FN_SET) {
|
||||||
return Some(&_fn_name[crate::engine::FN_SET.len()..]);
|
Some(&_fn_name[crate::engine::FN_SET.len()..])
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A type that temporarily stores a mutable reference to a `Dynamic`,
|
/// A type that temporarily stores a mutable reference to a `Dynamic`,
|
||||||
@ -244,6 +241,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Getter function not found?
|
// Getter function not found?
|
||||||
|
#[cfg(not(feature = "no_object"))]
|
||||||
if let Some(prop) = extract_prop_from_getter(fn_name) {
|
if let Some(prop) = extract_prop_from_getter(fn_name) {
|
||||||
return EvalAltResult::ErrorDotExpr(
|
return EvalAltResult::ErrorDotExpr(
|
||||||
format!(
|
format!(
|
||||||
@ -257,6 +255,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Setter function not found?
|
// Setter function not found?
|
||||||
|
#[cfg(not(feature = "no_object"))]
|
||||||
if let Some(prop) = extract_prop_from_setter(fn_name) {
|
if let Some(prop) = extract_prop_from_setter(fn_name) {
|
||||||
return EvalAltResult::ErrorDotExpr(
|
return EvalAltResult::ErrorDotExpr(
|
||||||
format!(
|
format!(
|
||||||
|
@ -3,14 +3,9 @@
|
|||||||
#![cfg(not(feature = "no_function"))]
|
#![cfg(not(feature = "no_function"))]
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use crate::ast::AST;
|
|
||||||
use crate::dynamic::Variant;
|
use crate::dynamic::Variant;
|
||||||
use crate::engine::Engine;
|
|
||||||
use crate::parse_error::ParseError;
|
|
||||||
use crate::result::EvalAltResult;
|
|
||||||
use crate::scope::Scope;
|
|
||||||
|
|
||||||
use crate::stdlib::{boxed::Box, string::ToString};
|
use crate::stdlib::{boxed::Box, string::ToString};
|
||||||
|
use crate::{Engine, EvalAltResult, ParseError, Scope, AST};
|
||||||
|
|
||||||
/// Trait to create a Rust closure from a script.
|
/// Trait to create a Rust closure from a script.
|
||||||
pub trait Func<ARGS, RET> {
|
pub trait Func<ARGS, RET> {
|
||||||
|
@ -1,29 +1,20 @@
|
|||||||
//! Module defining interfaces to native-Rust functions.
|
//! Module defining interfaces to native-Rust functions.
|
||||||
|
|
||||||
use crate::ast::{FnAccess, ScriptFnDef};
|
use crate::ast::{FnAccess, ScriptFnDef};
|
||||||
use crate::dynamic::Dynamic;
|
use crate::engine::Imports;
|
||||||
use crate::engine::{Engine, EvalContext, Imports};
|
|
||||||
use crate::module::Module;
|
|
||||||
use crate::plugin::PluginFunction;
|
use crate::plugin::PluginFunction;
|
||||||
use crate::result::EvalAltResult;
|
|
||||||
use crate::token::{is_valid_identifier, NO_POS};
|
|
||||||
use crate::utils::ImmutableString;
|
|
||||||
use crate::{calc_script_fn_hash, StaticVec};
|
|
||||||
|
|
||||||
use crate::stdlib::{boxed::Box, convert::TryFrom, fmt, iter::empty, mem, string::String};
|
use crate::stdlib::{boxed::Box, convert::TryFrom, fmt, iter::empty, mem, string::String};
|
||||||
|
use crate::token::is_valid_identifier;
|
||||||
|
use crate::{
|
||||||
|
calc_script_fn_hash, Dynamic, Engine, EvalAltResult, EvalContext, ImmutableString, Module,
|
||||||
|
StaticVec, NO_POS,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
use crate::stdlib::rc::Rc;
|
use crate::stdlib::rc::Rc;
|
||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
use crate::stdlib::sync::Arc;
|
use crate::stdlib::sync::Arc;
|
||||||
|
|
||||||
#[cfg(any(not(feature = "no_closure"), not(feature = "no_module")))]
|
|
||||||
#[cfg(not(feature = "sync"))]
|
|
||||||
use crate::stdlib::cell::RefCell;
|
|
||||||
#[cfg(any(not(feature = "no_closure"), not(feature = "no_module")))]
|
|
||||||
#[cfg(feature = "sync")]
|
|
||||||
use crate::stdlib::sync::RwLock;
|
|
||||||
|
|
||||||
/// Trait that maps to `Send + Sync` only under the `sync` feature.
|
/// Trait that maps to `Send + Sync` only under the `sync` feature.
|
||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
pub trait SendSync: Send + Sync {}
|
pub trait SendSync: Send + Sync {}
|
||||||
@ -48,11 +39,11 @@ pub type Shared<T> = Arc<T>;
|
|||||||
/// Synchronized shared object.
|
/// Synchronized shared object.
|
||||||
#[cfg(any(not(feature = "no_closure"), not(feature = "no_module")))]
|
#[cfg(any(not(feature = "no_closure"), not(feature = "no_module")))]
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
pub type Locked<T> = RefCell<T>;
|
pub type Locked<T> = crate::stdlib::cell::RefCell<T>;
|
||||||
/// Synchronized shared object.
|
/// Synchronized shared object.
|
||||||
#[cfg(any(not(feature = "no_closure"), not(feature = "no_module")))]
|
#[cfg(any(not(feature = "no_closure"), not(feature = "no_module")))]
|
||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
pub type Locked<T> = RwLock<T>;
|
pub type Locked<T> = crate::stdlib::sync::RwLock<T>;
|
||||||
|
|
||||||
/// Context of native Rust function call.
|
/// Context of native Rust function call.
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
@ -2,15 +2,13 @@
|
|||||||
|
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use crate::ast::FnAccess;
|
use crate::dynamic::{DynamicWriteLock, Variant};
|
||||||
use crate::dynamic::{Dynamic, DynamicWriteLock, Variant};
|
use crate::fn_native::{CallableFunction, FnAny, FnCallArgs, SendSync};
|
||||||
use crate::engine::Engine;
|
|
||||||
use crate::fn_native::{CallableFunction, FnAny, FnCallArgs, NativeCallContext, SendSync};
|
|
||||||
use crate::r#unsafe::unsafe_cast_box;
|
use crate::r#unsafe::unsafe_cast_box;
|
||||||
use crate::result::EvalAltResult;
|
|
||||||
use crate::utils::ImmutableString;
|
|
||||||
|
|
||||||
use crate::stdlib::{any::TypeId, boxed::Box, mem, string::String};
|
use crate::stdlib::{any::TypeId, boxed::Box, mem, string::String};
|
||||||
|
use crate::{
|
||||||
|
Dynamic, Engine, EvalAltResult, FnAccess, FnNamespace, ImmutableString, NativeCallContext,
|
||||||
|
};
|
||||||
|
|
||||||
/// Trait to register custom functions with the `Engine`.
|
/// Trait to register custom functions with the `Engine`.
|
||||||
pub trait RegisterFn<FN, ARGS, RET> {
|
pub trait RegisterFn<FN, ARGS, RET> {
|
||||||
@ -189,7 +187,7 @@ macro_rules! def_register {
|
|||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn register_fn(&mut self, name: &str, f: FN) -> &mut Self {
|
fn register_fn(&mut self, name: &str, f: FN) -> &mut Self {
|
||||||
self.global_module.set_fn(name, FnAccess::Public,
|
self.global_module.set_fn(name, FnNamespace::Global, FnAccess::Public,
|
||||||
&[$(map_type_id::<$par>()),*],
|
&[$(map_type_id::<$par>()),*],
|
||||||
CallableFunction::$abi(make_func!(f : map_dynamic ; $($par => $let => $clone => $arg),*))
|
CallableFunction::$abi(make_func!(f : map_dynamic ; $($par => $let => $clone => $arg),*))
|
||||||
);
|
);
|
||||||
@ -204,7 +202,7 @@ macro_rules! def_register {
|
|||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn register_result_fn(&mut self, name: &str, f: FN) -> &mut Self {
|
fn register_result_fn(&mut self, name: &str, f: FN) -> &mut Self {
|
||||||
self.global_module.set_fn(name, FnAccess::Public,
|
self.global_module.set_fn(name, FnNamespace::Global, FnAccess::Public,
|
||||||
&[$(map_type_id::<$par>()),*],
|
&[$(map_type_id::<$par>()),*],
|
||||||
CallableFunction::$abi(make_func!(f : map_result ; $($par => $let => $clone => $arg),*))
|
CallableFunction::$abi(make_func!(f : map_result ; $($par => $let => $clone => $arg),*))
|
||||||
);
|
);
|
||||||
|
17
src/lib.rs
17
src/lib.rs
@ -111,12 +111,12 @@ pub type FLOAT = f64;
|
|||||||
#[cfg(feature = "f32_float")]
|
#[cfg(feature = "f32_float")]
|
||||||
pub type FLOAT = f32;
|
pub type FLOAT = f32;
|
||||||
|
|
||||||
pub use ast::AST;
|
pub use ast::{FnAccess, AST};
|
||||||
pub use dynamic::Dynamic;
|
pub use dynamic::Dynamic;
|
||||||
pub use engine::{Engine, EvalContext};
|
pub use engine::{Engine, EvalContext};
|
||||||
pub use fn_native::{FnPtr, NativeCallContext};
|
pub use fn_native::{FnPtr, NativeCallContext};
|
||||||
pub use fn_register::{RegisterFn, RegisterResultFn};
|
pub use fn_register::{RegisterFn, RegisterResultFn};
|
||||||
pub use module::Module;
|
pub use module::{FnNamespace, Module};
|
||||||
pub use parse_error::{LexError, ParseError, ParseErrorType};
|
pub use parse_error::{LexError, ParseError, ParseErrorType};
|
||||||
pub use result::EvalAltResult;
|
pub use result::EvalAltResult;
|
||||||
pub use scope::Scope;
|
pub use scope::Scope;
|
||||||
@ -135,17 +135,20 @@ pub(crate) use utils::{calc_native_fn_hash, calc_script_fn_hash};
|
|||||||
|
|
||||||
pub use rhai_codegen::*;
|
pub use rhai_codegen::*;
|
||||||
|
|
||||||
#[cfg(not(feature = "no_function"))]
|
|
||||||
pub use ast::FnAccess;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
pub use fn_func::Func;
|
pub use fn_func::Func;
|
||||||
|
|
||||||
|
/// Variable-sized array of `Dynamic` values.
|
||||||
|
///
|
||||||
|
/// Not available under the `no_index` feature.
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
pub use engine::Array;
|
pub type Array = stdlib::vec::Vec<Dynamic>;
|
||||||
|
|
||||||
|
/// Hash map of `Dynamic` values with `ImmutableString` keys.
|
||||||
|
///
|
||||||
|
/// Not available under the `no_object` feature.
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
pub use engine::Map;
|
pub type Map = stdlib::collections::HashMap<ImmutableString, Dynamic>;
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
pub use module::ModuleResolver;
|
pub use module::ModuleResolver;
|
||||||
|
@ -1,24 +1,11 @@
|
|||||||
//! Module defining external-loaded modules for Rhai.
|
//! Module defining external-loaded modules for Rhai.
|
||||||
|
|
||||||
use crate::ast::{FnAccess, IdentX};
|
use crate::ast::{FnAccess, IdentX};
|
||||||
use crate::dynamic::{Dynamic, Variant};
|
use crate::dynamic::Variant;
|
||||||
use crate::fn_native::{
|
use crate::fn_native::{
|
||||||
shared_make_mut, shared_take_or_clone, CallableFunction, FnCallArgs, IteratorFn,
|
shared_make_mut, shared_take_or_clone, CallableFunction, FnCallArgs, IteratorFn, SendSync,
|
||||||
NativeCallContext, SendSync, Shared,
|
|
||||||
};
|
};
|
||||||
use crate::fn_register::by_value as cast_arg;
|
use crate::fn_register::by_value as cast_arg;
|
||||||
use crate::result::EvalAltResult;
|
|
||||||
use crate::token::{Token, NO_POS};
|
|
||||||
use crate::utils::{ImmutableString, StraightHasherBuilder};
|
|
||||||
use crate::StaticVec;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
|
||||||
use crate::Array;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
|
||||||
use crate::Map;
|
|
||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
any::TypeId,
|
any::TypeId,
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
@ -30,12 +17,57 @@ use crate::stdlib::{
|
|||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
|
use crate::token::Token;
|
||||||
|
use crate::utils::StraightHasherBuilder;
|
||||||
|
use crate::{
|
||||||
|
Dynamic, EvalAltResult, ImmutableString, NativeCallContext, Shared, StaticVec, NO_POS,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_index"))]
|
||||||
|
use crate::Array;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_index"))]
|
||||||
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
use crate::Map;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_function"))]
|
||||||
|
pub type SharedScriptFnDef = Shared<crate::ast::ScriptFnDef>;
|
||||||
|
|
||||||
|
/// A type representing the namespace of a function.
|
||||||
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||||
|
pub enum FnNamespace {
|
||||||
|
/// Global namespace.
|
||||||
|
Global,
|
||||||
|
/// Internal only.
|
||||||
|
Internal,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FnNamespace {
|
||||||
|
/// Is this namespace global?
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn is_global(self) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::Global => true,
|
||||||
|
Self::Internal => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Is this namespace internal?
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn is_internal(self) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::Global => false,
|
||||||
|
Self::Internal => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Data structure containing a single registered function.
|
/// Data structure containing a single registered function.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct FuncInfo {
|
pub struct FuncInfo {
|
||||||
/// Function instance.
|
/// Function instance.
|
||||||
pub func: CallableFunction,
|
pub func: CallableFunction,
|
||||||
|
/// Function namespace.
|
||||||
|
pub namespace: FnNamespace,
|
||||||
/// Function access mode.
|
/// Function access mode.
|
||||||
pub access: FnAccess,
|
pub access: FnAccess,
|
||||||
/// Function name.
|
/// Function name.
|
||||||
@ -282,7 +314,7 @@ impl Module {
|
|||||||
/// If there is an existing function of the same name and number of arguments, it is replaced.
|
/// If there is an existing function of the same name and number of arguments, it is replaced.
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn set_script_fn(&mut self, fn_def: Shared<crate::ast::ScriptFnDef>) -> u64 {
|
pub(crate) fn set_script_fn(&mut self, fn_def: SharedScriptFnDef) -> u64 {
|
||||||
// None + function name + number of arguments.
|
// None + function name + number of arguments.
|
||||||
let num_params = fn_def.params.len();
|
let num_params = fn_def.params.len();
|
||||||
let hash_script = crate::calc_script_fn_hash(empty(), &fn_def.name, num_params);
|
let hash_script = crate::calc_script_fn_hash(empty(), &fn_def.name, num_params);
|
||||||
@ -290,6 +322,7 @@ impl Module {
|
|||||||
hash_script,
|
hash_script,
|
||||||
FuncInfo {
|
FuncInfo {
|
||||||
name: fn_def.name.to_string(),
|
name: fn_def.name.to_string(),
|
||||||
|
namespace: FnNamespace::Internal,
|
||||||
access: fn_def.access,
|
access: fn_def.access,
|
||||||
params: num_params,
|
params: num_params,
|
||||||
types: None,
|
types: None,
|
||||||
@ -308,7 +341,7 @@ impl Module {
|
|||||||
name: &str,
|
name: &str,
|
||||||
num_params: usize,
|
num_params: usize,
|
||||||
public_only: bool,
|
public_only: bool,
|
||||||
) -> Option<&Shared<crate::ast::ScriptFnDef>> {
|
) -> Option<&SharedScriptFnDef> {
|
||||||
self.functions
|
self.functions
|
||||||
.values()
|
.values()
|
||||||
.find(
|
.find(
|
||||||
@ -440,6 +473,7 @@ impl Module {
|
|||||||
pub fn set_fn(
|
pub fn set_fn(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: impl Into<String>,
|
name: impl Into<String>,
|
||||||
|
namespace: FnNamespace,
|
||||||
access: FnAccess,
|
access: FnAccess,
|
||||||
arg_types: &[TypeId],
|
arg_types: &[TypeId],
|
||||||
func: CallableFunction,
|
func: CallableFunction,
|
||||||
@ -464,6 +498,7 @@ impl Module {
|
|||||||
hash_fn,
|
hash_fn,
|
||||||
FuncInfo {
|
FuncInfo {
|
||||||
name,
|
name,
|
||||||
|
namespace,
|
||||||
access,
|
access,
|
||||||
params: params.len(),
|
params: params.len(),
|
||||||
types: Some(params),
|
types: Some(params),
|
||||||
@ -507,10 +542,11 @@ impl Module {
|
|||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use rhai::Module;
|
/// use rhai::{Module, FnNamespace, FnAccess};
|
||||||
///
|
///
|
||||||
/// let mut module = Module::new();
|
/// let mut module = Module::new();
|
||||||
/// let hash = module.set_raw_fn("double_or_not",
|
/// let hash = module.set_raw_fn("double_or_not",
|
||||||
|
/// FnNamespace::Internal, FnAccess::Public,
|
||||||
/// // Pass parameter types via a slice with TypeId's
|
/// // Pass parameter types via a slice with TypeId's
|
||||||
/// &[std::any::TypeId::of::<i64>(), std::any::TypeId::of::<bool>()],
|
/// &[std::any::TypeId::of::<i64>(), std::any::TypeId::of::<bool>()],
|
||||||
/// // Fixed closure signature
|
/// // Fixed closure signature
|
||||||
@ -539,6 +575,8 @@ impl Module {
|
|||||||
pub fn set_raw_fn<T: Variant + Clone>(
|
pub fn set_raw_fn<T: Variant + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: impl Into<String>,
|
name: impl Into<String>,
|
||||||
|
namespace: FnNamespace,
|
||||||
|
access: FnAccess,
|
||||||
arg_types: &[TypeId],
|
arg_types: &[TypeId],
|
||||||
func: impl Fn(NativeCallContext, &mut FnCallArgs) -> Result<T, Box<EvalAltResult>>
|
func: impl Fn(NativeCallContext, &mut FnCallArgs) -> Result<T, Box<EvalAltResult>>
|
||||||
+ SendSync
|
+ SendSync
|
||||||
@ -546,14 +584,40 @@ impl Module {
|
|||||||
) -> u64 {
|
) -> u64 {
|
||||||
let f =
|
let f =
|
||||||
move |ctx: NativeCallContext, args: &mut FnCallArgs| func(ctx, args).map(Dynamic::from);
|
move |ctx: NativeCallContext, args: &mut FnCallArgs| func(ctx, args).map(Dynamic::from);
|
||||||
|
|
||||||
self.set_fn(
|
self.set_fn(
|
||||||
name,
|
name,
|
||||||
FnAccess::Public,
|
namespace,
|
||||||
|
access,
|
||||||
arg_types,
|
arg_types,
|
||||||
CallableFunction::from_method(Box::new(f)),
|
CallableFunction::from_method(Box::new(f)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the namespace of a registered function.
|
||||||
|
/// Returns `None` if a function with the hash does not exist.
|
||||||
|
///
|
||||||
|
/// The `u64` hash is calculated by the function `crate::calc_native_fn_hash`.
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn get_fn_namespace(&self, hash: u64) -> Option<FnNamespace> {
|
||||||
|
self.functions.get(&hash).map(|f| f.namespace)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the namespace of a registered function.
|
||||||
|
/// Returns the original namespace or `None` if a function with the hash does not exist.
|
||||||
|
///
|
||||||
|
/// The `u64` hash is calculated by the function `crate::calc_native_fn_hash`.
|
||||||
|
#[inline]
|
||||||
|
pub fn set_fn_namespace(&mut self, hash: u64, namespace: FnNamespace) -> Option<FnNamespace> {
|
||||||
|
if let Some(f) = self.functions.get_mut(&hash) {
|
||||||
|
let old_ns = f.namespace;
|
||||||
|
f.namespace = namespace;
|
||||||
|
Some(old_ns)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Set a Rust function taking no parameters into the module, returning a hash key.
|
/// Set a Rust function taking no parameters into the module, returning a hash key.
|
||||||
///
|
///
|
||||||
/// If there is a similar existing Rust function, it is replaced.
|
/// If there is a similar existing Rust function, it is replaced.
|
||||||
@ -577,6 +641,7 @@ impl Module {
|
|||||||
let arg_types = [];
|
let arg_types = [];
|
||||||
self.set_fn(
|
self.set_fn(
|
||||||
name,
|
name,
|
||||||
|
FnNamespace::Internal,
|
||||||
FnAccess::Public,
|
FnAccess::Public,
|
||||||
&arg_types,
|
&arg_types,
|
||||||
CallableFunction::from_pure(Box::new(f)),
|
CallableFunction::from_pure(Box::new(f)),
|
||||||
@ -608,6 +673,7 @@ impl Module {
|
|||||||
let arg_types = [TypeId::of::<A>()];
|
let arg_types = [TypeId::of::<A>()];
|
||||||
self.set_fn(
|
self.set_fn(
|
||||||
name,
|
name,
|
||||||
|
FnNamespace::Internal,
|
||||||
FnAccess::Public,
|
FnAccess::Public,
|
||||||
&arg_types,
|
&arg_types,
|
||||||
CallableFunction::from_pure(Box::new(f)),
|
CallableFunction::from_pure(Box::new(f)),
|
||||||
@ -639,6 +705,7 @@ impl Module {
|
|||||||
let arg_types = [TypeId::of::<A>()];
|
let arg_types = [TypeId::of::<A>()];
|
||||||
self.set_fn(
|
self.set_fn(
|
||||||
name,
|
name,
|
||||||
|
FnNamespace::Internal,
|
||||||
FnAccess::Public,
|
FnAccess::Public,
|
||||||
&arg_types,
|
&arg_types,
|
||||||
CallableFunction::from_method(Box::new(f)),
|
CallableFunction::from_method(Box::new(f)),
|
||||||
@ -698,6 +765,7 @@ impl Module {
|
|||||||
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>()];
|
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>()];
|
||||||
self.set_fn(
|
self.set_fn(
|
||||||
name,
|
name,
|
||||||
|
FnNamespace::Internal,
|
||||||
FnAccess::Public,
|
FnAccess::Public,
|
||||||
&arg_types,
|
&arg_types,
|
||||||
CallableFunction::from_pure(Box::new(f)),
|
CallableFunction::from_pure(Box::new(f)),
|
||||||
@ -735,6 +803,7 @@ impl Module {
|
|||||||
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>()];
|
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>()];
|
||||||
self.set_fn(
|
self.set_fn(
|
||||||
name,
|
name,
|
||||||
|
FnNamespace::Internal,
|
||||||
FnAccess::Public,
|
FnAccess::Public,
|
||||||
&arg_types,
|
&arg_types,
|
||||||
CallableFunction::from_method(Box::new(f)),
|
CallableFunction::from_method(Box::new(f)),
|
||||||
@ -848,6 +917,7 @@ impl Module {
|
|||||||
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()];
|
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()];
|
||||||
self.set_fn(
|
self.set_fn(
|
||||||
name,
|
name,
|
||||||
|
FnNamespace::Internal,
|
||||||
FnAccess::Public,
|
FnAccess::Public,
|
||||||
&arg_types,
|
&arg_types,
|
||||||
CallableFunction::from_pure(Box::new(f)),
|
CallableFunction::from_pure(Box::new(f)),
|
||||||
@ -891,6 +961,7 @@ impl Module {
|
|||||||
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()];
|
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()];
|
||||||
self.set_fn(
|
self.set_fn(
|
||||||
name,
|
name,
|
||||||
|
FnNamespace::Internal,
|
||||||
FnAccess::Public,
|
FnAccess::Public,
|
||||||
&arg_types,
|
&arg_types,
|
||||||
CallableFunction::from_method(Box::new(f)),
|
CallableFunction::from_method(Box::new(f)),
|
||||||
@ -949,6 +1020,7 @@ impl Module {
|
|||||||
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()];
|
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()];
|
||||||
self.set_fn(
|
self.set_fn(
|
||||||
crate::engine::FN_IDX_SET,
|
crate::engine::FN_IDX_SET,
|
||||||
|
FnNamespace::Internal,
|
||||||
FnAccess::Public,
|
FnAccess::Public,
|
||||||
&arg_types,
|
&arg_types,
|
||||||
CallableFunction::from_method(Box::new(f)),
|
CallableFunction::from_method(Box::new(f)),
|
||||||
@ -1039,6 +1111,7 @@ impl Module {
|
|||||||
];
|
];
|
||||||
self.set_fn(
|
self.set_fn(
|
||||||
name,
|
name,
|
||||||
|
FnNamespace::Internal,
|
||||||
FnAccess::Public,
|
FnAccess::Public,
|
||||||
&arg_types,
|
&arg_types,
|
||||||
CallableFunction::from_pure(Box::new(f)),
|
CallableFunction::from_pure(Box::new(f)),
|
||||||
@ -1089,6 +1162,7 @@ impl Module {
|
|||||||
];
|
];
|
||||||
self.set_fn(
|
self.set_fn(
|
||||||
name,
|
name,
|
||||||
|
FnNamespace::Internal,
|
||||||
FnAccess::Public,
|
FnAccess::Public,
|
||||||
&arg_types,
|
&arg_types,
|
||||||
CallableFunction::from_method(Box::new(f)),
|
CallableFunction::from_method(Box::new(f)),
|
||||||
@ -1196,14 +1270,14 @@ impl Module {
|
|||||||
/// Merge another module into this module.
|
/// Merge another module into this module.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn merge(&mut self, other: &Self) -> &mut Self {
|
pub fn merge(&mut self, other: &Self) -> &mut Self {
|
||||||
self.merge_filtered(other, &mut |_, _, _| true)
|
self.merge_filtered(other, &mut |_, _, _, _, _| true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Merge another module into this module, with only selected script-defined functions based on a filter predicate.
|
/// Merge another module into this module based on a filter predicate.
|
||||||
pub(crate) fn merge_filtered(
|
pub(crate) fn merge_filtered(
|
||||||
&mut self,
|
&mut self,
|
||||||
other: &Self,
|
other: &Self,
|
||||||
mut _filter: &mut impl FnMut(FnAccess, &str, usize) -> bool,
|
mut _filter: &mut impl FnMut(FnNamespace, FnAccess, bool, &str, usize) -> bool,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
other.modules.iter().for_each(|(k, v)| {
|
other.modules.iter().for_each(|(k, v)| {
|
||||||
@ -1221,13 +1295,27 @@ impl Module {
|
|||||||
other
|
other
|
||||||
.functions
|
.functions
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, FuncInfo { func, .. })| match func {
|
.filter(
|
||||||
#[cfg(not(feature = "no_function"))]
|
|(
|
||||||
CallableFunction::Script(f) => {
|
_,
|
||||||
_filter(f.access, f.name.as_str(), f.params.len())
|
FuncInfo {
|
||||||
}
|
namespace,
|
||||||
_ => true,
|
access,
|
||||||
})
|
name,
|
||||||
|
params,
|
||||||
|
func,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
)| {
|
||||||
|
_filter(
|
||||||
|
*namespace,
|
||||||
|
*access,
|
||||||
|
func.is_script(),
|
||||||
|
name.as_str(),
|
||||||
|
*params,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
.map(|(&k, v)| (k, v.clone())),
|
.map(|(&k, v)| (k, v.clone())),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1239,18 +1327,30 @@ impl Module {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Filter out the functions, retaining only some based on a filter predicate.
|
/// Filter out the functions, retaining only some script-defined functions based on a filter predicate.
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn retain_functions(
|
pub(crate) fn retain_script_functions(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut filter: impl FnMut(FnAccess, &str, usize) -> bool,
|
mut filter: impl FnMut(FnNamespace, FnAccess, &str, usize) -> bool,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
self.functions
|
self.functions.retain(
|
||||||
.retain(|_, FuncInfo { func, .. }| match func {
|
|_,
|
||||||
CallableFunction::Script(f) => filter(f.access, f.name.as_str(), f.params.len()),
|
FuncInfo {
|
||||||
_ => true,
|
namespace,
|
||||||
});
|
access,
|
||||||
|
name,
|
||||||
|
params,
|
||||||
|
func,
|
||||||
|
..
|
||||||
|
}| {
|
||||||
|
if func.is_script() {
|
||||||
|
filter(*namespace, *access, name.as_str(), *params)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
self.all_functions.clear();
|
self.all_functions.clear();
|
||||||
self.all_variables.clear();
|
self.all_variables.clear();
|
||||||
@ -1294,16 +1394,25 @@ impl Module {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn iter_script_fn<'a>(
|
pub(crate) fn iter_script_fn<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
) -> impl Iterator<Item = (FnAccess, &str, usize, Shared<crate::ast::ScriptFnDef>)> + 'a {
|
) -> impl Iterator<Item = (FnNamespace, FnAccess, &str, usize, SharedScriptFnDef)> + 'a {
|
||||||
self.functions
|
self.functions.values().filter(|f| f.func.is_script()).map(
|
||||||
.values()
|
|FuncInfo {
|
||||||
.map(|f| &f.func)
|
namespace,
|
||||||
.filter(|f| f.is_script())
|
access,
|
||||||
.map(CallableFunction::get_fn_def)
|
name,
|
||||||
.map(|f| {
|
params,
|
||||||
let func = f.clone();
|
func,
|
||||||
(f.access, f.name.as_str(), f.params.len(), func)
|
..
|
||||||
})
|
}| {
|
||||||
|
(
|
||||||
|
*namespace,
|
||||||
|
*access,
|
||||||
|
name.as_str(),
|
||||||
|
*params,
|
||||||
|
func.get_fn_def().clone(),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an iterator over all script-defined functions in the module.
|
/// Get an iterator over all script-defined functions in the module.
|
||||||
@ -1315,14 +1424,17 @@ impl Module {
|
|||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
#[cfg(not(feature = "internals"))]
|
#[cfg(not(feature = "internals"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn iter_script_fn_info(&self) -> impl Iterator<Item = (FnAccess, &str, usize)> {
|
pub fn iter_script_fn_info(
|
||||||
|
&self,
|
||||||
|
) -> impl Iterator<Item = (FnNamespace, FnAccess, &str, usize)> {
|
||||||
self.functions.values().filter(|f| f.func.is_script()).map(
|
self.functions.values().filter(|f| f.func.is_script()).map(
|
||||||
|FuncInfo {
|
|FuncInfo {
|
||||||
name,
|
name,
|
||||||
|
namespace,
|
||||||
access,
|
access,
|
||||||
params,
|
params,
|
||||||
..
|
..
|
||||||
}| (*access, name.as_str(), *params),
|
}| (*namespace, *access, name.as_str(), *params),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1339,7 +1451,7 @@ impl Module {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn iter_script_fn_info(
|
pub fn iter_script_fn_info(
|
||||||
&self,
|
&self,
|
||||||
) -> impl Iterator<Item = (FnAccess, &str, usize, Shared<crate::ast::ScriptFnDef>)> {
|
) -> impl Iterator<Item = (FnNamespace, FnAccess, &str, usize, SharedScriptFnDef)> {
|
||||||
self.iter_script_fn()
|
self.iter_script_fn()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1393,13 +1505,10 @@ impl Module {
|
|||||||
// Extra modules left in the scope become sub-modules
|
// Extra modules left in the scope become sub-modules
|
||||||
let mut func_mods: crate::engine::Imports = Default::default();
|
let mut func_mods: crate::engine::Imports = Default::default();
|
||||||
|
|
||||||
mods.into_iter()
|
mods.into_iter().skip(orig_mods_len).for_each(|(alias, m)| {
|
||||||
.skip(orig_mods_len)
|
func_mods.push(alias.clone(), m.clone());
|
||||||
.filter(|&(_, fixed, _)| !fixed)
|
module.set_sub_module(alias, m);
|
||||||
.for_each(|(alias, _, m)| {
|
});
|
||||||
func_mods.push(alias.clone(), m.clone());
|
|
||||||
module.set_sub_module(alias, m);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Non-private functions defined become module functions
|
// Non-private functions defined become module functions
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
@ -1407,8 +1516,8 @@ impl Module {
|
|||||||
let ast_lib: Shared<Module> = ast.lib().clone().into();
|
let ast_lib: Shared<Module> = ast.lib().clone().into();
|
||||||
|
|
||||||
ast.iter_functions()
|
ast.iter_functions()
|
||||||
.filter(|(access, _, _, _)| !access.is_private())
|
.filter(|(_, access, _, _, _)| !access.is_private())
|
||||||
.for_each(|(_, _, _, func)| {
|
.for_each(|(_, _, _, _, func)| {
|
||||||
// Encapsulate AST environment
|
// Encapsulate AST environment
|
||||||
let mut func = func.as_ref().clone();
|
let mut func = func.as_ref().clone();
|
||||||
func.lib = Some(ast_lib.clone());
|
func.lib = Some(ast_lib.clone());
|
||||||
@ -1464,6 +1573,7 @@ impl Module {
|
|||||||
&hash,
|
&hash,
|
||||||
FuncInfo {
|
FuncInfo {
|
||||||
name,
|
name,
|
||||||
|
namespace,
|
||||||
params,
|
params,
|
||||||
types,
|
types,
|
||||||
func,
|
func,
|
||||||
@ -1471,22 +1581,20 @@ impl Module {
|
|||||||
},
|
},
|
||||||
)| {
|
)| {
|
||||||
// Flatten all methods so they can be available without namespace qualifiers
|
// Flatten all methods so they can be available without namespace qualifiers
|
||||||
#[cfg(not(feature = "no_object"))]
|
if namespace.is_global() {
|
||||||
if func.is_method() {
|
|
||||||
functions.insert(hash, func.clone());
|
functions.insert(hash, func.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Qualifiers + function name + number of arguments.
|
||||||
|
let hash_qualified_script =
|
||||||
|
crate::calc_script_fn_hash(qualifiers.iter().cloned(), name, *params);
|
||||||
|
|
||||||
if let Some(param_types) = types {
|
if let Some(param_types) = types {
|
||||||
assert_eq!(*params, param_types.len());
|
assert_eq!(*params, param_types.len());
|
||||||
|
|
||||||
// Namespace-qualified Rust functions are indexed in two steps:
|
// Namespace-qualified Rust functions are indexed in two steps:
|
||||||
// 1) Calculate a hash in a similar manner to script-defined functions,
|
// 1) Calculate a hash in a similar manner to script-defined functions,
|
||||||
// i.e. qualifiers + function name + number of arguments.
|
// i.e. qualifiers + function name + number of arguments.
|
||||||
let hash_qualified_script = crate::calc_script_fn_hash(
|
|
||||||
qualifiers.iter().cloned(),
|
|
||||||
name,
|
|
||||||
*params,
|
|
||||||
);
|
|
||||||
// 2) Calculate a second hash with no qualifiers, empty function name,
|
// 2) Calculate a second hash with no qualifiers, empty function name,
|
||||||
// and the actual list of argument `TypeId`'.s
|
// and the actual list of argument `TypeId`'.s
|
||||||
let hash_fn_args = crate::calc_native_fn_hash(
|
let hash_fn_args = crate::calc_native_fn_hash(
|
||||||
@ -1499,17 +1607,6 @@ impl Module {
|
|||||||
|
|
||||||
functions.insert(hash_qualified_fn, func.clone());
|
functions.insert(hash_qualified_fn, func.clone());
|
||||||
} else if cfg!(not(feature = "no_function")) {
|
} else if cfg!(not(feature = "no_function")) {
|
||||||
let hash_qualified_script =
|
|
||||||
if cfg!(feature = "no_object") && qualifiers.is_empty() {
|
|
||||||
hash
|
|
||||||
} else {
|
|
||||||
// Qualifiers + function name + number of arguments.
|
|
||||||
crate::calc_script_fn_hash(
|
|
||||||
qualifiers.iter().map(|&v| v),
|
|
||||||
&name,
|
|
||||||
*params,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
functions.insert(hash_qualified_script, func.clone());
|
functions.insert(hash_qualified_script, func.clone());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,10 +1,5 @@
|
|||||||
use crate::engine::Engine;
|
|
||||||
use crate::fn_native::Shared;
|
|
||||||
use crate::module::{Module, ModuleResolver};
|
|
||||||
use crate::result::EvalAltResult;
|
|
||||||
use crate::token::Position;
|
|
||||||
|
|
||||||
use crate::stdlib::{boxed::Box, ops::AddAssign, vec::Vec};
|
use crate::stdlib::{boxed::Box, ops::AddAssign, vec::Vec};
|
||||||
|
use crate::{Engine, EvalAltResult, Module, ModuleResolver, Position, Shared};
|
||||||
|
|
||||||
/// Module resolution service that holds a collection of module resolves,
|
/// Module resolution service that holds a collection of module resolves,
|
||||||
/// to be searched in sequential order.
|
/// to be searched in sequential order.
|
||||||
|
@ -1,12 +1,7 @@
|
|||||||
use crate::engine::Engine;
|
|
||||||
use crate::fn_native::{Locked, Shared};
|
|
||||||
use crate::module::{Module, ModuleResolver};
|
|
||||||
use crate::result::EvalAltResult;
|
|
||||||
use crate::token::Position;
|
|
||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
boxed::Box, collections::HashMap, io::Error as IoError, path::PathBuf, string::String,
|
boxed::Box, collections::HashMap, io::Error as IoError, path::PathBuf, string::String,
|
||||||
};
|
};
|
||||||
|
use crate::{Engine, EvalAltResult, Locked, Module, ModuleResolver, Position, Shared};
|
||||||
|
|
||||||
/// Module resolution service that loads module script files from the file system.
|
/// Module resolution service that loads module script files from the file system.
|
||||||
///
|
///
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
use crate::engine::Engine;
|
use crate::fn_native::SendSync;
|
||||||
use crate::fn_native::{SendSync, Shared};
|
|
||||||
use crate::module::Module;
|
|
||||||
use crate::result::EvalAltResult;
|
|
||||||
use crate::token::Position;
|
|
||||||
|
|
||||||
use crate::stdlib::boxed::Box;
|
use crate::stdlib::boxed::Box;
|
||||||
|
use crate::{Engine, EvalAltResult, Module, Position, Shared};
|
||||||
|
|
||||||
mod collection;
|
mod collection;
|
||||||
pub use collection::ModuleResolversCollection;
|
pub use collection::ModuleResolversCollection;
|
||||||
|
@ -1,10 +1,5 @@
|
|||||||
use crate::engine::Engine;
|
|
||||||
use crate::fn_native::Shared;
|
|
||||||
use crate::module::{Module, ModuleResolver};
|
|
||||||
use crate::result::EvalAltResult;
|
|
||||||
use crate::token::Position;
|
|
||||||
|
|
||||||
use crate::stdlib::{boxed::Box, collections::HashMap, ops::AddAssign, string::String};
|
use crate::stdlib::{boxed::Box, collections::HashMap, ops::AddAssign, string::String};
|
||||||
|
use crate::{Engine, EvalAltResult, Module, ModuleResolver, Position, Shared};
|
||||||
|
|
||||||
/// Module resolution service that serves modules added into it.
|
/// Module resolution service that serves modules added into it.
|
||||||
///
|
///
|
||||||
|
@ -1,19 +1,12 @@
|
|||||||
//! Module implementing the AST optimizer.
|
//! Module implementing the AST optimizer.
|
||||||
|
|
||||||
use crate::ast::{Expr, ScriptFnDef, Stmt, AST};
|
use crate::ast::{Expr, ScriptFnDef, Stmt};
|
||||||
use crate::dynamic::Dynamic;
|
|
||||||
use crate::engine::{
|
use crate::engine::{
|
||||||
Engine, KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_IS_DEF_FN, KEYWORD_IS_DEF_VAR, KEYWORD_PRINT,
|
KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_IS_DEF_FN, KEYWORD_IS_DEF_VAR, KEYWORD_PRINT,
|
||||||
KEYWORD_TYPE_OF,
|
KEYWORD_TYPE_OF,
|
||||||
};
|
};
|
||||||
use crate::fn_call::run_builtin_binary_op;
|
use crate::fn_call::run_builtin_binary_op;
|
||||||
use crate::module::Module;
|
|
||||||
use crate::parser::map_dynamic_to_expr;
|
use crate::parser::map_dynamic_to_expr;
|
||||||
use crate::scope::Scope;
|
|
||||||
use crate::token::{is_valid_identifier, Position, NO_POS};
|
|
||||||
use crate::utils::get_hasher;
|
|
||||||
use crate::{calc_native_fn_hash, StaticVec};
|
|
||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
@ -23,6 +16,11 @@ use crate::stdlib::{
|
|||||||
vec,
|
vec,
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
|
use crate::token::is_valid_identifier;
|
||||||
|
use crate::utils::get_hasher;
|
||||||
|
use crate::{
|
||||||
|
calc_native_fn_hash, Dynamic, Engine, Module, Position, Scope, StaticVec, AST, NO_POS,
|
||||||
|
};
|
||||||
|
|
||||||
/// Level of optimization performed.
|
/// Level of optimization performed.
|
||||||
///
|
///
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use crate::def_package;
|
|
||||||
use crate::plugin::*;
|
use crate::plugin::*;
|
||||||
use crate::INT;
|
use crate::stdlib::{format, string::String};
|
||||||
|
use crate::{def_package, EvalAltResult, INT, NO_POS};
|
||||||
use crate::{result::EvalAltResult, token::NO_POS};
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
use crate::FLOAT;
|
use crate::FLOAT;
|
||||||
@ -13,8 +11,6 @@ use crate::FLOAT;
|
|||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
use num_traits::float::Float;
|
use num_traits::float::Float;
|
||||||
|
|
||||||
use crate::stdlib::{format, string::String};
|
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn make_err(msg: impl Into<String>) -> Box<EvalAltResult> {
|
pub fn make_err(msg: impl Into<String>) -> Box<EvalAltResult> {
|
||||||
EvalAltResult::ErrorArithmetic(msg.into(), NO_POS).into()
|
EvalAltResult::ErrorArithmetic(msg.into(), NO_POS).into()
|
||||||
|
@ -1,21 +1,17 @@
|
|||||||
#![cfg(not(feature = "no_index"))]
|
#![cfg(not(feature = "no_index"))]
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use crate::def_package;
|
use crate::engine::{OP_EQUALS, TYPICAL_ARRAY_SIZE};
|
||||||
use crate::dynamic::Dynamic;
|
|
||||||
use crate::engine::{Array, OP_EQUALS, TYPICAL_ARRAY_SIZE};
|
|
||||||
use crate::fn_native::{FnPtr, NativeCallContext};
|
|
||||||
use crate::plugin::*;
|
use crate::plugin::*;
|
||||||
use crate::result::EvalAltResult;
|
use crate::stdlib::{any::TypeId, boxed::Box, cmp::max, cmp::Ordering, string::ToString};
|
||||||
use crate::token::NO_POS;
|
use crate::{
|
||||||
use crate::utils::ImmutableString;
|
def_package, Array, Dynamic, EvalAltResult, FnPtr, ImmutableString, NativeCallContext, INT,
|
||||||
use crate::INT;
|
NO_POS,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
use crate::Map;
|
use crate::Map;
|
||||||
|
|
||||||
use crate::stdlib::{any::TypeId, boxed::Box, cmp::max, cmp::Ordering, string::ToString};
|
|
||||||
|
|
||||||
pub type Unit = ();
|
pub type Unit = ();
|
||||||
|
|
||||||
macro_rules! gen_array_functions {
|
macro_rules! gen_array_functions {
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
use crate::def_package;
|
|
||||||
use crate::dynamic::Dynamic;
|
|
||||||
use crate::plugin::*;
|
use crate::plugin::*;
|
||||||
use crate::result::EvalAltResult;
|
use crate::{def_package, Dynamic, EvalAltResult, ImmutableString};
|
||||||
use crate::utils::ImmutableString;
|
|
||||||
|
|
||||||
def_package!(crate:EvalPackage:"Disable 'eval'.", lib, {
|
def_package!(crate:EvalPackage:"Disable 'eval'.", lib, {
|
||||||
combine_with_exported_module!(lib, "eval", eval_override);
|
combine_with_exported_module!(lib, "eval", eval_override);
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use crate::def_package;
|
|
||||||
use crate::fn_native::FnPtr;
|
|
||||||
use crate::plugin::*;
|
use crate::plugin::*;
|
||||||
|
use crate::{def_package, FnPtr};
|
||||||
|
|
||||||
def_package!(crate:BasicFnPackage:"Basic Fn functions.", lib, {
|
def_package!(crate:BasicFnPackage:"Basic Fn functions.", lib, {
|
||||||
combine_with_exported_module!(lib, "FnPtr", fn_ptr_functions);
|
combine_with_exported_module!(lib, "FnPtr", fn_ptr_functions);
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
use crate::def_package;
|
|
||||||
use crate::dynamic::Variant;
|
use crate::dynamic::Variant;
|
||||||
use crate::result::EvalAltResult;
|
|
||||||
use crate::INT;
|
|
||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
ops::{Add, Range},
|
ops::{Add, Range},
|
||||||
};
|
};
|
||||||
|
use crate::{def_package, EvalAltResult, INT};
|
||||||
|
|
||||||
fn get_range<T: Variant + Clone>(from: T, to: T) -> Result<Range<T>, Box<EvalAltResult>> {
|
fn get_range<T: Variant + Clone>(from: T, to: T) -> Result<Range<T>, Box<EvalAltResult>> {
|
||||||
Ok(from..to)
|
Ok(from..to)
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
#![cfg(not(feature = "no_object"))]
|
#![cfg(not(feature = "no_object"))]
|
||||||
|
|
||||||
use crate::def_package;
|
use crate::engine::OP_EQUALS;
|
||||||
use crate::dynamic::Dynamic;
|
|
||||||
use crate::engine::{Map, OP_EQUALS};
|
|
||||||
use crate::plugin::*;
|
use crate::plugin::*;
|
||||||
use crate::utils::ImmutableString;
|
use crate::{def_package, Dynamic, ImmutableString, Map, INT};
|
||||||
use crate::INT;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
use crate::Array;
|
use crate::Array;
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use crate::def_package;
|
|
||||||
use crate::plugin::*;
|
use crate::plugin::*;
|
||||||
use crate::token::NO_POS;
|
use crate::{def_package, INT, NO_POS};
|
||||||
use crate::INT;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
use crate::FLOAT;
|
use crate::FLOAT;
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
//! Module containing all built-in _packages_ available to Rhai, plus facilities to define custom packages.
|
//! Module containing all built-in _packages_ available to Rhai, plus facilities to define custom packages.
|
||||||
|
|
||||||
use crate::fn_native::{CallableFunction, IteratorFn, Shared};
|
use crate::fn_native::{CallableFunction, IteratorFn};
|
||||||
use crate::module::Module;
|
|
||||||
use crate::StaticVec;
|
|
||||||
|
|
||||||
use crate::stdlib::any::TypeId;
|
use crate::stdlib::any::TypeId;
|
||||||
|
use crate::{Module, Shared, StaticVec};
|
||||||
|
|
||||||
pub(crate) mod arithmetic;
|
pub(crate) mod arithmetic;
|
||||||
mod array_basic;
|
mod array_basic;
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use crate::def_package;
|
|
||||||
use crate::engine::{FN_TO_STRING, KEYWORD_DEBUG, KEYWORD_PRINT};
|
use crate::engine::{FN_TO_STRING, KEYWORD_DEBUG, KEYWORD_PRINT};
|
||||||
use crate::fn_native::FnPtr;
|
|
||||||
use crate::plugin::*;
|
use crate::plugin::*;
|
||||||
use crate::utils::ImmutableString;
|
use crate::stdlib::{
|
||||||
use crate::INT;
|
fmt::{Debug, Display},
|
||||||
|
format,
|
||||||
|
string::ToString,
|
||||||
|
};
|
||||||
|
use crate::{def_package, FnPtr, ImmutableString, INT};
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
use crate::Array;
|
use crate::Array;
|
||||||
@ -13,12 +15,6 @@ use crate::Array;
|
|||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
use crate::Map;
|
use crate::Map;
|
||||||
|
|
||||||
use crate::stdlib::{
|
|
||||||
fmt::{Debug, Display},
|
|
||||||
format,
|
|
||||||
string::ToString,
|
|
||||||
};
|
|
||||||
|
|
||||||
type Unit = ();
|
type Unit = ();
|
||||||
|
|
||||||
macro_rules! gen_functions {
|
macro_rules! gen_functions {
|
||||||
|
@ -1,16 +1,10 @@
|
|||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use crate::def_package;
|
|
||||||
use crate::dynamic::Dynamic;
|
|
||||||
use crate::fn_native::FnPtr;
|
|
||||||
use crate::plugin::*;
|
use crate::plugin::*;
|
||||||
use crate::utils::ImmutableString;
|
|
||||||
use crate::StaticVec;
|
|
||||||
use crate::INT;
|
|
||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
any::TypeId, boxed::Box, format, mem, string::String, string::ToString, vec::Vec,
|
any::TypeId, boxed::Box, format, mem, string::String, string::ToString, vec::Vec,
|
||||||
};
|
};
|
||||||
|
use crate::{def_package, Dynamic, FnPtr, ImmutableString, StaticVec, INT};
|
||||||
|
|
||||||
macro_rules! gen_concat_functions {
|
macro_rules! gen_concat_functions {
|
||||||
($root:ident => $($arg_type:ident),+ ) => {
|
($root:ident => $($arg_type:ident),+ ) => {
|
||||||
|
@ -1,18 +1,13 @@
|
|||||||
#![cfg(not(feature = "no_std"))]
|
#![cfg(not(feature = "no_std"))]
|
||||||
|
|
||||||
use super::{arithmetic::make_err as make_arithmetic_err, math_basic::MAX_INT};
|
use super::{arithmetic::make_err as make_arithmetic_err, math_basic::MAX_INT};
|
||||||
|
|
||||||
use crate::def_package;
|
|
||||||
use crate::dynamic::Dynamic;
|
|
||||||
use crate::plugin::*;
|
use crate::plugin::*;
|
||||||
use crate::result::EvalAltResult;
|
use crate::stdlib::boxed::Box;
|
||||||
use crate::INT;
|
use crate::{def_package, Dynamic, EvalAltResult, INT};
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
use crate::FLOAT;
|
use crate::FLOAT;
|
||||||
|
|
||||||
use crate::stdlib::boxed::Box;
|
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use crate::stdlib::time::{Duration, Instant};
|
use crate::stdlib::time::{Duration, Instant};
|
||||||
|
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
//! Module containing error definitions for the parsing process.
|
//! Module containing error definitions for the parsing process.
|
||||||
|
|
||||||
use crate::result::EvalAltResult;
|
|
||||||
use crate::token::{Position, NO_POS};
|
|
||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
error::Error,
|
error::Error,
|
||||||
fmt,
|
fmt,
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
};
|
};
|
||||||
|
use crate::{EvalAltResult, Position, NO_POS};
|
||||||
|
|
||||||
/// _[INTERNALS]_ Error encountered when tokenizing the script text.
|
/// _[INTERNALS]_ Error encountered when tokenizing the script text.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
|
@ -1,24 +1,14 @@
|
|||||||
//! Main module defining the lexer and parser.
|
//! Main module defining the lexer and parser.
|
||||||
|
|
||||||
use crate::ast::{
|
use crate::ast::{
|
||||||
BinaryExpr, CustomExpr, Expr, FnCallExpr, Ident, IdentX, ReturnType, ScriptFnDef, Stmt, AST,
|
BinaryExpr, CustomExpr, Expr, FnCallExpr, Ident, IdentX, ReturnType, ScriptFnDef, Stmt,
|
||||||
};
|
};
|
||||||
use crate::dynamic::{Dynamic, Union};
|
use crate::dynamic::Union;
|
||||||
use crate::engine::{Engine, KEYWORD_THIS, MARKER_BLOCK, MARKER_EXPR, MARKER_IDENT};
|
use crate::engine::{KEYWORD_THIS, MARKER_BLOCK, MARKER_EXPR, MARKER_IDENT};
|
||||||
use crate::module::NamespaceRef;
|
use crate::module::NamespaceRef;
|
||||||
use crate::optimize::{optimize_into_ast, OptimizationLevel};
|
use crate::optimize::optimize_into_ast;
|
||||||
use crate::parse_error::{LexError, ParseError, ParseErrorType};
|
use crate::optimize::OptimizationLevel;
|
||||||
use crate::scope::{EntryType as ScopeEntryType, Scope};
|
use crate::scope::EntryType as ScopeEntryType;
|
||||||
use crate::syntax::CustomSyntax;
|
|
||||||
use crate::token::{
|
|
||||||
is_keyword_function, is_valid_identifier, Position, Token, TokenStream, NO_POS,
|
|
||||||
};
|
|
||||||
use crate::utils::{get_hasher, ImmutableString, StraightHasherBuilder};
|
|
||||||
use crate::{calc_script_fn_hash, StaticVec};
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
|
||||||
use crate::FLOAT;
|
|
||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
@ -31,6 +21,16 @@ use crate::stdlib::{
|
|||||||
vec,
|
vec,
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
|
use crate::syntax::CustomSyntax;
|
||||||
|
use crate::token::{is_keyword_function, is_valid_identifier, Token, TokenStream};
|
||||||
|
use crate::utils::{get_hasher, StraightHasherBuilder};
|
||||||
|
use crate::{
|
||||||
|
calc_script_fn_hash, Dynamic, Engine, FnAccess, ImmutableString, LexError, ParseError,
|
||||||
|
ParseErrorType, Position, Scope, StaticVec, AST, NO_POS,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
use crate::FLOAT;
|
||||||
|
|
||||||
type PERR = ParseErrorType;
|
type PERR = ParseErrorType;
|
||||||
|
|
||||||
@ -148,10 +148,10 @@ impl<'e> ParseState<'e> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get an interned string, creating one if it is not yet interned.
|
/// Get an interned string, creating one if it is not yet interned.
|
||||||
pub fn get_interned_string<S>(&mut self, text: S) -> ImmutableString
|
pub fn get_interned_string(
|
||||||
where
|
&mut self,
|
||||||
S: AsRef<str> + Into<ImmutableString>,
|
text: impl AsRef<str> + Into<ImmutableString>,
|
||||||
{
|
) -> ImmutableString {
|
||||||
#[allow(clippy::map_entry)]
|
#[allow(clippy::map_entry)]
|
||||||
if !self.strings.contains_key(text.as_ref()) {
|
if !self.strings.contains_key(text.as_ref()) {
|
||||||
let value: ImmutableString = text.into();
|
let value: ImmutableString = text.into();
|
||||||
@ -1418,7 +1418,9 @@ fn make_dot_expr(
|
|||||||
}
|
}
|
||||||
// lhs.Fn() or lhs.eval()
|
// lhs.Fn() or lhs.eval()
|
||||||
(_, Expr::FnCall(x, pos))
|
(_, Expr::FnCall(x, pos))
|
||||||
if x.args.len() == 0 && [crate::engine::KEYWORD_FN_PTR, crate::engine::KEYWORD_EVAL].contains(&x.name.as_ref()) =>
|
if x.args.len() == 0
|
||||||
|
&& [crate::engine::KEYWORD_FN_PTR, crate::engine::KEYWORD_EVAL]
|
||||||
|
.contains(&x.name.as_ref()) =>
|
||||||
{
|
{
|
||||||
return Err(PERR::BadInput(LexError::ImproperSymbol(format!(
|
return Err(PERR::BadInput(LexError::ImproperSymbol(format!(
|
||||||
"'{}' should not be called in method style. Try {}(...);",
|
"'{}' should not be called in method style. Try {}(...);",
|
||||||
@ -2369,9 +2371,9 @@ fn parse_stmt(
|
|||||||
Token::Fn | Token::Private => {
|
Token::Fn | Token::Private => {
|
||||||
let access = if matches!(token, Token::Private) {
|
let access = if matches!(token, Token::Private) {
|
||||||
eat_token(input, Token::Private);
|
eat_token(input, Token::Private);
|
||||||
crate::FnAccess::Private
|
FnAccess::Private
|
||||||
} else {
|
} else {
|
||||||
crate::FnAccess::Public
|
FnAccess::Public
|
||||||
};
|
};
|
||||||
|
|
||||||
match input.next().unwrap() {
|
match input.next().unwrap() {
|
||||||
@ -2552,7 +2554,7 @@ fn parse_fn(
|
|||||||
input: &mut TokenStream,
|
input: &mut TokenStream,
|
||||||
state: &mut ParseState,
|
state: &mut ParseState,
|
||||||
lib: &mut FunctionsLib,
|
lib: &mut FunctionsLib,
|
||||||
access: crate::FnAccess,
|
access: FnAccess,
|
||||||
mut settings: ParseSettings,
|
mut settings: ParseSettings,
|
||||||
) -> Result<ScriptFnDef, ParseError> {
|
) -> Result<ScriptFnDef, ParseError> {
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
@ -2664,11 +2666,13 @@ fn make_curry_from_externals(fn_expr: Expr, externals: StaticVec<IdentX>, pos: P
|
|||||||
args.push(Expr::Variable(Box::new((None, None, 0, x.clone().into()))));
|
args.push(Expr::Variable(Box::new((None, None, 0, x.clone().into()))));
|
||||||
});
|
});
|
||||||
|
|
||||||
let hash = calc_script_fn_hash(empty(), crate::engine::KEYWORD_FN_PTR_CURRY, num_externals + 1);
|
let curry_func = crate::engine::KEYWORD_FN_PTR_CURRY;
|
||||||
|
|
||||||
|
let hash = calc_script_fn_hash(empty(), curry_func, num_externals + 1);
|
||||||
|
|
||||||
let expr = Expr::FnCall(
|
let expr = Expr::FnCall(
|
||||||
Box::new(FnCallExpr {
|
Box::new(FnCallExpr {
|
||||||
name: crate::engine::KEYWORD_FN_PTR_CURRY.into(),
|
name: curry_func.into(),
|
||||||
hash,
|
hash,
|
||||||
args,
|
args,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -2785,7 +2789,7 @@ fn parse_anon_fn(
|
|||||||
// Define the function
|
// Define the function
|
||||||
let script = ScriptFnDef {
|
let script = ScriptFnDef {
|
||||||
name: fn_name.clone(),
|
name: fn_name.clone(),
|
||||||
access: crate::FnAccess::Public,
|
access: FnAccess::Public,
|
||||||
params,
|
params,
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
externals: Default::default(),
|
externals: Default::default(),
|
||||||
|
@ -1,15 +1,11 @@
|
|||||||
//! Module defining macros for developing _plugins_.
|
//! Module defining macros for developing _plugins_.
|
||||||
|
|
||||||
pub use crate::ast::FnAccess;
|
pub use crate::fn_native::{CallableFunction, FnCallArgs};
|
||||||
pub use crate::dynamic::Dynamic;
|
|
||||||
pub use crate::engine::Engine;
|
|
||||||
pub use crate::fn_native::{CallableFunction, FnCallArgs, NativeCallContext};
|
|
||||||
pub use crate::fn_register::{RegisterFn, RegisterResultFn};
|
|
||||||
pub use crate::module::Module;
|
|
||||||
pub use crate::result::EvalAltResult;
|
|
||||||
pub use crate::utils::ImmutableString;
|
|
||||||
|
|
||||||
pub use crate::stdlib::{any::TypeId, boxed::Box, format, mem, string::ToString, vec as new_vec};
|
pub use crate::stdlib::{any::TypeId, boxed::Box, format, mem, string::ToString, vec as new_vec};
|
||||||
|
pub use crate::{
|
||||||
|
Dynamic, Engine, EvalAltResult, FnAccess, FnNamespace, ImmutableString, Module,
|
||||||
|
NativeCallContext, RegisterFn, RegisterResultFn,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(not(features = "no_module"))]
|
#[cfg(not(features = "no_module"))]
|
||||||
pub use rhai_codegen::*;
|
pub use rhai_codegen::*;
|
||||||
|
@ -1,17 +1,12 @@
|
|||||||
//! Module containing error definitions for the evaluation process.
|
//! Module containing error definitions for the evaluation process.
|
||||||
|
|
||||||
use crate::dynamic::Dynamic;
|
|
||||||
use crate::parse_error::ParseErrorType;
|
|
||||||
use crate::token::{Position, NO_POS};
|
|
||||||
use crate::utils::ImmutableString;
|
|
||||||
use crate::INT;
|
|
||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
error::Error,
|
error::Error,
|
||||||
fmt,
|
fmt,
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
};
|
};
|
||||||
|
use crate::{Dynamic, ImmutableString, ParseErrorType, Position, INT, NO_POS};
|
||||||
|
|
||||||
/// Evaluation result.
|
/// Evaluation result.
|
||||||
///
|
///
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
//! Module that defines the `Scope` type representing a function call-stack scope.
|
//! Module that defines the `Scope` type representing a function call-stack scope.
|
||||||
|
|
||||||
use crate::dynamic::{Dynamic, Variant};
|
use crate::dynamic::Variant;
|
||||||
use crate::StaticVec;
|
|
||||||
|
|
||||||
use crate::stdlib::{borrow::Cow, boxed::Box, iter, string::String, vec::Vec};
|
use crate::stdlib::{borrow::Cow, boxed::Box, iter, string::String, vec::Vec};
|
||||||
|
use crate::{Dynamic, StaticVec};
|
||||||
|
|
||||||
/// Type of an entry in the Scope.
|
/// Type of an entry in the Scope.
|
||||||
#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone)]
|
#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone)]
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
//! Implement deserialization support of `Dynamic` for [`serde`](https://crates.io/crates/serde).
|
//! Implement deserialization support of `Dynamic` for [`serde`](https://crates.io/crates/serde).
|
||||||
|
|
||||||
use super::str::ImmutableStringDeserializer;
|
use super::str::ImmutableStringDeserializer;
|
||||||
use crate::dynamic::{Dynamic, Union};
|
use crate::dynamic::Union;
|
||||||
use crate::parse_error::{LexError, ParseErrorType};
|
use crate::stdlib::{any::type_name, boxed::Box, fmt, string::ToString};
|
||||||
use crate::result::EvalAltResult;
|
use crate::{Dynamic, EvalAltResult, ImmutableString, LexError, ParseErrorType, NO_POS};
|
||||||
use crate::token::NO_POS;
|
|
||||||
use crate::utils::ImmutableString;
|
|
||||||
|
|
||||||
use serde::de::{
|
use serde::de::{
|
||||||
DeserializeSeed, Deserializer, Error, IntoDeserializer, MapAccess, SeqAccess, Visitor,
|
DeserializeSeed, Deserializer, Error, IntoDeserializer, MapAccess, SeqAccess, Visitor,
|
||||||
};
|
};
|
||||||
@ -18,8 +15,6 @@ use crate::Array;
|
|||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
use crate::Map;
|
use crate::Map;
|
||||||
|
|
||||||
use crate::stdlib::{any::type_name, boxed::Box, fmt, string::ToString};
|
|
||||||
|
|
||||||
/// Deserializer for `Dynamic` which is kept as a reference.
|
/// Deserializer for `Dynamic` which is kept as a reference.
|
||||||
///
|
///
|
||||||
/// The reference is necessary because the deserialized type may hold references
|
/// The reference is necessary because the deserialized type may hold references
|
||||||
|
@ -1,22 +1,18 @@
|
|||||||
//! Implement serialization support of `Dynamic` for [`serde`](https://crates.io/crates/serde).
|
//! Implement serialization support of `Dynamic` for [`serde`](https://crates.io/crates/serde).
|
||||||
|
|
||||||
use crate::dynamic::Dynamic;
|
use crate::stdlib::{boxed::Box, fmt, string::ToString};
|
||||||
use crate::result::EvalAltResult;
|
use crate::{Dynamic, EvalAltResult, NO_POS};
|
||||||
use crate::token::NO_POS;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
|
||||||
use crate::Array;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
|
||||||
use crate::Map;
|
|
||||||
|
|
||||||
use serde::ser::{
|
use serde::ser::{
|
||||||
Error, SerializeMap, SerializeSeq, SerializeStruct, SerializeTuple, SerializeTupleStruct,
|
Error, SerializeMap, SerializeSeq, SerializeStruct, SerializeTuple, SerializeTupleStruct,
|
||||||
Serializer,
|
Serializer,
|
||||||
};
|
};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::stdlib::{boxed::Box, fmt, string::ToString};
|
#[cfg(not(feature = "no_index"))]
|
||||||
|
use crate::Array;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
use crate::Map;
|
||||||
|
|
||||||
/// Serializer for `Dynamic` which is kept as a reference.
|
/// Serializer for `Dynamic` which is kept as a reference.
|
||||||
pub struct DynamicSerializer {
|
pub struct DynamicSerializer {
|
||||||
|
@ -1,12 +1,8 @@
|
|||||||
//! Implement deserialization support of `ImmutableString` for [`serde`](https://crates.io/crates/serde).
|
//! Implement deserialization support of `ImmutableString` for [`serde`](https://crates.io/crates/serde).
|
||||||
|
|
||||||
use crate::result::EvalAltResult;
|
|
||||||
use crate::token::NO_POS;
|
|
||||||
use crate::utils::ImmutableString;
|
|
||||||
|
|
||||||
use serde::de::{Deserializer, Visitor};
|
|
||||||
|
|
||||||
use crate::stdlib::{any::type_name, boxed::Box};
|
use crate::stdlib::{any::type_name, boxed::Box};
|
||||||
|
use crate::{EvalAltResult, ImmutableString, NO_POS};
|
||||||
|
use serde::de::{Deserializer, Visitor};
|
||||||
|
|
||||||
/// Deserializer for `ImmutableString`.
|
/// Deserializer for `ImmutableString`.
|
||||||
pub struct ImmutableStringDeserializer<'a> {
|
pub struct ImmutableStringDeserializer<'a> {
|
||||||
|
@ -1,20 +1,18 @@
|
|||||||
//! Module implementing custom syntax for `Engine`.
|
//! Module implementing custom syntax for `Engine`.
|
||||||
|
|
||||||
use crate::ast::Expr;
|
use crate::ast::Expr;
|
||||||
use crate::dynamic::Dynamic;
|
use crate::engine::{EvalContext, MARKER_BLOCK, MARKER_EXPR, MARKER_IDENT};
|
||||||
use crate::engine::{Engine, EvalContext, MARKER_BLOCK, MARKER_EXPR, MARKER_IDENT};
|
use crate::fn_native::SendSync;
|
||||||
use crate::fn_native::{SendSync, Shared};
|
|
||||||
use crate::parse_error::{LexError, ParseError};
|
|
||||||
use crate::result::EvalAltResult;
|
|
||||||
use crate::token::{is_valid_identifier, Position, Token, NO_POS};
|
|
||||||
use crate::utils::ImmutableString;
|
|
||||||
use crate::StaticVec;
|
|
||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
format,
|
format,
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
};
|
};
|
||||||
|
use crate::token::{is_valid_identifier, Token};
|
||||||
|
use crate::{
|
||||||
|
Dynamic, Engine, EvalAltResult, ImmutableString, LexError, ParseError, Position, Shared,
|
||||||
|
StaticVec, NO_POS,
|
||||||
|
};
|
||||||
|
|
||||||
/// A general expression evaluation trait object.
|
/// A general expression evaluation trait object.
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
|
14
src/token.rs
14
src/token.rs
@ -1,17 +1,9 @@
|
|||||||
//! Main module defining the lexer and parser.
|
//! Main module defining the lexer and parser.
|
||||||
|
|
||||||
use crate::engine::{
|
use crate::engine::{
|
||||||
Engine, KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_FN_PTR, KEYWORD_FN_PTR_CALL, KEYWORD_FN_PTR_CURRY,
|
KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_FN_PTR, KEYWORD_FN_PTR_CALL, KEYWORD_FN_PTR_CURRY,
|
||||||
KEYWORD_IS_DEF_FN, KEYWORD_IS_DEF_VAR, KEYWORD_PRINT, KEYWORD_THIS, KEYWORD_TYPE_OF,
|
KEYWORD_IS_DEF_FN, KEYWORD_IS_DEF_VAR, KEYWORD_PRINT, KEYWORD_THIS, KEYWORD_TYPE_OF,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::parse_error::LexError;
|
|
||||||
use crate::StaticVec;
|
|
||||||
use crate::INT;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
|
||||||
use crate::FLOAT;
|
|
||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
@ -20,6 +12,10 @@ use crate::stdlib::{
|
|||||||
str::{Chars, FromStr},
|
str::{Chars, FromStr},
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
};
|
};
|
||||||
|
use crate::{Engine, LexError, StaticVec, INT};
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
use crate::FLOAT;
|
||||||
|
|
||||||
type LERR = LexError;
|
type LERR = LexError;
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
//! A helper module containing unsafe utility functions.
|
//! A helper module containing unsafe utility functions.
|
||||||
|
|
||||||
use crate::dynamic::Variant;
|
use crate::dynamic::Variant;
|
||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
any::{Any, TypeId},
|
any::{Any, TypeId},
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
|
20
src/utils.rs
20
src/utils.rs
@ -1,7 +1,6 @@
|
|||||||
//! Module containing various utility types and functions.
|
//! Module containing various utility types and functions.
|
||||||
|
|
||||||
use crate::fn_native::{shared_make_mut, shared_take, Shared};
|
use crate::fn_native::{shared_make_mut, shared_take};
|
||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
any::TypeId,
|
any::TypeId,
|
||||||
borrow::Borrow,
|
borrow::Borrow,
|
||||||
@ -14,12 +13,7 @@ use crate::stdlib::{
|
|||||||
str::FromStr,
|
str::FromStr,
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
};
|
};
|
||||||
|
use crate::Shared;
|
||||||
#[cfg(not(feature = "no_std"))]
|
|
||||||
use crate::stdlib::collections::hash_map::DefaultHasher;
|
|
||||||
|
|
||||||
#[cfg(feature = "no_std")]
|
|
||||||
use ahash::AHasher;
|
|
||||||
|
|
||||||
/// A hasher that only takes one single `u64` and returns it as a hash key.
|
/// A hasher that only takes one single `u64` and returns it as a hash key.
|
||||||
///
|
///
|
||||||
@ -95,9 +89,9 @@ pub fn calc_script_fn_hash<'a>(
|
|||||||
/// Create an instance of the default hasher.
|
/// Create an instance of the default hasher.
|
||||||
pub fn get_hasher() -> impl Hasher {
|
pub fn get_hasher() -> impl Hasher {
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
let s: AHasher = Default::default();
|
let s: ahash::AHasher = Default::default();
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
let s = DefaultHasher::new();
|
let s = crate::stdlib::collections::hash_map::DefaultHasher::new();
|
||||||
|
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
@ -111,15 +105,17 @@ pub fn get_hasher() -> impl Hasher {
|
|||||||
///
|
///
|
||||||
/// The first module name is skipped. Hashing starts from the _second_ module in the chain.
|
/// The first module name is skipped. Hashing starts from the _second_ module in the chain.
|
||||||
fn calc_fn_hash<'a>(
|
fn calc_fn_hash<'a>(
|
||||||
modules: impl Iterator<Item = &'a str>,
|
mut modules: impl Iterator<Item = &'a str>,
|
||||||
fn_name: &str,
|
fn_name: &str,
|
||||||
num: Option<usize>,
|
num: Option<usize>,
|
||||||
params: impl Iterator<Item = TypeId>,
|
params: impl Iterator<Item = TypeId>,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
let s = &mut get_hasher();
|
let s = &mut get_hasher();
|
||||||
|
|
||||||
|
// Hash a boolean indicating whether the hash is namespace-qualified.
|
||||||
|
modules.next().is_some().hash(s);
|
||||||
// We always skip the first module
|
// We always skip the first module
|
||||||
modules.skip(1).for_each(|m| m.hash(s));
|
modules.for_each(|m| m.hash(s));
|
||||||
s.write(fn_name.as_bytes());
|
s.write(fn_name.as_bytes());
|
||||||
if let Some(num) = num {
|
if let Some(num) = num {
|
||||||
s.write_usize(num);
|
s.write_usize(num);
|
||||||
|
@ -267,7 +267,7 @@ fn test_closures_external() -> Result<(), Box<EvalAltResult>> {
|
|||||||
let fn_ptr = engine.eval_ast::<FnPtr>(&ast)?;
|
let fn_ptr = engine.eval_ast::<FnPtr>(&ast)?;
|
||||||
|
|
||||||
// Get rid of the script, retaining only functions
|
// Get rid of the script, retaining only functions
|
||||||
ast.retain_functions(|_, _, _| true);
|
ast.retain_functions(|_, _, _, _| true);
|
||||||
|
|
||||||
// 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((&engine, &[ast.as_ref()]).into(), None, [x.into()]);
|
let f = move |x: INT| fn_ptr.call_dynamic((&engine, &[ast.as_ref()]).into(), None, [x.into()]);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#![cfg(not(feature = "no_module"))]
|
#![cfg(not(feature = "no_module"))]
|
||||||
use rhai::{
|
use rhai::{
|
||||||
module_resolvers::StaticModuleResolver, Dynamic, Engine, EvalAltResult, ImmutableString,
|
module_resolvers::StaticModuleResolver, Dynamic, Engine, EvalAltResult, FnNamespace,
|
||||||
Module, ParseError, ParseErrorType, Scope, INT,
|
ImmutableString, Module, ParseError, ParseErrorType, Scope, INT,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -23,7 +23,8 @@ fn test_module_sub_module() -> Result<(), Box<EvalAltResult>> {
|
|||||||
sub_module2.set_var("answer", 41 as INT);
|
sub_module2.set_var("answer", 41 as INT);
|
||||||
|
|
||||||
let hash_inc = sub_module2.set_fn_1("inc", |x: INT| Ok(x + 1));
|
let hash_inc = sub_module2.set_fn_1("inc", |x: INT| Ok(x + 1));
|
||||||
sub_module2.set_fn_1_mut("super_inc", |x: &mut INT| Ok(*x + 1));
|
let hash_super_inc = sub_module2.set_fn_1_mut("super_inc", |x: &mut INT| Ok(*x + 1));
|
||||||
|
sub_module2.set_fn_namespace(hash_super_inc, FnNamespace::Global);
|
||||||
|
|
||||||
sub_module.set_sub_module("universe", sub_module2);
|
sub_module.set_sub_module("universe", sub_module2);
|
||||||
module.set_sub_module("life", sub_module);
|
module.set_sub_module("life", sub_module);
|
||||||
@ -56,16 +57,10 @@ fn test_module_sub_module() -> Result<(), Box<EvalAltResult>> {
|
|||||||
assert!(engine
|
assert!(engine
|
||||||
.eval::<INT>("inc(question::life::universe::answer)")
|
.eval::<INT>("inc(question::life::universe::answer)")
|
||||||
.is_err());
|
.is_err());
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
engine.eval::<INT>("super_inc(question::life::universe::answer)")?,
|
engine.eval::<INT>("super_inc(question::life::universe::answer)")?,
|
||||||
42
|
42
|
||||||
);
|
);
|
||||||
#[cfg(feature = "no_object")]
|
|
||||||
assert!(engine
|
|
||||||
.eval::<INT>("super_inc(question::life::universe::answer)")
|
|
||||||
.is_err());
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#![cfg(not(any(feature = "no_index", feature = "no_module")))]
|
#![cfg(not(any(feature = "no_index", feature = "no_module")))]
|
||||||
|
|
||||||
use rhai::module_resolvers::StaticModuleResolver;
|
|
||||||
use rhai::plugin::*;
|
use rhai::plugin::*;
|
||||||
use rhai::{Engine, EvalAltResult, INT};
|
use rhai::{Engine, EvalAltResult, INT};
|
||||||
|
|
||||||
@ -96,14 +95,9 @@ fn test_plugins_package() -> Result<(), Box<EvalAltResult>> {
|
|||||||
"6 kitties"
|
"6 kitties"
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut resolver = StaticModuleResolver::new();
|
engine.register_module("test", exported_module!(test::special_array_package));
|
||||||
resolver.insert("test", exported_module!(test::special_array_package));
|
|
||||||
|
|
||||||
engine.set_module_resolver(Some(resolver));
|
assert_eq!(engine.eval::<INT>("test::MYSTIC_NUMBER")?, 42);
|
||||||
assert_eq!(
|
|
||||||
engine.eval::<INT>(r#"import "test" as test; test::MYSTIC_NUMBER"#)?,
|
|
||||||
42
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user