Pack Imports.
This commit is contained in:
parent
717e8e7eee
commit
b07a2aa79c
@ -25,6 +25,14 @@ import "crypto_init"; // run the script file 'crypto_init.rhai' withou
|
|||||||
|
|
||||||
import "crypto" as lock; // run the script file 'crypto.rhai' and import it as a module named 'lock'
|
import "crypto" as lock; // run the script file 'crypto.rhai' and import it as a module named 'lock'
|
||||||
|
|
||||||
|
const SECRET_NUMBER = 42;
|
||||||
|
|
||||||
|
let mod_file = "crypto_" + SECRET_NUMBER;
|
||||||
|
|
||||||
|
import mod_file as my_mod; // load the script file "crypto_42.rhai" and import it as a module named 'my_mod'
|
||||||
|
// notice that module path names can be dynamically constructed!
|
||||||
|
// any expression that evaluates to a string is acceptable after the 'import' keyword
|
||||||
|
|
||||||
lock::encrypt(secret); // use functions defined under the module via '::'
|
lock::encrypt(secret); // use functions defined under the module via '::'
|
||||||
|
|
||||||
lock::hash::sha256(key); // sub-modules are also supported
|
lock::hash::sha256(key); // sub-modules are also supported
|
||||||
|
@ -69,10 +69,58 @@ pub type Map = HashMap<ImmutableString, Dynamic>;
|
|||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
//
|
//
|
||||||
// Note - We cannot use &str or Cow<str> here because `eval` may load a module
|
// # Implementation Notes
|
||||||
// and the module name will live beyond the AST of the eval script text.
|
//
|
||||||
// The best we can do is a shared reference.
|
// We cannot use &str or Cow<str> here because `eval` may load a module and the module name will live beyond
|
||||||
pub type Imports = Vec<(ImmutableString, Module)>;
|
// the AST of the eval script text. The best we can do is a shared reference.
|
||||||
|
//
|
||||||
|
// `Imports` is implemented as two `Vec`'s of exactly the same length. That's because a `Module` is large,
|
||||||
|
// so packing the import names together improves cache locality.
|
||||||
|
#[derive(Debug, Clone, Default)]
|
||||||
|
pub struct Imports(StaticVec<ImmutableString>, StaticVec<Module>);
|
||||||
|
|
||||||
|
impl Imports {
|
||||||
|
/// Get the length of this stack of imported modules.
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.0.len()
|
||||||
|
}
|
||||||
|
/// Get the imported module at a particular index.
|
||||||
|
pub fn get(&self, index: usize) -> Option<&Module> {
|
||||||
|
self.1.get(index)
|
||||||
|
}
|
||||||
|
/// Get a mutable reference to the imported module at a particular index.
|
||||||
|
pub fn get_mut(&mut self, index: usize) -> Option<&mut Module> {
|
||||||
|
self.1.get_mut(index)
|
||||||
|
}
|
||||||
|
/// Get the index of an imported module by name.
|
||||||
|
pub fn find(&self, name: &str) -> Option<usize> {
|
||||||
|
self.0
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.rev()
|
||||||
|
.find(|(_, key)| key.as_str() == name)
|
||||||
|
.map(|(index, _)| index)
|
||||||
|
}
|
||||||
|
/// Push an imported module onto the stack.
|
||||||
|
pub fn push(&mut self, name: impl Into<ImmutableString>, module: Module) {
|
||||||
|
self.0.push(name.into());
|
||||||
|
self.1.push(module);
|
||||||
|
}
|
||||||
|
/// Truncate the stack of imported modules to a particular length.
|
||||||
|
pub fn truncate(&mut self, size: usize) {
|
||||||
|
self.0.truncate(size);
|
||||||
|
self.1.truncate(size);
|
||||||
|
}
|
||||||
|
/// Get an iterator to this stack of imported modules.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn iter(&self) -> impl Iterator<Item = (&str, &Module)> {
|
||||||
|
self.0.iter().map(|name| name.as_str()).zip(self.1.iter())
|
||||||
|
}
|
||||||
|
/// Get a consuming iterator to this stack of imported modules.
|
||||||
|
pub fn into_iter(self) -> impl Iterator<Item = (ImmutableString, Module)> {
|
||||||
|
self.0.into_iter().zip(self.1.into_iter())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
@ -602,12 +650,10 @@ pub fn search_imports<'s>(
|
|||||||
|
|
||||||
Ok(if index > 0 {
|
Ok(if index > 0 {
|
||||||
let offset = mods.len() - index;
|
let offset = mods.len() - index;
|
||||||
&mods.get(offset).unwrap().1
|
mods.get(offset).expect("invalid index in Imports")
|
||||||
} else {
|
} else {
|
||||||
mods.iter()
|
mods.find(root)
|
||||||
.rev()
|
.map(|n| mods.get(n).expect("invalid index in Imports"))
|
||||||
.find(|(n, _)| n == root)
|
|
||||||
.map(|(_, m)| m)
|
|
||||||
.ok_or_else(|| EvalAltResult::ErrorModuleNotFound(root.to_string(), *pos))?
|
.ok_or_else(|| EvalAltResult::ErrorModuleNotFound(root.to_string(), *pos))?
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -630,13 +676,14 @@ pub fn search_imports_mut<'s>(
|
|||||||
|
|
||||||
Ok(if index > 0 {
|
Ok(if index > 0 {
|
||||||
let offset = mods.len() - index;
|
let offset = mods.len() - index;
|
||||||
&mut mods.get_mut(offset).unwrap().1
|
mods.get_mut(offset).expect("invalid index in Imports")
|
||||||
} else {
|
} else {
|
||||||
mods.iter_mut()
|
if let Some(n) = mods.find(root) {
|
||||||
.rev()
|
mods.get_mut(n)
|
||||||
.find(|(n, _)| n == root)
|
} else {
|
||||||
.map(|(_, m)| m)
|
None
|
||||||
.ok_or_else(|| EvalAltResult::ErrorModuleNotFound(root.to_string(), *pos))?
|
}
|
||||||
|
.ok_or_else(|| EvalAltResult::ErrorModuleNotFound(root.to_string(), *pos))?
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2092,7 +2139,7 @@ impl Engine {
|
|||||||
|
|
||||||
if let Some(name_def) = alias {
|
if let Some(name_def) = alias {
|
||||||
module.index_all_sub_modules();
|
module.index_all_sub_modules();
|
||||||
mods.push((name_def.name.clone(), module));
|
mods.push(name_def.name.clone(), module);
|
||||||
}
|
}
|
||||||
|
|
||||||
state.modules += 1;
|
state.modules += 1;
|
||||||
|
@ -13,11 +13,7 @@ use crate::{calc_native_fn_hash, calc_script_fn_hash, StaticVec};
|
|||||||
use crate::{ast::ScriptFnDef, fn_native::Shared};
|
use crate::{ast::ScriptFnDef, fn_native::Shared};
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
use crate::{
|
use crate::{ast::AST, engine::Engine, scope::Scope};
|
||||||
ast::AST,
|
|
||||||
engine::{Engine, Imports},
|
|
||||||
scope::Scope,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
use crate::engine::{Array, FN_IDX_GET, FN_IDX_SET};
|
use crate::engine::{Array, FN_IDX_GET, FN_IDX_SET};
|
||||||
@ -1340,7 +1336,7 @@ impl Module {
|
|||||||
ast: &AST,
|
ast: &AST,
|
||||||
engine: &Engine,
|
engine: &Engine,
|
||||||
) -> Result<Self, Box<EvalAltResult>> {
|
) -> Result<Self, Box<EvalAltResult>> {
|
||||||
let mut mods = Imports::new();
|
let mut mods = Default::default();
|
||||||
|
|
||||||
// Run the script
|
// Run the script
|
||||||
engine.eval_ast_with_scope_raw(&mut scope, &mut mods, &ast)?;
|
engine.eval_ast_with_scope_raw(&mut scope, &mut mods, &ast)?;
|
||||||
|
Loading…
Reference in New Issue
Block a user