Remove no_module gates to prepare for plugins.
This commit is contained in:
parent
c6e5f672c9
commit
cec6748ac6
@ -105,7 +105,7 @@ Optional features
|
|||||||
| `no_index` | Disable [arrays] and indexing features. |
|
| `no_index` | Disable [arrays] and indexing features. |
|
||||||
| `no_object` | Disable support for custom types and [object maps]. |
|
| `no_object` | Disable support for custom types and [object maps]. |
|
||||||
| `no_function` | Disable script-defined functions. |
|
| `no_function` | Disable script-defined functions. |
|
||||||
| `no_module` | Disable loading modules. |
|
| `no_module` | Disable loading external modules. |
|
||||||
| `no_std` | Build for `no-std`. Notice that additional dependencies will be pulled in to replace `std` features. |
|
| `no_std` | Build for `no-std`. Notice that additional dependencies will be pulled in to replace `std` features. |
|
||||||
|
|
||||||
By default, Rhai includes all the standard functionalities in a small, tight package.
|
By default, Rhai includes all the standard functionalities in a small, tight package.
|
||||||
|
14
src/any.rs
14
src/any.rs
@ -1,11 +1,9 @@
|
|||||||
//! 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::module::Module;
|
||||||
use crate::parser::{ImmutableString, INT};
|
use crate::parser::{ImmutableString, INT};
|
||||||
use crate::r#unsafe::{unsafe_cast_box, unsafe_try_cast};
|
use crate::r#unsafe::{unsafe_cast_box, unsafe_try_cast};
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
use crate::module::Module;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
use crate::parser::FLOAT;
|
use crate::parser::FLOAT;
|
||||||
|
|
||||||
@ -160,7 +158,6 @@ pub enum Union {
|
|||||||
Array(Box<Array>),
|
Array(Box<Array>),
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Map(Box<Map>),
|
Map(Box<Map>),
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
Module(Box<Module>),
|
Module(Box<Module>),
|
||||||
Variant(Box<Box<dyn Variant>>),
|
Variant(Box<Box<dyn Variant>>),
|
||||||
}
|
}
|
||||||
@ -198,7 +195,6 @@ impl Dynamic {
|
|||||||
Union::Array(_) => TypeId::of::<Array>(),
|
Union::Array(_) => TypeId::of::<Array>(),
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Union::Map(_) => TypeId::of::<Map>(),
|
Union::Map(_) => TypeId::of::<Map>(),
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
Union::Module(_) => TypeId::of::<Module>(),
|
Union::Module(_) => TypeId::of::<Module>(),
|
||||||
Union::Variant(value) => (***value).type_id(),
|
Union::Variant(value) => (***value).type_id(),
|
||||||
}
|
}
|
||||||
@ -218,7 +214,6 @@ impl Dynamic {
|
|||||||
Union::Array(_) => "array",
|
Union::Array(_) => "array",
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Union::Map(_) => "map",
|
Union::Map(_) => "map",
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
Union::Module(_) => "sub-scope",
|
Union::Module(_) => "sub-scope",
|
||||||
|
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
@ -242,7 +237,6 @@ impl fmt::Display for Dynamic {
|
|||||||
Union::Array(value) => write!(f, "{:?}", value),
|
Union::Array(value) => write!(f, "{:?}", value),
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Union::Map(value) => write!(f, "#{:?}", value),
|
Union::Map(value) => write!(f, "#{:?}", value),
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
Union::Module(value) => write!(f, "{:?}", value),
|
Union::Module(value) => write!(f, "{:?}", value),
|
||||||
|
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
@ -266,7 +260,6 @@ impl fmt::Debug for Dynamic {
|
|||||||
Union::Array(value) => write!(f, "{:?}", value),
|
Union::Array(value) => write!(f, "{:?}", value),
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Union::Map(value) => write!(f, "#{:?}", value),
|
Union::Map(value) => write!(f, "#{:?}", value),
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
Union::Module(value) => write!(f, "{:?}", value),
|
Union::Module(value) => write!(f, "{:?}", value),
|
||||||
|
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
@ -290,7 +283,6 @@ impl Clone for Dynamic {
|
|||||||
Union::Array(ref value) => Self(Union::Array(value.clone())),
|
Union::Array(ref value) => Self(Union::Array(value.clone())),
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Union::Map(ref value) => Self(Union::Map(value.clone())),
|
Union::Map(ref value) => Self(Union::Map(value.clone())),
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
Union::Module(ref value) => Self(Union::Module(value.clone())),
|
Union::Module(ref value) => Self(Union::Module(value.clone())),
|
||||||
Union::Variant(ref value) => (***value).clone_into_dynamic(),
|
Union::Variant(ref value) => (***value).clone_into_dynamic(),
|
||||||
}
|
}
|
||||||
@ -426,7 +418,6 @@ impl Dynamic {
|
|||||||
Union::Array(value) => unsafe_cast_box::<_, T>(value).ok().map(|v| *v),
|
Union::Array(value) => unsafe_cast_box::<_, T>(value).ok().map(|v| *v),
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Union::Map(value) => unsafe_cast_box::<_, T>(value).ok().map(|v| *v),
|
Union::Map(value) => unsafe_cast_box::<_, T>(value).ok().map(|v| *v),
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
Union::Module(value) => unsafe_cast_box::<_, T>(value).ok().map(|v| *v),
|
Union::Module(value) => unsafe_cast_box::<_, T>(value).ok().map(|v| *v),
|
||||||
Union::Variant(value) => (*value).as_box_any().downcast().map(|x| *x).ok(),
|
Union::Variant(value) => (*value).as_box_any().downcast().map(|x| *x).ok(),
|
||||||
}
|
}
|
||||||
@ -470,7 +461,6 @@ impl Dynamic {
|
|||||||
Union::Array(value) => *unsafe_cast_box::<_, T>(value).unwrap(),
|
Union::Array(value) => *unsafe_cast_box::<_, T>(value).unwrap(),
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Union::Map(value) => *unsafe_cast_box::<_, T>(value).unwrap(),
|
Union::Map(value) => *unsafe_cast_box::<_, T>(value).unwrap(),
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
Union::Module(value) => *unsafe_cast_box::<_, T>(value).unwrap(),
|
Union::Module(value) => *unsafe_cast_box::<_, T>(value).unwrap(),
|
||||||
Union::Variant(value) => (*value).as_box_any().downcast().map(|x| *x).unwrap(),
|
Union::Variant(value) => (*value).as_box_any().downcast().map(|x| *x).unwrap(),
|
||||||
}
|
}
|
||||||
@ -498,7 +488,6 @@ impl Dynamic {
|
|||||||
Union::Array(value) => (value.as_ref() as &dyn Any).downcast_ref::<T>(),
|
Union::Array(value) => (value.as_ref() as &dyn Any).downcast_ref::<T>(),
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Union::Map(value) => (value.as_ref() as &dyn Any).downcast_ref::<T>(),
|
Union::Map(value) => (value.as_ref() as &dyn Any).downcast_ref::<T>(),
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
Union::Module(value) => (value.as_ref() as &dyn Any).downcast_ref::<T>(),
|
Union::Module(value) => (value.as_ref() as &dyn Any).downcast_ref::<T>(),
|
||||||
Union::Variant(value) => value.as_ref().as_ref().as_any().downcast_ref::<T>(),
|
Union::Variant(value) => value.as_ref().as_ref().as_any().downcast_ref::<T>(),
|
||||||
}
|
}
|
||||||
@ -524,7 +513,6 @@ impl Dynamic {
|
|||||||
Union::Array(value) => (value.as_mut() as &mut dyn Any).downcast_mut::<T>(),
|
Union::Array(value) => (value.as_mut() as &mut dyn Any).downcast_mut::<T>(),
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Union::Map(value) => (value.as_mut() as &mut dyn Any).downcast_mut::<T>(),
|
Union::Map(value) => (value.as_mut() as &mut dyn Any).downcast_mut::<T>(),
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
Union::Module(value) => (value.as_mut() as &mut dyn Any).downcast_mut::<T>(),
|
Union::Module(value) => (value.as_mut() as &mut dyn Any).downcast_mut::<T>(),
|
||||||
Union::Variant(value) => value.as_mut().as_mut_any().downcast_mut::<T>(),
|
Union::Variant(value) => value.as_mut().as_mut_any().downcast_mut::<T>(),
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ use crate::any::{Dynamic, Union};
|
|||||||
use crate::calc_fn_hash;
|
use crate::calc_fn_hash;
|
||||||
use crate::error::ParseErrorType;
|
use crate::error::ParseErrorType;
|
||||||
use crate::fn_native::{CallableFunction, FnCallArgs, Shared};
|
use crate::fn_native::{CallableFunction, FnCallArgs, Shared};
|
||||||
use crate::module::Module;
|
use crate::module::{resolvers, Module, ModuleResolver};
|
||||||
use crate::optimize::OptimizationLevel;
|
use crate::optimize::OptimizationLevel;
|
||||||
use crate::packages::{CorePackage, Package, PackageLibrary, PackagesCollection, StandardPackage};
|
use crate::packages::{CorePackage, Package, PackageLibrary, PackagesCollection, StandardPackage};
|
||||||
use crate::parser::{Expr, FnAccess, FnDef, ImmutableString, ReturnType, Stmt, AST, INT};
|
use crate::parser::{Expr, FnAccess, FnDef, ImmutableString, ReturnType, Stmt, AST, INT};
|
||||||
@ -17,9 +17,6 @@ use crate::utils::{StaticVec, StraightHasherBuilder};
|
|||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
use crate::parser::FLOAT;
|
use crate::parser::FLOAT;
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
use crate::module::{resolvers, ModuleResolver};
|
|
||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
any::TypeId,
|
any::TypeId,
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
@ -297,7 +294,6 @@ pub struct Engine {
|
|||||||
pub(crate) packages: PackagesCollection,
|
pub(crate) packages: PackagesCollection,
|
||||||
|
|
||||||
/// A module resolution service.
|
/// A module resolution service.
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
pub(crate) module_resolver: Option<Box<dyn ModuleResolver>>,
|
pub(crate) module_resolver: Option<Box<dyn ModuleResolver>>,
|
||||||
|
|
||||||
/// A hashmap mapping type names to pretty-print names.
|
/// A hashmap mapping type names to pretty-print names.
|
||||||
@ -350,8 +346,7 @@ impl Default for Engine {
|
|||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
module_resolver: Some(Box::new(resolvers::FileModuleResolver::new())),
|
module_resolver: Some(Box::new(resolvers::FileModuleResolver::new())),
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(any(feature = "no_module", feature = "no_std"))]
|
||||||
#[cfg(feature = "no_std")]
|
|
||||||
module_resolver: None,
|
module_resolver: None,
|
||||||
|
|
||||||
type_names: HashMap::new(),
|
type_names: HashMap::new(),
|
||||||
@ -442,31 +437,28 @@ fn search_scope<'s, 'a>(
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
if let Some(modules) = modules.as_ref() {
|
||||||
{
|
let module = if let Some(index) = modules.index() {
|
||||||
if let Some(modules) = modules.as_ref() {
|
scope
|
||||||
let module = if let Some(index) = modules.index() {
|
.get_mut(scope.len() - index.get())
|
||||||
scope
|
.0
|
||||||
.get_mut(scope.len() - index.get())
|
.downcast_mut::<Module>()
|
||||||
.0
|
.unwrap()
|
||||||
.downcast_mut::<Module>()
|
} else {
|
||||||
.unwrap()
|
let (id, root_pos) = modules.get(0);
|
||||||
} else {
|
|
||||||
let (id, root_pos) = modules.get(0);
|
|
||||||
|
|
||||||
scope.find_module(id).ok_or_else(|| {
|
scope
|
||||||
Box::new(EvalAltResult::ErrorModuleNotFound(id.into(), *root_pos))
|
.find_module_internal(id)
|
||||||
})?
|
.ok_or_else(|| Box::new(EvalAltResult::ErrorModuleNotFound(id.into(), *root_pos)))?
|
||||||
};
|
};
|
||||||
|
|
||||||
return Ok((
|
return Ok((
|
||||||
module.get_qualified_var_mut(name, *hash_var, *pos)?,
|
module.get_qualified_var_mut(name, *hash_var, *pos)?,
|
||||||
name,
|
name,
|
||||||
// Module variables are constant
|
// Module variables are constant
|
||||||
ScopeEntryType::Constant,
|
ScopeEntryType::Constant,
|
||||||
*pos,
|
*pos,
|
||||||
));
|
));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let index = if state.always_search { None } else { *index };
|
let index = if state.always_search { None } else { *index };
|
||||||
@ -496,8 +488,6 @@ impl Engine {
|
|||||||
Self {
|
Self {
|
||||||
packages: Default::default(),
|
packages: Default::default(),
|
||||||
global_module: Default::default(),
|
global_module: Default::default(),
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
module_resolver: None,
|
module_resolver: None,
|
||||||
|
|
||||||
type_names: HashMap::new(),
|
type_names: HashMap::new(),
|
||||||
@ -1609,7 +1599,6 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Module-qualified function call
|
// Module-qualified function call
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
Expr::FnCall(x) if x.1.is_some() => {
|
Expr::FnCall(x) if x.1.is_some() => {
|
||||||
let ((name, _, pos), modules, hash_fn_def, args_expr, def_val) = x.as_ref();
|
let ((name, _, pos), modules, hash_fn_def, args_expr, def_val) = x.as_ref();
|
||||||
let modules = modules.as_ref().unwrap();
|
let modules = modules.as_ref().unwrap();
|
||||||
@ -1630,7 +1619,7 @@ impl Engine {
|
|||||||
.downcast_mut::<Module>()
|
.downcast_mut::<Module>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
} else {
|
} else {
|
||||||
scope.find_module(id).ok_or_else(|| {
|
scope.find_module_internal(id).ok_or_else(|| {
|
||||||
Box::new(EvalAltResult::ErrorModuleNotFound(id.into(), *root_pos))
|
Box::new(EvalAltResult::ErrorModuleNotFound(id.into(), *root_pos))
|
||||||
})?
|
})?
|
||||||
};
|
};
|
||||||
@ -1919,21 +1908,18 @@ impl Engine {
|
|||||||
|
|
||||||
// Import statement
|
// Import statement
|
||||||
Stmt::Import(x) => {
|
Stmt::Import(x) => {
|
||||||
#[cfg(feature = "no_module")]
|
let (expr, (name, pos)) = x.as_ref();
|
||||||
unreachable!();
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
// Guard against too many modules
|
||||||
|
if state.modules >= self.max_modules {
|
||||||
|
return Err(Box::new(EvalAltResult::ErrorTooManyModules(*pos)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(path) = self
|
||||||
|
.eval_expr(scope, state, lib, &expr, level)?
|
||||||
|
.try_cast::<ImmutableString>()
|
||||||
{
|
{
|
||||||
let (expr, (name, pos)) = x.as_ref();
|
#[cfg(not(feature = "no_module"))]
|
||||||
|
|
||||||
// Guard against too many modules
|
|
||||||
if state.modules >= self.max_modules {
|
|
||||||
return Err(Box::new(EvalAltResult::ErrorTooManyModules(*pos)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(path) = self
|
|
||||||
.eval_expr(scope, state, lib, &expr, level)?
|
|
||||||
.try_cast::<ImmutableString>()
|
|
||||||
{
|
{
|
||||||
if let Some(resolver) = &self.module_resolver {
|
if let Some(resolver) = &self.module_resolver {
|
||||||
// Use an empty scope to create a module
|
// Use an empty scope to create a module
|
||||||
@ -1941,7 +1927,7 @@ impl Engine {
|
|||||||
resolver.resolve(self, Scope::new(), &path, expr.position())?;
|
resolver.resolve(self, Scope::new(), &path, expr.position())?;
|
||||||
|
|
||||||
let mod_name = unsafe_cast_var_name_to_lifetime(name, &state);
|
let mod_name = unsafe_cast_var_name_to_lifetime(name, &state);
|
||||||
scope.push_module(mod_name, module);
|
scope.push_module_internal(mod_name, module);
|
||||||
|
|
||||||
state.modules += 1;
|
state.modules += 1;
|
||||||
|
|
||||||
@ -1952,9 +1938,12 @@ impl Engine {
|
|||||||
expr.position(),
|
expr.position(),
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Err(Box::new(EvalAltResult::ErrorImportExpr(expr.position())))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "no_module")]
|
||||||
|
Ok(Default::default())
|
||||||
|
} else {
|
||||||
|
Err(Box::new(EvalAltResult::ErrorImportExpr(expr.position())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
use crate::any::{Dynamic, Variant};
|
use crate::any::{Dynamic, Variant};
|
||||||
use crate::calc_fn_hash;
|
use crate::calc_fn_hash;
|
||||||
use crate::engine::{make_getter, make_setter, Engine, FunctionsLib, FUNC_INDEXER};
|
use crate::engine::{make_getter, make_setter, Engine, FunctionsLib, FUNC_INDEXER};
|
||||||
use crate::fn_native::{CallableFunction, FnCallArgs, IteratorFn};
|
use crate::fn_native::{CallableFunction, FnCallArgs, IteratorFn, SendSync};
|
||||||
use crate::parser::{
|
use crate::parser::{
|
||||||
FnAccess,
|
FnAccess,
|
||||||
FnAccess::{Private, Public},
|
FnAccess::{Private, Public},
|
||||||
@ -945,23 +945,7 @@ impl ModuleRef {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Trait that encapsulates a module resolution service.
|
/// Trait that encapsulates a module resolution service.
|
||||||
#[cfg(not(feature = "no_module"))]
|
pub trait ModuleResolver: SendSync {
|
||||||
#[cfg(not(feature = "sync"))]
|
|
||||||
pub trait ModuleResolver {
|
|
||||||
/// Resolve a module based on a path string.
|
|
||||||
fn resolve(
|
|
||||||
&self,
|
|
||||||
engine: &Engine,
|
|
||||||
scope: Scope,
|
|
||||||
path: &str,
|
|
||||||
pos: Position,
|
|
||||||
) -> Result<Module, Box<EvalAltResult>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trait that encapsulates a module resolution service.
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
#[cfg(feature = "sync")]
|
|
||||||
pub trait ModuleResolver: Send + Sync {
|
|
||||||
/// Resolve a module based on a path string.
|
/// Resolve a module based on a path string.
|
||||||
fn resolve(
|
fn resolve(
|
||||||
&self,
|
&self,
|
||||||
@ -979,6 +963,8 @@ pub mod resolvers {
|
|||||||
pub use super::file::FileModuleResolver;
|
pub use super::file::FileModuleResolver;
|
||||||
pub use super::stat::StaticModuleResolver;
|
pub use super::stat::StaticModuleResolver;
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "no_module")]
|
||||||
|
pub mod resolvers {}
|
||||||
|
|
||||||
/// Script file-based module resolver.
|
/// Script file-based module resolver.
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
|
@ -4,18 +4,12 @@ use crate::any::{Dynamic, Union};
|
|||||||
use crate::calc_fn_hash;
|
use crate::calc_fn_hash;
|
||||||
use crate::engine::{make_getter, make_setter, Engine, FunctionsLib};
|
use crate::engine::{make_getter, make_setter, Engine, FunctionsLib};
|
||||||
use crate::error::{LexError, ParseError, ParseErrorType};
|
use crate::error::{LexError, ParseError, ParseErrorType};
|
||||||
|
use crate::module::ModuleRef;
|
||||||
use crate::optimize::{optimize_into_ast, OptimizationLevel};
|
use crate::optimize::{optimize_into_ast, OptimizationLevel};
|
||||||
use crate::scope::{EntryType as ScopeEntryType, Scope};
|
use crate::scope::{EntryType as ScopeEntryType, Scope};
|
||||||
use crate::token::{Position, Token, TokenIterator};
|
use crate::token::{Position, Token, TokenIterator};
|
||||||
use crate::utils::{StaticVec, StraightHasherBuilder};
|
use crate::utils::{StaticVec, StraightHasherBuilder};
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
use crate::module::ModuleRef;
|
|
||||||
|
|
||||||
#[cfg(feature = "no_module")]
|
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Hash, Copy, Default)]
|
|
||||||
pub struct ModuleRef;
|
|
||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
@ -644,7 +638,6 @@ impl Expr {
|
|||||||
|
|
||||||
Self::Variable(_) => match token {
|
Self::Variable(_) => match token {
|
||||||
Token::LeftBracket | Token::LeftParen => true,
|
Token::LeftBracket | Token::LeftParen => true,
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
Token::DoubleColon => true,
|
Token::DoubleColon => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
@ -761,27 +754,21 @@ fn parse_call_expr<'a>(
|
|||||||
Token::RightParen => {
|
Token::RightParen => {
|
||||||
eat_token(input, Token::RightParen);
|
eat_token(input, Token::RightParen);
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
let hash_fn_def = if let Some(modules) = modules.as_mut() {
|
||||||
let hash_fn_def = {
|
modules.set_index(state.find_module(&modules.get(0).0));
|
||||||
if let Some(modules) = modules.as_mut() {
|
|
||||||
modules.set_index(state.find_module(&modules.get(0).0));
|
|
||||||
|
|
||||||
// Rust functions are indexed in two steps:
|
// 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.
|
||||||
// 2) Calculate a second hash with no qualifiers, empty function name,
|
// 2) Calculate a second hash with no qualifiers, empty function name,
|
||||||
// zero number of arguments, and the actual list of argument `TypeId`'s.
|
// zero number of arguments, and the actual list of argument `TypeId`'s.
|
||||||
// 3) The final hash is the XOR of the two hashes.
|
// 3) The final hash is the XOR of the two hashes.
|
||||||
let qualifiers = modules.iter().map(|(m, _)| m.as_str());
|
let qualifiers = modules.iter().map(|(m, _)| m.as_str());
|
||||||
calc_fn_hash(qualifiers, &id, 0, empty())
|
calc_fn_hash(qualifiers, &id, 0, empty())
|
||||||
} else {
|
} else {
|
||||||
// Qualifiers (none) + function name + no parameters.
|
// Qualifiers (none) + function name + no parameters.
|
||||||
calc_fn_hash(empty(), &id, 0, empty())
|
calc_fn_hash(empty(), &id, 0, empty())
|
||||||
}
|
|
||||||
};
|
};
|
||||||
// Qualifiers (none) + function name + no parameters.
|
|
||||||
#[cfg(feature = "no_module")]
|
|
||||||
let hash_fn_def = calc_fn_hash(empty(), &id, 0, empty());
|
|
||||||
|
|
||||||
return Ok(Expr::FnCall(Box::new((
|
return Ok(Expr::FnCall(Box::new((
|
||||||
(id.into(), false, begin),
|
(id.into(), false, begin),
|
||||||
@ -803,27 +790,21 @@ fn parse_call_expr<'a>(
|
|||||||
(Token::RightParen, _) => {
|
(Token::RightParen, _) => {
|
||||||
eat_token(input, Token::RightParen);
|
eat_token(input, Token::RightParen);
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
let hash_fn_def = if let Some(modules) = modules.as_mut() {
|
||||||
let hash_fn_def = {
|
modules.set_index(state.find_module(&modules.get(0).0));
|
||||||
if let Some(modules) = modules.as_mut() {
|
|
||||||
modules.set_index(state.find_module(&modules.get(0).0));
|
|
||||||
|
|
||||||
// Rust functions are indexed in two steps:
|
// 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.
|
||||||
// 2) Calculate a second hash with no qualifiers, empty function name,
|
// 2) Calculate a second hash with no qualifiers, empty function name,
|
||||||
// zero number of arguments, and the actual list of argument `TypeId`'s.
|
// zero number of arguments, and the actual list of argument `TypeId`'s.
|
||||||
// 3) The final hash is the XOR of the two hashes.
|
// 3) The final hash is the XOR of the two hashes.
|
||||||
let qualifiers = modules.iter().map(|(m, _)| m.as_str());
|
let qualifiers = modules.iter().map(|(m, _)| m.as_str());
|
||||||
calc_fn_hash(qualifiers, &id, args.len(), empty())
|
calc_fn_hash(qualifiers, &id, args.len(), empty())
|
||||||
} else {
|
} else {
|
||||||
// Qualifiers (none) + function name + number of arguments.
|
// Qualifiers (none) + function name + number of arguments.
|
||||||
calc_fn_hash(empty(), &id, args.len(), empty())
|
calc_fn_hash(empty(), &id, args.len(), empty())
|
||||||
}
|
|
||||||
};
|
};
|
||||||
// Qualifiers (none) + function name + number of arguments.
|
|
||||||
#[cfg(feature = "no_module")]
|
|
||||||
let hash_fn_def = calc_fn_hash(empty(), &id, args.len(), empty());
|
|
||||||
|
|
||||||
return Ok(Expr::FnCall(Box::new((
|
return Ok(Expr::FnCall(Box::new((
|
||||||
(id.into(), false, begin),
|
(id.into(), false, begin),
|
||||||
@ -1265,7 +1246,6 @@ fn parse_primary<'a>(
|
|||||||
}
|
}
|
||||||
(Expr::Property(_), _) => unreachable!(),
|
(Expr::Property(_), _) => unreachable!(),
|
||||||
// module access
|
// module access
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
(Expr::Variable(x), Token::DoubleColon) => match input.next().unwrap() {
|
(Expr::Variable(x), Token::DoubleColon) => match input.next().unwrap() {
|
||||||
(Token::Identifier(id2), pos2) => {
|
(Token::Identifier(id2), pos2) => {
|
||||||
let ((name, pos), mut modules, _, index) = *x;
|
let ((name, pos), mut modules, _, index) = *x;
|
||||||
@ -1293,7 +1273,6 @@ fn parse_primary<'a>(
|
|||||||
|
|
||||||
match &mut root_expr {
|
match &mut root_expr {
|
||||||
// Cache the hash key for module-qualified variables
|
// Cache the hash key for module-qualified variables
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
Expr::Variable(x) if x.1.is_some() => {
|
Expr::Variable(x) if x.1.is_some() => {
|
||||||
let ((name, _), modules, hash, _) = x.as_mut();
|
let ((name, _), modules, hash, _) = x.as_mut();
|
||||||
let modules = modules.as_mut().unwrap();
|
let modules = modules.as_mut().unwrap();
|
||||||
@ -1520,9 +1499,6 @@ fn make_dot_expr(lhs: Expr, rhs: Expr, op_pos: Position) -> Result<Expr, ParseEr
|
|||||||
}
|
}
|
||||||
// lhs.module::id - syntax error
|
// lhs.module::id - syntax error
|
||||||
(_, Expr::Variable(x)) if x.1.is_some() => {
|
(_, Expr::Variable(x)) if x.1.is_some() => {
|
||||||
#[cfg(feature = "no_module")]
|
|
||||||
unreachable!();
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
return Err(PERR::PropertyExpected.into_err(x.1.unwrap().get(0).1));
|
return Err(PERR::PropertyExpected.into_err(x.1.unwrap().get(0).1));
|
||||||
}
|
}
|
||||||
// lhs.prop
|
// lhs.prop
|
||||||
@ -2113,6 +2089,7 @@ fn parse_import<'a>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Parse an export statement.
|
/// Parse an export statement.
|
||||||
|
#[cfg(not(feature = "no_module"))]
|
||||||
fn parse_export<'a>(
|
fn parse_export<'a>(
|
||||||
input: &mut Peekable<TokenIterator<'a>>,
|
input: &mut Peekable<TokenIterator<'a>>,
|
||||||
state: &mut ParseState,
|
state: &mut ParseState,
|
||||||
@ -2294,7 +2271,9 @@ fn parse_stmt<'a>(
|
|||||||
Token::LeftBrace => parse_block(input, state, breakable, level + 1, allow_stmt_expr),
|
Token::LeftBrace => parse_block(input, state, breakable, level + 1, allow_stmt_expr),
|
||||||
|
|
||||||
// fn ...
|
// fn ...
|
||||||
|
#[cfg(not(feature = "no_function"))]
|
||||||
Token::Fn if !is_global => Err(PERR::WrongFnDefinition.into_err(*pos)),
|
Token::Fn if !is_global => Err(PERR::WrongFnDefinition.into_err(*pos)),
|
||||||
|
#[cfg(not(feature = "no_function"))]
|
||||||
Token::Fn => unreachable!(),
|
Token::Fn => unreachable!(),
|
||||||
|
|
||||||
Token::If => parse_if(input, state, breakable, level + 1, allow_stmt_expr),
|
Token::If => parse_if(input, state, breakable, level + 1, allow_stmt_expr),
|
||||||
@ -2343,8 +2322,6 @@ fn parse_stmt<'a>(
|
|||||||
|
|
||||||
Token::Let => parse_let(input, state, Normal, level + 1, allow_stmt_expr),
|
Token::Let => parse_let(input, state, Normal, level + 1, allow_stmt_expr),
|
||||||
Token::Const => parse_let(input, state, Constant, level + 1, allow_stmt_expr),
|
Token::Const => parse_let(input, state, Constant, level + 1, allow_stmt_expr),
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
Token::Import => parse_import(input, state, level + 1, allow_stmt_expr),
|
Token::Import => parse_import(input, state, level + 1, allow_stmt_expr),
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
@ -2358,6 +2335,7 @@ fn parse_stmt<'a>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a function definition.
|
/// Parse a function definition.
|
||||||
|
#[cfg(not(feature = "no_function"))]
|
||||||
fn parse_fn<'a>(
|
fn parse_fn<'a>(
|
||||||
input: &mut Peekable<TokenIterator<'a>>,
|
input: &mut Peekable<TokenIterator<'a>>,
|
||||||
state: &mut ParseState,
|
state: &mut ParseState,
|
||||||
@ -2499,6 +2477,7 @@ fn parse_global_level<'a>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
match input.peek().unwrap() {
|
match input.peek().unwrap() {
|
||||||
|
#[cfg(not(feature = "no_function"))]
|
||||||
(Token::Fn, _) => {
|
(Token::Fn, _) => {
|
||||||
let mut state = ParseState::new(max_expr_depth.1);
|
let mut state = ParseState::new(max_expr_depth.1);
|
||||||
let func = parse_fn(input, &mut state, access, 0, true)?;
|
let func = parse_fn(input, &mut state, access, 0, true)?;
|
||||||
|
20
src/scope.rs
20
src/scope.rs
@ -1,12 +1,10 @@
|
|||||||
//! 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::any::{Dynamic, Union, Variant};
|
use crate::any::{Dynamic, Union, Variant};
|
||||||
|
use crate::module::Module;
|
||||||
use crate::parser::{map_dynamic_to_expr, Expr};
|
use crate::parser::{map_dynamic_to_expr, Expr};
|
||||||
use crate::token::Position;
|
use crate::token::Position;
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
use crate::module::Module;
|
|
||||||
|
|
||||||
use crate::stdlib::{borrow::Cow, boxed::Box, iter, string::String, vec::Vec};
|
use crate::stdlib::{borrow::Cow, boxed::Box, iter, string::String, vec::Vec};
|
||||||
|
|
||||||
/// Type of an entry in the Scope.
|
/// Type of an entry in the Scope.
|
||||||
@ -178,6 +176,17 @@ impl<'a> Scope<'a> {
|
|||||||
/// Modules are used for accessing member variables, functions and plugins under a namespace.
|
/// Modules are used for accessing member variables, functions and plugins under a namespace.
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
pub fn push_module<K: Into<Cow<'a, str>>>(&mut self, name: K, mut value: Module) {
|
pub fn push_module<K: Into<Cow<'a, str>>>(&mut self, name: K, mut value: Module) {
|
||||||
|
self.push_module_internal(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add (push) a new module to the Scope.
|
||||||
|
///
|
||||||
|
/// Modules are used for accessing member variables, functions and plugins under a namespace.
|
||||||
|
pub(crate) fn push_module_internal<K: Into<Cow<'a, str>>>(
|
||||||
|
&mut self,
|
||||||
|
name: K,
|
||||||
|
mut value: Module,
|
||||||
|
) {
|
||||||
value.index_all_sub_modules();
|
value.index_all_sub_modules();
|
||||||
|
|
||||||
self.push_dynamic_value(
|
self.push_dynamic_value(
|
||||||
@ -350,6 +359,11 @@ impl<'a> Scope<'a> {
|
|||||||
/// Find a module in the Scope, starting from the last entry.
|
/// Find a module in the Scope, starting from the last entry.
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
pub fn find_module(&mut self, name: &str) -> Option<&mut Module> {
|
pub fn find_module(&mut self, name: &str) -> Option<&mut Module> {
|
||||||
|
self.find_module_internal(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Find a module in the Scope, starting from the last entry.
|
||||||
|
pub(crate) fn find_module_internal(&mut self, name: &str) -> Option<&mut Module> {
|
||||||
let index = self.get_module_index(name)?;
|
let index = self.get_module_index(name)?;
|
||||||
self.get_mut(index).0.downcast_mut::<Module>()
|
self.get_mut(index).0.downcast_mut::<Module>()
|
||||||
}
|
}
|
||||||
|
@ -181,6 +181,7 @@ pub enum Token {
|
|||||||
XOr,
|
XOr,
|
||||||
Ampersand,
|
Ampersand,
|
||||||
And,
|
And,
|
||||||
|
#[cfg(not(feature = "no_function"))]
|
||||||
Fn,
|
Fn,
|
||||||
Continue,
|
Continue,
|
||||||
Break,
|
Break,
|
||||||
@ -199,6 +200,7 @@ pub enum Token {
|
|||||||
PowerOfAssign,
|
PowerOfAssign,
|
||||||
Private,
|
Private,
|
||||||
Import,
|
Import,
|
||||||
|
#[cfg(not(feature = "no_module"))]
|
||||||
Export,
|
Export,
|
||||||
As,
|
As,
|
||||||
LexError(Box<LexError>),
|
LexError(Box<LexError>),
|
||||||
@ -260,6 +262,7 @@ impl Token {
|
|||||||
Or => "||",
|
Or => "||",
|
||||||
Ampersand => "&",
|
Ampersand => "&",
|
||||||
And => "&&",
|
And => "&&",
|
||||||
|
#[cfg(not(feature = "no_function"))]
|
||||||
Fn => "fn",
|
Fn => "fn",
|
||||||
Continue => "continue",
|
Continue => "continue",
|
||||||
Break => "break",
|
Break => "break",
|
||||||
@ -283,6 +286,7 @@ impl Token {
|
|||||||
PowerOfAssign => "~=",
|
PowerOfAssign => "~=",
|
||||||
Private => "private",
|
Private => "private",
|
||||||
Import => "import",
|
Import => "import",
|
||||||
|
#[cfg(not(feature = "no_module"))]
|
||||||
Export => "export",
|
Export => "export",
|
||||||
As => "as",
|
As => "as",
|
||||||
EOF => "{EOF}",
|
EOF => "{EOF}",
|
||||||
@ -754,12 +758,9 @@ impl<'a> TokenIterator<'a> {
|
|||||||
"for" => Token::For,
|
"for" => Token::For,
|
||||||
"in" => Token::In,
|
"in" => Token::In,
|
||||||
"private" => Token::Private,
|
"private" => Token::Private,
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
"import" => Token::Import,
|
"import" => Token::Import,
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
"export" => Token::Export,
|
"export" => Token::Export,
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
"as" => Token::As,
|
"as" => Token::As,
|
||||||
|
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
@ -916,7 +917,6 @@ impl<'a> TokenIterator<'a> {
|
|||||||
}
|
}
|
||||||
('=', _) => return Some((Token::Equals, pos)),
|
('=', _) => return Some((Token::Equals, pos)),
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
(':', ':') => {
|
(':', ':') => {
|
||||||
self.eat_next();
|
self.eat_next();
|
||||||
return Some((Token::DoubleColon, pos));
|
return Some((Token::DoubleColon, pos));
|
||||||
|
@ -195,6 +195,7 @@ fn test_module_from_ast() -> Result<(), Box<EvalAltResult>> {
|
|||||||
let module = Module::eval_ast_as_new(Scope::new(), &ast, &engine)?;
|
let module = Module::eval_ast_as_new(Scope::new(), &ast, &engine)?;
|
||||||
|
|
||||||
let mut scope = Scope::new();
|
let mut scope = Scope::new();
|
||||||
|
|
||||||
scope.push_module("testing", module);
|
scope.push_module("testing", module);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
Loading…
Reference in New Issue
Block a user