commit
87e1921aad
12
CHANGELOG.md
12
CHANGELOG.md
@ -4,12 +4,24 @@ Rhai Release Notes
|
|||||||
Version 0.20.1
|
Version 0.20.1
|
||||||
==============
|
==============
|
||||||
|
|
||||||
|
This version enables functions to access constants declared at global level via the special `global` module.
|
||||||
|
|
||||||
Breaking changes
|
Breaking changes
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
* `Dynamic::is_shared` and `Dynamic::is_locked` are removed under the `no_closure` feature. They used to always return `false`.
|
* `Dynamic::is_shared` and `Dynamic::is_locked` are removed under the `no_closure` feature. They used to always return `false`.
|
||||||
* `Engine::call_fn` now evaluates the `AST` before calling the function.
|
* `Engine::call_fn` now evaluates the `AST` before calling the function.
|
||||||
|
|
||||||
|
Enhancements
|
||||||
|
------------
|
||||||
|
|
||||||
|
* The crate [`no-std-compat`](https://crates.io/crates/no_std_compat) is used to compile for `no-std`. This removes the need to use a special `crate::stdlib` namespace for `std` imports.
|
||||||
|
|
||||||
|
New features
|
||||||
|
------------
|
||||||
|
|
||||||
|
* A module called `global` is automatically created to hold global-level constants, which can then be accessed from functions.
|
||||||
|
|
||||||
|
|
||||||
Version 0.20.0
|
Version 0.20.0
|
||||||
==============
|
==============
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
// This script defines a function with many parameters and calls it
|
// This script defines a function with many parameters and calls it
|
||||||
|
|
||||||
|
const KEY = 38;
|
||||||
|
|
||||||
fn f(a, b, c, d, e, f) {
|
fn f(a, b, c, d, e, f) {
|
||||||
a - b * c - d * e - f
|
a - b * c - d * e - f + global::KEY
|
||||||
}
|
}
|
||||||
|
|
||||||
print("f() call should be 4:");
|
print("f() call should be 42:");
|
||||||
|
|
||||||
print(f(100, 5, 2, 9, 6, 32));
|
print(f(100, 5, 2, 9, 6, 32));
|
||||||
|
@ -12,7 +12,7 @@ fn new_mat(x, y) {
|
|||||||
|
|
||||||
fn mat_gen(n) {
|
fn mat_gen(n) {
|
||||||
let m = new_mat(n, n);
|
let m = new_mat(n, n);
|
||||||
let tmp = 1.0 / n / n;
|
const tmp = 1.0 / n / n;
|
||||||
|
|
||||||
for i in range(0, n) {
|
for i in range(0, n) {
|
||||||
for j in range(0, n) {
|
for j in range(0, n) {
|
||||||
@ -24,43 +24,36 @@ fn mat_gen(n) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn mat_mul(a, b) {
|
fn mat_mul(a, b) {
|
||||||
let m = a.len;
|
let b2 = new_mat(a[0].len, b[0].len);
|
||||||
let n = a[0].len;
|
|
||||||
let p = b[0].len;
|
|
||||||
|
|
||||||
let b2 = new_mat(n, p);
|
|
||||||
|
|
||||||
for i in range(0, n) {
|
for i in range(0, a[0].len) {
|
||||||
for j in range(0, p) {
|
for j in range(0, b[0].len) {
|
||||||
b2[j][i] = b[i][j];
|
b2[j][i] = b[i][j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let c = new_mat(m, p);
|
let c = new_mat(a.len, b[0].len);
|
||||||
|
|
||||||
for i in range(0, c.len) {
|
for i in range(0, c.len) {
|
||||||
let ci = c[i];
|
for j in range(0, c[i].len) {
|
||||||
for j in range(0, ci.len) {
|
c[i][j] = 0.0;
|
||||||
let b2j = b2[j];
|
|
||||||
ci[j] = 0.0;
|
|
||||||
|
|
||||||
for z in range(0, a[i].len) {
|
for z in range(0, a[i].len) {
|
||||||
let x = a[i][z];
|
let x = a[i][z];
|
||||||
let y = b2j[z];
|
let y = b2[j][z];
|
||||||
ci[j] += x * y;
|
c[i][j] += x * y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c[i] = ci;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c
|
c
|
||||||
}
|
}
|
||||||
|
|
||||||
let now = timestamp();
|
const now = timestamp();
|
||||||
|
|
||||||
let a = mat_gen(SIZE);
|
const a = mat_gen(SIZE);
|
||||||
let b = mat_gen(SIZE);
|
const b = mat_gen(SIZE);
|
||||||
let c = mat_mul(a, b);
|
const c = mat_mul(a, b);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
for i in range(0, SIZE) {
|
for i in range(0, SIZE) {
|
||||||
|
@ -70,6 +70,12 @@ impl Imports {
|
|||||||
pub fn get(&self, index: usize) -> Option<Shared<Module>> {
|
pub fn get(&self, index: usize) -> Option<Shared<Module>> {
|
||||||
self.1.get(index).cloned()
|
self.1.get(index).cloned()
|
||||||
}
|
}
|
||||||
|
/// Get the imported [modules][Module] at a particular index.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[inline(always)]
|
||||||
|
pub(crate) fn get_mut(&mut self, index: usize) -> Option<&mut Shared<Module>> {
|
||||||
|
self.1.get_mut(index)
|
||||||
|
}
|
||||||
/// Get the index of an imported [modules][Module] by name.
|
/// Get the index of an imported [modules][Module] by name.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn find(&self, name: &str) -> Option<usize> {
|
pub fn find(&self, name: &str) -> Option<usize> {
|
||||||
@ -199,6 +205,8 @@ pub const KEYWORD_IS_DEF_VAR: &str = "is_def_var";
|
|||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
pub const KEYWORD_IS_DEF_FN: &str = "is_def_fn";
|
pub const KEYWORD_IS_DEF_FN: &str = "is_def_fn";
|
||||||
pub const KEYWORD_THIS: &str = "this";
|
pub const KEYWORD_THIS: &str = "this";
|
||||||
|
#[cfg(not(feature = "no_function"))]
|
||||||
|
pub const KEYWORD_GLOBAL: &str = "global";
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
pub const FN_GET: &str = "get$";
|
pub const FN_GET: &str = "get$";
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
@ -896,6 +904,7 @@ impl Engine {
|
|||||||
disable_doc_comments: false,
|
disable_doc_comments: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
engine.global_namespace.set_internal(true);
|
||||||
engine.register_global_module(StandardPackage::new().as_shared_module());
|
engine.register_global_module(StandardPackage::new().as_shared_module());
|
||||||
|
|
||||||
engine
|
engine
|
||||||
@ -906,7 +915,7 @@ impl Engine {
|
|||||||
/// Use [`register_global_module`][Engine::register_global_module] to add packages of functions.
|
/// Use [`register_global_module`][Engine::register_global_module] to add packages of functions.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn new_raw() -> Self {
|
pub fn new_raw() -> Self {
|
||||||
Self {
|
let mut engine = Self {
|
||||||
global_namespace: Default::default(),
|
global_namespace: Default::default(),
|
||||||
global_modules: Default::default(),
|
global_modules: Default::default(),
|
||||||
global_sub_modules: Default::default(),
|
global_sub_modules: Default::default(),
|
||||||
@ -952,7 +961,11 @@ impl Engine {
|
|||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
disable_doc_comments: false,
|
disable_doc_comments: false,
|
||||||
}
|
};
|
||||||
|
|
||||||
|
engine.global_namespace.set_internal(true);
|
||||||
|
|
||||||
|
engine
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Search for a module within an imports stack.
|
/// Search for a module within an imports stack.
|
||||||
@ -2504,6 +2517,31 @@ impl Engine {
|
|||||||
.flatten();
|
.flatten();
|
||||||
|
|
||||||
let (var_name, _alias): (Cow<'_, str>, _) = if state.is_global() {
|
let (var_name, _alias): (Cow<'_, str>, _) = if state.is_global() {
|
||||||
|
#[cfg(not(feature = "no_function"))]
|
||||||
|
if entry_type == AccessMode::ReadOnly && lib.iter().any(|&m| !m.is_empty()) {
|
||||||
|
let global = if let Some(index) = mods.find(KEYWORD_GLOBAL) {
|
||||||
|
let global = mods.get_mut(index).unwrap();
|
||||||
|
|
||||||
|
if !global.is_internal() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(global)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Create automatic global module
|
||||||
|
let mut global = Module::new();
|
||||||
|
global.set_internal(true);
|
||||||
|
mods.push(crate::engine::KEYWORD_GLOBAL, global);
|
||||||
|
Some(mods.get_mut(mods.len() - 1).unwrap())
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(global) = global {
|
||||||
|
let global = Shared::get_mut(global).unwrap();
|
||||||
|
global.set_var(name.clone(), value.clone());
|
||||||
|
global.build_index();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
(
|
(
|
||||||
name.to_string().into(),
|
name.to_string().into(),
|
||||||
if *export { Some(name.clone()) } else { None },
|
if *export { Some(name.clone()) } else { None },
|
||||||
|
@ -128,6 +128,8 @@ fn calc_native_fn_hash<'a>(
|
|||||||
pub struct Module {
|
pub struct Module {
|
||||||
/// ID identifying the module.
|
/// ID identifying the module.
|
||||||
id: Option<Identifier>,
|
id: Option<Identifier>,
|
||||||
|
/// Is this module internal?
|
||||||
|
internal: bool,
|
||||||
/// Sub-modules.
|
/// Sub-modules.
|
||||||
modules: BTreeMap<Identifier, Shared<Module>>,
|
modules: BTreeMap<Identifier, Shared<Module>>,
|
||||||
/// [`Module`] variables.
|
/// [`Module`] variables.
|
||||||
@ -156,6 +158,7 @@ impl Default for Module {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: None,
|
id: None,
|
||||||
|
internal: false,
|
||||||
modules: Default::default(),
|
modules: Default::default(),
|
||||||
variables: Default::default(),
|
variables: Default::default(),
|
||||||
all_variables: Default::default(),
|
all_variables: Default::default(),
|
||||||
@ -301,8 +304,23 @@ impl Module {
|
|||||||
/// assert_eq!(module.id(), Some("hello"));
|
/// assert_eq!(module.id(), Some("hello"));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn set_id<S: Into<Identifier>>(&mut self, id: Option<S>) {
|
pub fn set_id<S: Into<Identifier>>(&mut self, id: Option<S>) -> &mut Self {
|
||||||
self.id = id.map(|s| s.into());
|
self.id = id.map(|s| s.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Is the [`Module`] internal?
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[inline(always)]
|
||||||
|
pub(crate) fn is_internal(&self) -> bool {
|
||||||
|
self.internal
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the interal status of the [`Module`].
|
||||||
|
#[inline(always)]
|
||||||
|
pub(crate) fn set_internal(&mut self, value: bool) -> &mut Self {
|
||||||
|
self.internal = value;
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is the [`Module`] empty?
|
/// Is the [`Module`] empty?
|
||||||
|
@ -62,7 +62,22 @@ fn test_functions_namespaces() -> Result<(), Box<EvalAltResult>> {
|
|||||||
assert_eq!(engine.eval::<INT>("test()")?, 42);
|
assert_eq!(engine.eval::<INT>("test()")?, 42);
|
||||||
|
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
assert_eq!(engine.eval::<INT>("fn test() { 123 } test()")?, 123);
|
{
|
||||||
|
assert_eq!(engine.eval::<INT>("fn test() { 123 } test()")?, 123);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
engine.eval::<INT>(
|
||||||
|
r"
|
||||||
|
const ANSWER = 42;
|
||||||
|
|
||||||
|
fn foo() { global::ANSWER }
|
||||||
|
|
||||||
|
foo()
|
||||||
|
"
|
||||||
|
)?,
|
||||||
|
42
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user