Reduce usage of Default::default() to make it easier to refactor.
This commit is contained in:
parent
61cc3d0bf2
commit
68c0ee08c0
30
src/ast.rs
30
src/ast.rs
@ -227,11 +227,11 @@ impl AST {
|
|||||||
/// Create an empty [`AST`].
|
/// Create an empty [`AST`].
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub(crate) fn empty() -> Self {
|
pub fn empty() -> Self {
|
||||||
Self {
|
Self {
|
||||||
source: None,
|
source: None,
|
||||||
body: Default::default(),
|
body: StmtBlock::empty(),
|
||||||
functions: Default::default(),
|
functions: Module::new().into(),
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
resolver: None,
|
resolver: None,
|
||||||
}
|
}
|
||||||
@ -399,11 +399,11 @@ impl AST {
|
|||||||
&self,
|
&self,
|
||||||
filter: impl Fn(FnNamespace, FnAccess, bool, &str, usize) -> bool,
|
filter: impl Fn(FnNamespace, FnAccess, bool, &str, usize) -> bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut functions: Module = Default::default();
|
let mut functions = Module::new();
|
||||||
functions.merge_filtered(&self.functions, &filter);
|
functions.merge_filtered(&self.functions, &filter);
|
||||||
Self {
|
Self {
|
||||||
source: self.source.clone(),
|
source: self.source.clone(),
|
||||||
body: Default::default(),
|
body: StmtBlock::empty(),
|
||||||
functions: functions.into(),
|
functions: functions.into(),
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
resolver: self.resolver.clone(),
|
resolver: self.resolver.clone(),
|
||||||
@ -417,7 +417,7 @@ impl AST {
|
|||||||
Self {
|
Self {
|
||||||
source: self.source.clone(),
|
source: self.source.clone(),
|
||||||
body: self.body.clone(),
|
body: self.body.clone(),
|
||||||
functions: Default::default(),
|
functions: Module::new().into(),
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
resolver: self.resolver.clone(),
|
resolver: self.resolver.clone(),
|
||||||
}
|
}
|
||||||
@ -599,7 +599,7 @@ impl AST {
|
|||||||
}
|
}
|
||||||
(false, true) => body.clone(),
|
(false, true) => body.clone(),
|
||||||
(true, false) => other.body.clone(),
|
(true, false) => other.body.clone(),
|
||||||
(true, true) => Default::default(),
|
(true, true) => StmtBlock::empty(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let source = other.source.clone().or_else(|| self.source.clone());
|
let source = other.source.clone().or_else(|| self.source.clone());
|
||||||
@ -740,13 +740,13 @@ impl AST {
|
|||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn clear_functions(&mut self) -> &mut Self {
|
pub fn clear_functions(&mut self) -> &mut Self {
|
||||||
self.functions = Default::default();
|
self.functions = Module::new().into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
/// Clear all statements in the [`AST`], leaving only function definitions.
|
/// Clear all statements in the [`AST`], leaving only function definitions.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn clear_statements(&mut self) -> &mut Self {
|
pub fn clear_statements(&mut self) -> &mut Self {
|
||||||
self.body = Default::default();
|
self.body = StmtBlock::empty();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
/// Recursively walk the [`AST`], including function bodies (if any).
|
/// Recursively walk the [`AST`], including function bodies (if any).
|
||||||
@ -755,7 +755,7 @@ impl AST {
|
|||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn walk(&self, on_node: &mut impl FnMut(&[ASTNode]) -> bool) -> bool {
|
pub(crate) fn walk(&self, on_node: &mut impl FnMut(&[ASTNode]) -> bool) -> bool {
|
||||||
let path = &mut Default::default();
|
let path = &mut Vec::new();
|
||||||
|
|
||||||
for stmt in self.statements() {
|
for stmt in self.statements() {
|
||||||
if !stmt.walk(path, on_node) {
|
if !stmt.walk(path, on_node) {
|
||||||
@ -777,7 +777,7 @@ impl AST {
|
|||||||
#[cfg(feature = "internals")]
|
#[cfg(feature = "internals")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn walk(&self, on_node: &mut impl FnMut(&[ASTNode]) -> bool) -> bool {
|
pub fn walk(&self, on_node: &mut impl FnMut(&[ASTNode]) -> bool) -> bool {
|
||||||
let path = &mut Default::default();
|
let path = &mut Vec::new();
|
||||||
|
|
||||||
for stmt in self.statements() {
|
for stmt in self.statements() {
|
||||||
if !stmt.walk(path, on_node) {
|
if !stmt.walk(path, on_node) {
|
||||||
@ -899,6 +899,12 @@ impl StmtBlock {
|
|||||||
statements.shrink_to_fit();
|
statements.shrink_to_fit();
|
||||||
Self(statements, pos)
|
Self(statements, pos)
|
||||||
}
|
}
|
||||||
|
/// Create an empty [`StmtBlock`].
|
||||||
|
#[inline(always)]
|
||||||
|
#[must_use]
|
||||||
|
pub fn empty() -> Self {
|
||||||
|
Default::default()
|
||||||
|
}
|
||||||
/// Is this statements block empty?
|
/// Is this statements block empty?
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
@ -1205,7 +1211,7 @@ impl From<Stmt> for StmtBlock {
|
|||||||
fn from(stmt: Stmt) -> Self {
|
fn from(stmt: Stmt) -> Self {
|
||||||
match stmt {
|
match stmt {
|
||||||
Stmt::Block(mut block, pos) => Self(block.iter_mut().map(mem::take).collect(), pos),
|
Stmt::Block(mut block, pos) => Self(block.iter_mut().map(mem::take).collect(), pos),
|
||||||
Stmt::Noop(pos) => Self(Default::default(), pos),
|
Stmt::Noop(pos) => Self(StaticVec::new(), pos),
|
||||||
_ => {
|
_ => {
|
||||||
let pos = stmt.position();
|
let pos = stmt.position();
|
||||||
Self(vec![stmt].into(), pos)
|
Self(vec![stmt].into(), pos)
|
||||||
|
@ -114,7 +114,7 @@ fn main() {
|
|||||||
.map_err(|err| err.into())
|
.map_err(|err| err.into())
|
||||||
.and_then(|mut ast| {
|
.and_then(|mut ast| {
|
||||||
ast.set_source(filename.to_string_lossy().to_string());
|
ast.set_source(filename.to_string_lossy().to_string());
|
||||||
Module::eval_ast_as_new(Default::default(), &ast, &engine)
|
Module::eval_ast_as_new(Scope::new(), &ast, &engine)
|
||||||
}) {
|
}) {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
let filename = filename.to_string_lossy();
|
let filename = filename.to_string_lossy();
|
||||||
@ -163,9 +163,9 @@ fn main() {
|
|||||||
|
|
||||||
// REPL loop
|
// REPL loop
|
||||||
let mut input = String::new();
|
let mut input = String::new();
|
||||||
let mut main_ast: AST = Default::default();
|
let mut main_ast = AST::empty();
|
||||||
let mut ast_u: AST = Default::default();
|
let mut ast_u = AST::empty();
|
||||||
let mut ast: AST = Default::default();
|
let mut ast = AST::empty();
|
||||||
|
|
||||||
'main_loop: loop {
|
'main_loop: loop {
|
||||||
print!("rhai-repl> ");
|
print!("rhai-repl> ");
|
||||||
|
@ -56,7 +56,7 @@ pub type Precedence = NonZeroU8;
|
|||||||
// This implementation splits the module names from the shared modules to improve data locality.
|
// This implementation splits the module names from the shared modules to improve data locality.
|
||||||
// Most usage will be looking up a particular key from the list and then getting the module that
|
// Most usage will be looking up a particular key from the list and then getting the module that
|
||||||
// corresponds to that key.
|
// corresponds to that key.
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone)]
|
||||||
pub struct Imports {
|
pub struct Imports {
|
||||||
keys: StaticVec<Identifier>,
|
keys: StaticVec<Identifier>,
|
||||||
modules: StaticVec<Shared<Module>>,
|
modules: StaticVec<Shared<Module>>,
|
||||||
@ -689,12 +689,6 @@ pub struct EvalState {
|
|||||||
pub global_constants: BTreeMap<Identifier, Dynamic>,
|
pub global_constants: BTreeMap<Identifier, Dynamic>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for EvalState {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EvalState {
|
impl EvalState {
|
||||||
/// Create a new [`EvalState`].
|
/// Create a new [`EvalState`].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@ -736,7 +730,7 @@ impl EvalState {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn push_fn_resolution_cache(&mut self) {
|
pub fn push_fn_resolution_cache(&mut self) {
|
||||||
self.fn_resolution_caches.push(Default::default());
|
self.fn_resolution_caches.push(BTreeMap::new());
|
||||||
}
|
}
|
||||||
/// Remove the current function resolution cache from the stack and make the last one current.
|
/// Remove the current function resolution cache from the stack and make the last one current.
|
||||||
///
|
///
|
||||||
@ -824,8 +818,8 @@ pub struct Limits {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
impl Default for Limits {
|
impl Limits {
|
||||||
fn default() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
max_call_stack_depth: MAX_CALL_STACK_DEPTH,
|
max_call_stack_depth: MAX_CALL_STACK_DEPTH,
|
||||||
@ -1090,17 +1084,17 @@ impl Engine {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new_raw() -> Self {
|
pub fn new_raw() -> Self {
|
||||||
let mut engine = Self {
|
let mut engine = Self {
|
||||||
global_modules: Default::default(),
|
global_modules: StaticVec::new(),
|
||||||
global_sub_modules: Default::default(),
|
global_sub_modules: BTreeMap::new(),
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
module_resolver: None,
|
module_resolver: None,
|
||||||
|
|
||||||
type_names: Default::default(),
|
type_names: BTreeMap::new(),
|
||||||
empty_string: Default::default(),
|
empty_string: ImmutableString::new(),
|
||||||
disabled_symbols: Default::default(),
|
disabled_symbols: BTreeSet::new(),
|
||||||
custom_keywords: Default::default(),
|
custom_keywords: BTreeMap::new(),
|
||||||
custom_syntax: Default::default(),
|
custom_syntax: BTreeMap::new(),
|
||||||
|
|
||||||
resolve_var: None,
|
resolve_var: None,
|
||||||
token_mapper: None,
|
token_mapper: None,
|
||||||
@ -1115,7 +1109,7 @@ impl Engine {
|
|||||||
optimization_level: Default::default(),
|
optimization_level: Default::default(),
|
||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
limits: Default::default(),
|
limits: Limits::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add the global namespace module
|
// Add the global namespace module
|
||||||
@ -1654,7 +1648,7 @@ impl Engine {
|
|||||||
let rhs_chain = match_chaining_type(rhs);
|
let rhs_chain = match_chaining_type(rhs);
|
||||||
let hash_get = FnCallHashes::from_native(*hash_get);
|
let hash_get = FnCallHashes::from_native(*hash_get);
|
||||||
let hash_set = FnCallHashes::from_native(*hash_set);
|
let hash_set = FnCallHashes::from_native(*hash_set);
|
||||||
let mut arg_values = [target.as_mut(), &mut Default::default()];
|
let mut arg_values = [target.as_mut(), &mut Dynamic::UNIT.clone()];
|
||||||
let args = &mut arg_values[..1];
|
let args = &mut arg_values[..1];
|
||||||
|
|
||||||
// Assume getters are always pure
|
// Assume getters are always pure
|
||||||
@ -1796,7 +1790,7 @@ impl Engine {
|
|||||||
_ => unreachable!("index or dot chain expected, but gets {:?}", expr),
|
_ => unreachable!("index or dot chain expected, but gets {:?}", expr),
|
||||||
};
|
};
|
||||||
|
|
||||||
let idx_values = &mut Default::default();
|
let idx_values = &mut StaticVec::new();
|
||||||
|
|
||||||
self.eval_dot_index_chain_arguments(
|
self.eval_dot_index_chain_arguments(
|
||||||
scope, mods, state, lib, this_ptr, rhs, term, chain_type, idx_values, 0, level,
|
scope, mods, state, lib, this_ptr, rhs, term, chain_type, idx_values, 0, level,
|
||||||
@ -2037,7 +2031,7 @@ impl Engine {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
if _add_if_not_found && !map.contains_key(index.as_str()) {
|
if _add_if_not_found && !map.contains_key(index.as_str()) {
|
||||||
map.insert(index.clone().into(), Default::default());
|
map.insert(index.clone().into(), Dynamic::UNIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(map
|
Ok(map
|
||||||
@ -2782,7 +2776,6 @@ impl Engine {
|
|||||||
});
|
});
|
||||||
scope.push(unsafe_cast_var_name_to_lifetime(name), ());
|
scope.push(unsafe_cast_var_name_to_lifetime(name), ());
|
||||||
let index = scope.len() - 1;
|
let index = scope.len() - 1;
|
||||||
state.scope_level += 1;
|
|
||||||
|
|
||||||
for (x, iter_value) in func(iter_obj).enumerate() {
|
for (x, iter_value) in func(iter_obj).enumerate() {
|
||||||
// Increment counter
|
// Increment counter
|
||||||
@ -2839,7 +2832,6 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state.scope_level -= 1;
|
|
||||||
scope.rewind(orig_scope_len);
|
scope.rewind(orig_scope_len);
|
||||||
Ok(Dynamic::UNIT)
|
Ok(Dynamic::UNIT)
|
||||||
} else {
|
} else {
|
||||||
@ -2942,7 +2934,6 @@ impl Engine {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let orig_scope_len = scope.len();
|
let orig_scope_len = scope.len();
|
||||||
state.scope_level += 1;
|
|
||||||
|
|
||||||
err_var.as_ref().map(|Ident { name, .. }| {
|
err_var.as_ref().map(|Ident { name, .. }| {
|
||||||
scope.push(unsafe_cast_var_name_to_lifetime(name), err_value)
|
scope.push(unsafe_cast_var_name_to_lifetime(name), err_value)
|
||||||
@ -2952,7 +2943,6 @@ impl Engine {
|
|||||||
scope, mods, state, lib, this_ptr, catch_stmt, true, level,
|
scope, mods, state, lib, this_ptr, catch_stmt, true, level,
|
||||||
);
|
);
|
||||||
|
|
||||||
state.scope_level -= 1;
|
|
||||||
scope.rewind(orig_scope_len);
|
scope.rewind(orig_scope_len);
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
|
@ -1002,7 +1002,7 @@ impl Engine {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn compile(&self, script: &str) -> Result<AST, ParseError> {
|
pub fn compile(&self, script: &str) -> Result<AST, ParseError> {
|
||||||
self.compile_with_scope(&Default::default(), script)
|
self.compile_with_scope(&Scope::new(), script)
|
||||||
}
|
}
|
||||||
/// Compile a string into an [`AST`] using own scope, which can be used later for evaluation.
|
/// Compile a string into an [`AST`] using own scope, which can be used later for evaluation.
|
||||||
///
|
///
|
||||||
@ -1091,7 +1091,7 @@ impl Engine {
|
|||||||
|
|
||||||
if let Some(ref module_resolver) = self.module_resolver {
|
if let Some(ref module_resolver) = self.module_resolver {
|
||||||
let mut resolver = StaticModuleResolver::new();
|
let mut resolver = StaticModuleResolver::new();
|
||||||
let mut imports = Default::default();
|
let mut imports = BTreeSet::new();
|
||||||
|
|
||||||
collect_imports(&ast, &resolver, &mut imports);
|
collect_imports(&ast, &resolver, &mut imports);
|
||||||
|
|
||||||
@ -1256,7 +1256,7 @@ impl Engine {
|
|||||||
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn compile_file(&self, path: std::path::PathBuf) -> Result<AST, Box<EvalAltResult>> {
|
pub fn compile_file(&self, path: std::path::PathBuf) -> Result<AST, Box<EvalAltResult>> {
|
||||||
self.compile_file_with_scope(&Default::default(), path)
|
self.compile_file_with_scope(&Scope::new(), 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.
|
||||||
///
|
///
|
||||||
@ -1424,7 +1424,7 @@ impl Engine {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn compile_expression(&self, script: &str) -> Result<AST, ParseError> {
|
pub fn compile_expression(&self, script: &str) -> Result<AST, ParseError> {
|
||||||
self.compile_expression_with_scope(&Default::default(), script)
|
self.compile_expression_with_scope(&Scope::new(), script)
|
||||||
}
|
}
|
||||||
/// Compile a string containing an expression into an [`AST`] using own scope,
|
/// Compile a string containing an expression into an [`AST`] using own scope,
|
||||||
/// which can be used later for evaluation.
|
/// which can be used later for evaluation.
|
||||||
@ -1558,7 +1558,7 @@ impl Engine {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn eval<T: Variant + Clone>(&self, script: &str) -> Result<T, Box<EvalAltResult>> {
|
pub fn eval<T: Variant + Clone>(&self, script: &str) -> Result<T, Box<EvalAltResult>> {
|
||||||
self.eval_with_scope(&mut Default::default(), script)
|
self.eval_with_scope(&mut Scope::new(), script)
|
||||||
}
|
}
|
||||||
/// Evaluate a string with own scope.
|
/// Evaluate a string with own scope.
|
||||||
///
|
///
|
||||||
@ -1615,7 +1615,7 @@ impl Engine {
|
|||||||
&self,
|
&self,
|
||||||
script: &str,
|
script: &str,
|
||||||
) -> Result<T, Box<EvalAltResult>> {
|
) -> Result<T, Box<EvalAltResult>> {
|
||||||
self.eval_expression_with_scope(&mut Default::default(), script)
|
self.eval_expression_with_scope(&mut Scope::new(), script)
|
||||||
}
|
}
|
||||||
/// Evaluate a string containing an expression with own scope.
|
/// Evaluate a string containing an expression with own scope.
|
||||||
///
|
///
|
||||||
@ -1677,7 +1677,7 @@ impl Engine {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn eval_ast<T: Variant + Clone>(&self, ast: &AST) -> Result<T, Box<EvalAltResult>> {
|
pub fn eval_ast<T: Variant + Clone>(&self, ast: &AST) -> Result<T, Box<EvalAltResult>> {
|
||||||
self.eval_ast_with_scope(&mut Default::default(), ast)
|
self.eval_ast_with_scope(&mut Scope::new(), ast)
|
||||||
}
|
}
|
||||||
/// Evaluate an [`AST`] with own scope.
|
/// Evaluate an [`AST`] with own scope.
|
||||||
///
|
///
|
||||||
@ -1714,7 +1714,7 @@ impl Engine {
|
|||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
ast: &AST,
|
ast: &AST,
|
||||||
) -> Result<T, Box<EvalAltResult>> {
|
) -> Result<T, Box<EvalAltResult>> {
|
||||||
let mods = &mut Default::default();
|
let mods = &mut Imports::new();
|
||||||
|
|
||||||
let result = self.eval_ast_with_scope_raw(scope, mods, ast, 0)?;
|
let result = self.eval_ast_with_scope_raw(scope, mods, ast, 0)?;
|
||||||
|
|
||||||
@ -1779,7 +1779,7 @@ impl Engine {
|
|||||||
/// Evaluate a script, returning any error (if any).
|
/// Evaluate a script, returning any error (if any).
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn run(&self, script: &str) -> Result<(), Box<EvalAltResult>> {
|
pub fn run(&self, script: &str) -> Result<(), Box<EvalAltResult>> {
|
||||||
self.run_with_scope(&mut Default::default(), script)
|
self.run_with_scope(&mut Scope::new(), script)
|
||||||
}
|
}
|
||||||
/// Evaluate a script with own scope, returning any error (if any).
|
/// Evaluate a script with own scope, returning any error (if any).
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -1806,7 +1806,7 @@ impl Engine {
|
|||||||
/// Evaluate an AST, returning any error (if any).
|
/// Evaluate an AST, returning any error (if any).
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn run_ast(&self, ast: &AST) -> Result<(), Box<EvalAltResult>> {
|
pub fn run_ast(&self, ast: &AST) -> Result<(), Box<EvalAltResult>> {
|
||||||
self.run_ast_with_scope(&mut Default::default(), ast)
|
self.run_ast_with_scope(&mut Scope::new(), ast)
|
||||||
}
|
}
|
||||||
/// Evaluate an [`AST`] with own scope, returning any error (if any).
|
/// Evaluate an [`AST`] with own scope, returning any error (if any).
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -1815,7 +1815,7 @@ impl Engine {
|
|||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
ast: &AST,
|
ast: &AST,
|
||||||
) -> Result<(), Box<EvalAltResult>> {
|
) -> Result<(), Box<EvalAltResult>> {
|
||||||
let mods = &mut Default::default();
|
let mods = &mut Imports::new();
|
||||||
let mut state = EvalState::new();
|
let mut state = EvalState::new();
|
||||||
state.source = ast.source_raw().cloned();
|
state.source = ast.source_raw().cloned();
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
@ -1989,7 +1989,7 @@ impl Engine {
|
|||||||
args: &mut FnCallArgs,
|
args: &mut FnCallArgs,
|
||||||
) -> RhaiResult {
|
) -> RhaiResult {
|
||||||
let state = &mut EvalState::new();
|
let state = &mut EvalState::new();
|
||||||
let mods = &mut Default::default();
|
let mods = &mut Imports::new();
|
||||||
let lib = &[ast.lib()];
|
let lib = &[ast.lib()];
|
||||||
let statements = ast.statements();
|
let statements = ast.statements();
|
||||||
|
|
||||||
@ -2059,7 +2059,7 @@ impl Engine {
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
#[cfg(feature = "no_function")]
|
#[cfg(feature = "no_function")]
|
||||||
let lib = Default::default();
|
let lib = StaticVec::new();
|
||||||
|
|
||||||
let stmt = std::mem::take(ast.statements_mut());
|
let stmt = std::mem::take(ast.statements_mut());
|
||||||
crate::optimize::optimize_into_ast(self, scope, stmt, lib, optimization_level)
|
crate::optimize::optimize_into_ast(self, scope, stmt, lib, optimization_level)
|
||||||
|
@ -33,13 +33,20 @@ pub type FnCallArgs<'a> = [&'a mut Dynamic];
|
|||||||
|
|
||||||
/// A type that temporarily stores a mutable reference to a `Dynamic`,
|
/// A type that temporarily stores a mutable reference to a `Dynamic`,
|
||||||
/// replacing it with a cloned copy.
|
/// replacing it with a cloned copy.
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug)]
|
||||||
struct ArgBackup<'a> {
|
struct ArgBackup<'a> {
|
||||||
orig_mut: Option<&'a mut Dynamic>,
|
orig_mut: Option<&'a mut Dynamic>,
|
||||||
value_copy: Dynamic,
|
value_copy: Dynamic,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ArgBackup<'a> {
|
impl<'a> ArgBackup<'a> {
|
||||||
|
/// Create a new `ArgBackup`.
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
orig_mut: None,
|
||||||
|
value_copy: Dynamic::UNIT,
|
||||||
|
}
|
||||||
|
}
|
||||||
/// This function replaces the first argument of a method call with a clone copy.
|
/// This function replaces the first argument of a method call with a clone copy.
|
||||||
/// This is to prevent a pure function unintentionally consuming the first argument.
|
/// This is to prevent a pure function unintentionally consuming the first argument.
|
||||||
///
|
///
|
||||||
@ -325,7 +332,7 @@ impl Engine {
|
|||||||
// Calling pure function but the first argument is a reference?
|
// Calling pure function but the first argument is a reference?
|
||||||
let mut backup: Option<ArgBackup> = None;
|
let mut backup: Option<ArgBackup> = None;
|
||||||
if is_method_call && func.is_pure() && !args.is_empty() {
|
if is_method_call && func.is_pure() && !args.is_empty() {
|
||||||
backup = Some(Default::default());
|
backup = Some(ArgBackup::new());
|
||||||
backup
|
backup
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.expect("`backup` is `Some`")
|
.expect("`backup` is `Some`")
|
||||||
@ -523,9 +530,6 @@ impl Engine {
|
|||||||
return Err(EvalAltResult::ErrorStackOverflow(pos).into());
|
return Err(EvalAltResult::ErrorStackOverflow(pos).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let orig_scope_level = state.scope_level;
|
|
||||||
state.scope_level += 1;
|
|
||||||
|
|
||||||
let prev_scope_len = scope.len();
|
let prev_scope_len = scope.len();
|
||||||
let prev_mods_len = mods.len();
|
let prev_mods_len = mods.len();
|
||||||
|
|
||||||
@ -593,7 +597,6 @@ impl Engine {
|
|||||||
// Remove all local variables
|
// Remove all local variables
|
||||||
scope.rewind(prev_scope_len);
|
scope.rewind(prev_scope_len);
|
||||||
mods.truncate(prev_mods_len);
|
mods.truncate(prev_mods_len);
|
||||||
state.scope_level = orig_scope_level;
|
|
||||||
|
|
||||||
if unified {
|
if unified {
|
||||||
state.pop_fn_resolution_cache();
|
state.pop_fn_resolution_cache();
|
||||||
@ -782,7 +785,7 @@ impl Engine {
|
|||||||
// The first argument is a reference?
|
// The first argument is a reference?
|
||||||
let mut backup: Option<ArgBackup> = None;
|
let mut backup: Option<ArgBackup> = None;
|
||||||
if is_ref_mut && !args.is_empty() {
|
if is_ref_mut && !args.is_empty() {
|
||||||
backup = Some(Default::default());
|
backup = Some(ArgBackup::new());
|
||||||
backup
|
backup
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.expect("`backup` is `Some`")
|
.expect("`backup` is `Some`")
|
||||||
@ -862,7 +865,7 @@ impl Engine {
|
|||||||
// Compile the script text
|
// Compile the script text
|
||||||
// No optimizations because we only run it once
|
// No optimizations because we only run it once
|
||||||
let ast = self.compile_with_scope_and_optimization_level(
|
let ast = self.compile_with_scope_and_optimization_level(
|
||||||
&Default::default(),
|
&Scope::new(),
|
||||||
&[script],
|
&[script],
|
||||||
#[cfg(not(feature = "no_optimize"))]
|
#[cfg(not(feature = "no_optimize"))]
|
||||||
crate::OptimizationLevel::None,
|
crate::OptimizationLevel::None,
|
||||||
@ -1352,7 +1355,7 @@ impl Engine {
|
|||||||
// func(x, ...) -> x.func(...)
|
// func(x, ...) -> x.func(...)
|
||||||
for index in 0..args_expr.len() {
|
for index in 0..args_expr.len() {
|
||||||
if index == 0 {
|
if index == 0 {
|
||||||
arg_values.push(Default::default());
|
arg_values.push(Dynamic::UNIT);
|
||||||
} else {
|
} else {
|
||||||
let (value, _) = self.get_arg_value(
|
let (value, _) = self.get_arg_value(
|
||||||
scope, mods, state, lib, this_ptr, level, args_expr, constants, index,
|
scope, mods, state, lib, this_ptr, level, args_expr, constants, index,
|
||||||
@ -1433,7 +1436,7 @@ impl Engine {
|
|||||||
if fn_def.body.is_empty() {
|
if fn_def.body.is_empty() {
|
||||||
Ok(Dynamic::UNIT)
|
Ok(Dynamic::UNIT)
|
||||||
} else {
|
} else {
|
||||||
let new_scope = &mut Default::default();
|
let new_scope = &mut Scope::new();
|
||||||
|
|
||||||
let mut source = module.id_raw().cloned();
|
let mut source = module.id_raw().cloned();
|
||||||
mem::swap(&mut state.source, &mut source);
|
mem::swap(&mut state.source, &mut source);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Module defining interfaces to native-Rust functions.
|
//! Module defining interfaces to native-Rust functions.
|
||||||
|
|
||||||
use crate::ast::{FnAccess, FnCallHashes};
|
use crate::ast::{FnAccess, FnCallHashes};
|
||||||
use crate::engine::Imports;
|
use crate::engine::{EvalState, Imports};
|
||||||
use crate::fn_call::FnCallArgs;
|
use crate::fn_call::FnCallArgs;
|
||||||
use crate::plugin::PluginFunction;
|
use crate::plugin::PluginFunction;
|
||||||
use crate::token::{Token, TokenizeState};
|
use crate::token::{Token, TokenizeState};
|
||||||
@ -89,18 +89,18 @@ impl<'a, M: AsRef<[&'a Module]> + ?Sized>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, M: AsRef<[&'a Module]> + ?Sized> From<(&'a Engine, &'a str, &'a M, Position)>
|
impl<'a, M: AsRef<[&'a Module]> + ?Sized> From<(&'a Engine, &'a str, &'a M)>
|
||||||
for NativeCallContext<'a>
|
for NativeCallContext<'a>
|
||||||
{
|
{
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(value: (&'a Engine, &'a str, &'a M, Position)) -> Self {
|
fn from(value: (&'a Engine, &'a str, &'a M)) -> Self {
|
||||||
Self {
|
Self {
|
||||||
engine: value.0,
|
engine: value.0,
|
||||||
fn_name: value.1,
|
fn_name: value.1,
|
||||||
source: None,
|
source: None,
|
||||||
mods: None,
|
mods: None,
|
||||||
lib: value.2.as_ref(),
|
lib: value.2.as_ref(),
|
||||||
pos: value.3,
|
pos: Position::NONE,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -109,19 +109,14 @@ impl<'a> NativeCallContext<'a> {
|
|||||||
/// Create a new [`NativeCallContext`].
|
/// Create a new [`NativeCallContext`].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn new(
|
pub const fn new(engine: &'a Engine, fn_name: &'a str, lib: &'a [&Module]) -> Self {
|
||||||
engine: &'a Engine,
|
|
||||||
fn_name: &'a str,
|
|
||||||
lib: &'a [&Module],
|
|
||||||
pos: Position,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
engine,
|
engine,
|
||||||
fn_name,
|
fn_name,
|
||||||
source: None,
|
source: None,
|
||||||
mods: None,
|
mods: None,
|
||||||
lib,
|
lib,
|
||||||
pos,
|
pos: Position::NONE,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// _(internals)_ Create a new [`NativeCallContext`].
|
/// _(internals)_ Create a new [`NativeCallContext`].
|
||||||
@ -247,8 +242,8 @@ impl<'a> NativeCallContext<'a> {
|
|||||||
|
|
||||||
self.engine()
|
self.engine()
|
||||||
.exec_fn_call(
|
.exec_fn_call(
|
||||||
&mut self.mods.cloned().unwrap_or_default(),
|
&mut self.mods.cloned().unwrap_or_else(|| Imports::new()),
|
||||||
&mut Default::default(),
|
&mut EvalState::new(),
|
||||||
self.lib,
|
self.lib,
|
||||||
fn_name,
|
fn_name,
|
||||||
hash,
|
hash,
|
||||||
|
@ -146,7 +146,7 @@ impl TryFrom<Identifier> for FnPtr {
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn try_from(value: Identifier) -> Result<Self, Self::Error> {
|
fn try_from(value: Identifier) -> Result<Self, Self::Error> {
|
||||||
if is_valid_identifier(value.chars()) {
|
if is_valid_identifier(value.chars()) {
|
||||||
Ok(Self(value, Default::default()))
|
Ok(Self(value, StaticVec::new()))
|
||||||
} else {
|
} else {
|
||||||
Err(EvalAltResult::ErrorFunctionNotFound(value.to_string(), Position::NONE).into())
|
Err(EvalAltResult::ErrorFunctionNotFound(value.to_string(), Position::NONE).into())
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,7 @@ macro_rules! def_register {
|
|||||||
#[inline(always)] fn into_callable_function(self) -> CallableFunction {
|
#[inline(always)] fn into_callable_function(self) -> CallableFunction {
|
||||||
CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| {
|
CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| {
|
||||||
if args.len() == 2 && args[0].is_read_only() && is_setter(ctx.fn_name()) {
|
if args.len() == 2 && args[0].is_read_only() && is_setter(ctx.fn_name()) {
|
||||||
return Err(EvalAltResult::ErrorAssignmentToConstant(Default::default(), Position::NONE).into());
|
return Err(EvalAltResult::ErrorAssignmentToConstant(String::new(), Position::NONE).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
// The arguments are assumed to be of the correct number and types!
|
// The arguments are assumed to be of the correct number and types!
|
||||||
@ -151,7 +151,7 @@ macro_rules! def_register {
|
|||||||
#[inline(always)] fn into_callable_function(self) -> CallableFunction {
|
#[inline(always)] fn into_callable_function(self) -> CallableFunction {
|
||||||
CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| {
|
CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| {
|
||||||
if args.len() == 2 && args[0].is_read_only() && is_setter(ctx.fn_name()) {
|
if args.len() == 2 && args[0].is_read_only() && is_setter(ctx.fn_name()) {
|
||||||
return Err(EvalAltResult::ErrorAssignmentToConstant(Default::default(), Position::NONE).into());
|
return Err(EvalAltResult::ErrorAssignmentToConstant(String::new(), Position::NONE).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
// The arguments are assumed to be of the correct number and types!
|
// The arguments are assumed to be of the correct number and types!
|
||||||
@ -179,7 +179,7 @@ macro_rules! def_register {
|
|||||||
#[inline(always)] fn into_callable_function(self) -> CallableFunction {
|
#[inline(always)] fn into_callable_function(self) -> CallableFunction {
|
||||||
CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| {
|
CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| {
|
||||||
if args.len() == 2 && args[0].is_read_only() && is_setter(ctx.fn_name()) {
|
if args.len() == 2 && args[0].is_read_only() && is_setter(ctx.fn_name()) {
|
||||||
return Err(EvalAltResult::ErrorAssignmentToConstant(Default::default(), Position::NONE).into());
|
return Err(EvalAltResult::ErrorAssignmentToConstant(String::new(), Position::NONE).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
// The arguments are assumed to be of the correct number and types!
|
// The arguments are assumed to be of the correct number and types!
|
||||||
@ -204,7 +204,7 @@ macro_rules! def_register {
|
|||||||
#[inline(always)] fn into_callable_function(self) -> CallableFunction {
|
#[inline(always)] fn into_callable_function(self) -> CallableFunction {
|
||||||
CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| {
|
CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| {
|
||||||
if args.len() == 2 && args[0].is_read_only() && is_setter(ctx.fn_name()) {
|
if args.len() == 2 && args[0].is_read_only() && is_setter(ctx.fn_name()) {
|
||||||
return Err(EvalAltResult::ErrorAssignmentToConstant(Default::default(), Position::NONE).into());
|
return Err(EvalAltResult::ErrorAssignmentToConstant(String::new(), Position::NONE).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
// The arguments are assumed to be of the correct number and types!
|
// The arguments are assumed to be of the correct number and types!
|
||||||
|
@ -37,13 +37,6 @@ pub enum FnNamespace {
|
|||||||
Internal,
|
Internal,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for FnNamespace {
|
|
||||||
#[inline(always)]
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::Internal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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 {
|
||||||
@ -249,16 +242,16 @@ impl Module {
|
|||||||
id: None,
|
id: None,
|
||||||
internal: false,
|
internal: false,
|
||||||
standard: false,
|
standard: false,
|
||||||
modules: Default::default(),
|
modules: BTreeMap::new(),
|
||||||
variables: Default::default(),
|
variables: BTreeMap::new(),
|
||||||
all_variables: Default::default(),
|
all_variables: BTreeMap::new(),
|
||||||
functions: Default::default(),
|
functions: BTreeMap::new(),
|
||||||
all_functions: Default::default(),
|
all_functions: BTreeMap::new(),
|
||||||
type_iterators: Default::default(),
|
type_iterators: BTreeMap::new(),
|
||||||
all_type_iterators: Default::default(),
|
all_type_iterators: BTreeMap::new(),
|
||||||
indexed: true,
|
indexed: true,
|
||||||
contains_indexed_global_functions: false,
|
contains_indexed_global_functions: false,
|
||||||
identifiers: Default::default(),
|
identifiers: IdentifierBuilder::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,7 +479,7 @@ impl Module {
|
|||||||
namespace: FnNamespace::Internal,
|
namespace: FnNamespace::Internal,
|
||||||
access: fn_def.access,
|
access: fn_def.access,
|
||||||
params: num_params,
|
params: num_params,
|
||||||
param_types: Default::default(),
|
param_types: StaticVec::new(),
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
param_names,
|
param_names,
|
||||||
func: Into::<CallableFunction>::into(fn_def).into(),
|
func: Into::<CallableFunction>::into(fn_def).into(),
|
||||||
@ -1565,9 +1558,9 @@ impl Module {
|
|||||||
|
|
||||||
if !self.indexed {
|
if !self.indexed {
|
||||||
let mut path = Vec::with_capacity(4);
|
let mut path = Vec::with_capacity(4);
|
||||||
let mut variables = Default::default();
|
let mut variables = BTreeMap::new();
|
||||||
let mut functions = Default::default();
|
let mut functions = BTreeMap::new();
|
||||||
let mut type_iterators = Default::default();
|
let mut type_iterators = BTreeMap::new();
|
||||||
|
|
||||||
path.push("");
|
path.push("");
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@ use std::prelude::v1::*;
|
|||||||
/// let mut engine = Engine::new();
|
/// let mut engine = Engine::new();
|
||||||
/// engine.set_module_resolver(collection);
|
/// engine.set_module_resolver(collection);
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Default)]
|
|
||||||
pub struct ModuleResolversCollection(Vec<Box<dyn ModuleResolver>>);
|
pub struct ModuleResolversCollection(Vec<Box<dyn ModuleResolver>>);
|
||||||
|
|
||||||
impl ModuleResolversCollection {
|
impl ModuleResolversCollection {
|
||||||
@ -43,7 +42,7 @@ impl ModuleResolversCollection {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Default::default()
|
Self(Vec::new())
|
||||||
}
|
}
|
||||||
/// Append a [module resolver][ModuleResolver] to the end.
|
/// Append a [module resolver][ModuleResolver] to the end.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{Engine, EvalAltResult, Identifier, Module, ModuleResolver, Position, Shared};
|
use crate::{Engine, EvalAltResult, Identifier, Module, ModuleResolver, Position, Scope, Shared};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
use std::{
|
use std::{
|
||||||
@ -51,13 +51,6 @@ pub struct FileModuleResolver {
|
|||||||
cache: std::sync::RwLock<BTreeMap<PathBuf, Shared<Module>>>,
|
cache: std::sync::RwLock<BTreeMap<PathBuf, Shared<Module>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for FileModuleResolver {
|
|
||||||
#[inline(always)]
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FileModuleResolver {
|
impl FileModuleResolver {
|
||||||
/// Create a new [`FileModuleResolver`] with the current directory as base path.
|
/// Create a new [`FileModuleResolver`] with the current directory as base path.
|
||||||
///
|
///
|
||||||
@ -301,7 +294,7 @@ impl ModuleResolver for FileModuleResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load the script file and compile it
|
// Load the script file and compile it
|
||||||
let scope = Default::default();
|
let scope = Scope::new();
|
||||||
|
|
||||||
let mut ast = engine
|
let mut ast = engine
|
||||||
.compile_file(file_path.clone())
|
.compile_file(file_path.clone())
|
||||||
|
@ -22,7 +22,7 @@ use std::{collections::BTreeMap, ops::AddAssign};
|
|||||||
///
|
///
|
||||||
/// engine.set_module_resolver(resolver);
|
/// engine.set_module_resolver(resolver);
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct StaticModuleResolver(BTreeMap<Identifier, Shared<Module>>);
|
pub struct StaticModuleResolver(BTreeMap<Identifier, Shared<Module>>);
|
||||||
|
|
||||||
impl StaticModuleResolver {
|
impl StaticModuleResolver {
|
||||||
@ -45,7 +45,7 @@ impl StaticModuleResolver {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Default::default()
|
Self(BTreeMap::new())
|
||||||
}
|
}
|
||||||
/// Add a [module][Module] keyed by its path.
|
/// Add a [module][Module] keyed by its path.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
use crate::ast::{Expr, OpAssignment, Stmt, AST_OPTION_FLAGS::*};
|
use crate::ast::{Expr, OpAssignment, Stmt, AST_OPTION_FLAGS::*};
|
||||||
use crate::dynamic::AccessMode;
|
use crate::dynamic::AccessMode;
|
||||||
use crate::engine::{KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_FN_PTR, KEYWORD_PRINT, KEYWORD_TYPE_OF};
|
use crate::engine::{
|
||||||
|
EvalState, Imports, KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_FN_PTR, KEYWORD_PRINT, KEYWORD_TYPE_OF,
|
||||||
|
};
|
||||||
use crate::fn_builtin::get_builtin_binary_op_fn;
|
use crate::fn_builtin::get_builtin_binary_op_fn;
|
||||||
use crate::fn_hash::get_hasher;
|
use crate::fn_hash::get_hasher;
|
||||||
use crate::token::Token;
|
use crate::token::Token;
|
||||||
@ -131,8 +133,8 @@ impl<'a> OptimizerState<'a> {
|
|||||||
) -> Option<Dynamic> {
|
) -> Option<Dynamic> {
|
||||||
self.engine
|
self.engine
|
||||||
.call_native_fn(
|
.call_native_fn(
|
||||||
&Default::default(),
|
&Imports::new(),
|
||||||
&mut Default::default(),
|
&mut EvalState::new(),
|
||||||
self.lib,
|
self.lib,
|
||||||
fn_name,
|
fn_name,
|
||||||
calc_fn_hash(fn_name, arg_values.len()),
|
calc_fn_hash(fn_name, arg_values.len()),
|
||||||
@ -959,7 +961,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) {
|
|||||||
state.set_dirty();
|
state.set_dirty();
|
||||||
let fn_ptr = FnPtr::new_unchecked(
|
let fn_ptr = FnPtr::new_unchecked(
|
||||||
fn_name.as_str_ref().expect("`fn_name` is `ImmutableString`").into(),
|
fn_name.as_str_ref().expect("`fn_name` is `ImmutableString`").into(),
|
||||||
Default::default()
|
StaticVec::new()
|
||||||
);
|
);
|
||||||
*expr = Expr::DynamicConstant(Box::new(fn_ptr.into()), *pos);
|
*expr = Expr::DynamicConstant(Box::new(fn_ptr.into()), *pos);
|
||||||
}
|
}
|
||||||
@ -1001,7 +1003,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) {
|
|||||||
_ if x.args.len() == 2 && !state.has_native_fn_override(x.hashes.native, arg_types.as_ref()) => {
|
_ if x.args.len() == 2 && !state.has_native_fn_override(x.hashes.native, arg_types.as_ref()) => {
|
||||||
if let Some(result) = get_builtin_binary_op_fn(x.name.as_ref(), &arg_values[0], &arg_values[1])
|
if let Some(result) = get_builtin_binary_op_fn(x.name.as_ref(), &arg_values[0], &arg_values[1])
|
||||||
.and_then(|f| {
|
.and_then(|f| {
|
||||||
let context = (state.engine, x.name.as_ref(), state.lib, Position::NONE).into();
|
let context = (state.engine, x.name.as_ref(), state.lib).into();
|
||||||
let (first, second) = arg_values.split_first_mut().expect("`arg_values` is not empty");
|
let (first, second) = arg_values.split_first_mut().expect("`arg_values` is not empty");
|
||||||
(f)(context, &mut [ first, &mut second[0] ]).ok()
|
(f)(context, &mut [ first, &mut second[0] ]).ok()
|
||||||
}) {
|
}) {
|
||||||
@ -1154,16 +1156,16 @@ pub fn optimize_into_ast(
|
|||||||
.map(|fn_def| crate::ast::ScriptFnDef {
|
.map(|fn_def| crate::ast::ScriptFnDef {
|
||||||
name: fn_def.name.clone(),
|
name: fn_def.name.clone(),
|
||||||
access: fn_def.access,
|
access: fn_def.access,
|
||||||
body: Default::default(),
|
body: crate::ast::StmtBlock::empty(),
|
||||||
params: fn_def.params.clone(),
|
params: fn_def.params.clone(),
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
externals: fn_def.externals.clone(),
|
externals: fn_def.externals.clone(),
|
||||||
lib: None,
|
lib: None,
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
mods: Default::default(),
|
mods: crate::engine::Imports::new(),
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
comments: Default::default(),
|
comments: StaticVec::new(),
|
||||||
})
|
})
|
||||||
.for_each(|fn_def| {
|
.for_each(|fn_def| {
|
||||||
lib2.set_script_fn(fn_def);
|
lib2.set_script_fn(fn_def);
|
||||||
@ -1198,7 +1200,7 @@ pub fn optimize_into_ast(
|
|||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "no_function")]
|
#[cfg(feature = "no_function")]
|
||||||
let lib = Default::default();
|
let lib = Module::new();
|
||||||
|
|
||||||
statements.shrink_to_fit();
|
statements.shrink_to_fit();
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ where
|
|||||||
if r == from {
|
if r == from {
|
||||||
return Err(EvalAltResult::ErrorInFunctionCall(
|
return Err(EvalAltResult::ErrorInFunctionCall(
|
||||||
"range".to_string(),
|
"range".to_string(),
|
||||||
Default::default(),
|
String::new(),
|
||||||
EvalAltResult::ErrorArithmetic(
|
EvalAltResult::ErrorArithmetic(
|
||||||
"step value cannot be zero".to_string(),
|
"step value cannot be zero".to_string(),
|
||||||
crate::Position::NONE,
|
crate::Position::NONE,
|
||||||
@ -201,7 +201,7 @@ struct CharsStream(Vec<char>, usize);
|
|||||||
impl CharsStream {
|
impl CharsStream {
|
||||||
pub fn new(string: &str, from: INT, len: INT) -> Self {
|
pub fn new(string: &str, from: INT, len: INT) -> Self {
|
||||||
if len <= 0 {
|
if len <= 0 {
|
||||||
return Self(Default::default(), 0);
|
return Self(Vec::new(), 0);
|
||||||
}
|
}
|
||||||
if from >= 0 {
|
if from >= 0 {
|
||||||
return Self(
|
return Self(
|
||||||
|
@ -60,8 +60,8 @@ mod print_debug_functions {
|
|||||||
ctx.engine().map_type_name(&format!("{:?}", item)).into()
|
ctx.engine().map_type_name(&format!("{:?}", item)).into()
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "print", name = "debug")]
|
#[rhai_fn(name = "print", name = "debug")]
|
||||||
pub fn print_empty_string() -> ImmutableString {
|
pub fn print_empty_string(ctx: NativeCallContext) -> ImmutableString {
|
||||||
Default::default()
|
ctx.engine().const_empty_string()
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "print", name = "to_string")]
|
#[rhai_fn(name = "print", name = "to_string")]
|
||||||
pub fn print_string(s: ImmutableString) -> ImmutableString {
|
pub fn print_string(s: ImmutableString) -> ImmutableString {
|
||||||
|
39
src/parse.rs
39
src/parse.rs
@ -50,12 +50,21 @@ const NEVER_ENDS: &str = "`TokenStream` never ends";
|
|||||||
/// When [`ImmutableString`] is used as [`Identifier`], this type acts as an interner which keeps a
|
/// When [`ImmutableString`] is used as [`Identifier`], this type acts as an interner which keeps a
|
||||||
/// collection of strings and returns shared instances, only creating a new string when it is not
|
/// collection of strings and returns shared instances, only creating a new string when it is not
|
||||||
/// yet interned.
|
/// yet interned.
|
||||||
#[derive(Debug, Clone, Default, Hash)]
|
#[derive(Debug, Clone, Hash)]
|
||||||
pub struct IdentifierBuilder(
|
pub struct IdentifierBuilder(
|
||||||
#[cfg(feature = "no_smartstring")] std::collections::BTreeSet<Identifier>,
|
#[cfg(feature = "no_smartstring")] std::collections::BTreeSet<Identifier>,
|
||||||
);
|
);
|
||||||
|
|
||||||
impl IdentifierBuilder {
|
impl IdentifierBuilder {
|
||||||
|
/// Create a new IdentifierBuilder.
|
||||||
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self(
|
||||||
|
#[cfg(feature = "no_smartstring")]
|
||||||
|
std::collections::BTreeSet::new(),
|
||||||
|
)
|
||||||
|
}
|
||||||
/// Get an identifier from a text string.
|
/// Get an identifier from a text string.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
@ -121,14 +130,14 @@ impl<'e> ParseState<'e> {
|
|||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
max_function_expr_depth: NonZeroUsize::new(engine.max_function_expr_depth()),
|
max_function_expr_depth: NonZeroUsize::new(engine.max_function_expr_depth()),
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
external_vars: Default::default(),
|
external_vars: BTreeMap::new(),
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
allow_capture: true,
|
allow_capture: true,
|
||||||
interned_strings: Default::default(),
|
interned_strings: IdentifierBuilder::new(),
|
||||||
stack: Default::default(),
|
stack: StaticVec::new(),
|
||||||
entry_stack_len: 0,
|
entry_stack_len: 0,
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
modules: Default::default(),
|
modules: StaticVec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -398,7 +407,7 @@ fn parse_symbol(input: &mut TokenStream) -> Result<(String, Position), ParseErro
|
|||||||
// Bad identifier
|
// Bad identifier
|
||||||
(Token::LexError(err), pos) => Err(err.into_err(pos)),
|
(Token::LexError(err), pos) => Err(err.into_err(pos)),
|
||||||
// Not a symbol
|
// Not a symbol
|
||||||
(_, pos) => Err(PERR::MissingSymbol(Default::default()).into_err(pos)),
|
(_, pos) => Err(PERR::MissingSymbol(String::new()).into_err(pos)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -902,7 +911,7 @@ fn parse_map_literal(
|
|||||||
|
|
||||||
let expr = parse_expr(input, state, lib, settings.level_up())?;
|
let expr = parse_expr(input, state, lib, settings.level_up())?;
|
||||||
let name = state.get_identifier(name);
|
let name = state.get_identifier(name);
|
||||||
template.insert(name.clone(), Default::default());
|
template.insert(name.clone(), crate::Dynamic::UNIT);
|
||||||
map.push((Ident { name, pos }, expr));
|
map.push((Ident { name, pos }, expr));
|
||||||
|
|
||||||
match input.peek().expect(NEVER_ENDS) {
|
match input.peek().expect(NEVER_ENDS) {
|
||||||
@ -2556,7 +2565,7 @@ fn parse_export(
|
|||||||
}
|
}
|
||||||
(name, pos)
|
(name, pos)
|
||||||
} else {
|
} else {
|
||||||
(Default::default(), Position::NONE)
|
(String::new(), Position::NONE)
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.push((
|
exports.push((
|
||||||
@ -3075,7 +3084,7 @@ fn parse_fn(
|
|||||||
body,
|
body,
|
||||||
lib: None,
|
lib: None,
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
mods: Default::default(),
|
mods: crate::engine::Imports::new(),
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
comments,
|
comments,
|
||||||
@ -3216,17 +3225,17 @@ fn parse_anon_fn(
|
|||||||
access: FnAccess::Public,
|
access: FnAccess::Public,
|
||||||
params,
|
params,
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
externals: Default::default(),
|
externals: std::collections::BTreeSet::new(),
|
||||||
body: body.into(),
|
body: body.into(),
|
||||||
lib: None,
|
lib: None,
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
mods: Default::default(),
|
mods: crate::engine::Imports::new(),
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
comments: Default::default(),
|
comments: StaticVec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let fn_ptr = crate::FnPtr::new_unchecked(fn_name, Default::default());
|
let fn_ptr = crate::FnPtr::new_unchecked(fn_name, StaticVec::new());
|
||||||
let expr = Expr::DynamicConstant(Box::new(fn_ptr.into()), settings.pos);
|
let expr = Expr::DynamicConstant(Box::new(fn_ptr.into()), settings.pos);
|
||||||
|
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
@ -3245,7 +3254,7 @@ impl Engine {
|
|||||||
#[cfg(not(feature = "no_optimize"))] optimization_level: crate::OptimizationLevel,
|
#[cfg(not(feature = "no_optimize"))] optimization_level: crate::OptimizationLevel,
|
||||||
) -> Result<AST, ParseError> {
|
) -> Result<AST, ParseError> {
|
||||||
let _scope = scope;
|
let _scope = scope;
|
||||||
let mut functions = Default::default();
|
let mut functions = BTreeMap::new();
|
||||||
|
|
||||||
let settings = ParseSettings {
|
let settings = ParseSettings {
|
||||||
allow_if_expr: false,
|
allow_if_expr: false,
|
||||||
@ -3278,7 +3287,7 @@ impl Engine {
|
|||||||
self,
|
self,
|
||||||
_scope,
|
_scope,
|
||||||
statements,
|
statements,
|
||||||
Default::default(),
|
StaticVec::new(),
|
||||||
optimization_level,
|
optimization_level,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -243,7 +243,7 @@ impl<'a> Scope<'a> {
|
|||||||
access: AccessMode,
|
access: AccessMode,
|
||||||
mut value: Dynamic,
|
mut value: Dynamic,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
self.names.push((name.into(), Default::default()));
|
self.names.push((name.into(), None));
|
||||||
value.set_access_mode(access);
|
value.set_access_mode(access);
|
||||||
self.values.push(value);
|
self.values.push(value);
|
||||||
self
|
self
|
||||||
@ -592,7 +592,7 @@ impl<'a, K: Into<Cow<'a, str>>> Extend<(K, Dynamic)> for Scope<'a> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn extend<T: IntoIterator<Item = (K, Dynamic)>>(&mut self, iter: T) {
|
fn extend<T: IntoIterator<Item = (K, Dynamic)>>(&mut self, iter: T) {
|
||||||
iter.into_iter().for_each(|(name, value)| {
|
iter.into_iter().for_each(|(name, value)| {
|
||||||
self.names.push((name.into(), Default::default()));
|
self.names.push((name.into(), None));
|
||||||
self.values.push(value);
|
self.values.push(value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ pub fn from_dynamic<'de, T: Deserialize<'de>>(
|
|||||||
|
|
||||||
impl Error for Box<EvalAltResult> {
|
impl Error for Box<EvalAltResult> {
|
||||||
fn custom<T: fmt::Display>(err: T) -> Self {
|
fn custom<T: fmt::Display>(err: T) -> Self {
|
||||||
LexError::ImproperSymbol(Default::default(), err.to_string())
|
LexError::ImproperSymbol(String::new(), err.to_string())
|
||||||
.into_err(Position::NONE)
|
.into_err(Position::NONE)
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
@ -168,7 +168,7 @@ impl From<&crate::module::FuncInfo> for FnMetadata {
|
|||||||
.to_vec()
|
.to_vec()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Default::default()
|
Vec::new()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -198,7 +198,7 @@ impl From<crate::ast::ScriptFnMetadata<'_>> for FnMetadata {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
struct ModuleMetadata {
|
struct ModuleMetadata {
|
||||||
#[serde(skip_serializing_if = "BTreeMap::is_empty")]
|
#[serde(skip_serializing_if = "BTreeMap::is_empty")]
|
||||||
@ -210,7 +210,10 @@ struct ModuleMetadata {
|
|||||||
impl ModuleMetadata {
|
impl ModuleMetadata {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Default::default()
|
Self {
|
||||||
|
modules: BTreeMap::new(),
|
||||||
|
functions: Vec::new(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,6 +284,6 @@ impl Engine {
|
|||||||
/// 2) Functions in static modules
|
/// 2) Functions in static modules
|
||||||
/// 3) Functions in global modules (optional)
|
/// 3) Functions in global modules (optional)
|
||||||
pub fn gen_fn_metadata_to_json(&self, include_global: bool) -> serde_json::Result<String> {
|
pub fn gen_fn_metadata_to_json(&self, include_global: bool) -> serde_json::Result<String> {
|
||||||
self.gen_fn_metadata_with_ast_to_json(&Default::default(), include_global)
|
self.gen_fn_metadata_with_ast_to_json(&AST::empty(), include_global)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ impl DynamicSerializer {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(_value: Dynamic) -> Self {
|
pub fn new(_value: Dynamic) -> Self {
|
||||||
Self {
|
Self {
|
||||||
_key: Default::default(),
|
_key: Dynamic::UNIT,
|
||||||
_value,
|
_value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -83,7 +83,7 @@ impl DynamicSerializer {
|
|||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn to_dynamic<T: Serialize>(value: T) -> RhaiResult {
|
pub fn to_dynamic<T: Serialize>(value: T) -> RhaiResult {
|
||||||
let mut s = DynamicSerializer::new(Default::default());
|
let mut s = DynamicSerializer::new(Dynamic::UNIT);
|
||||||
value.serialize(&mut s)
|
value.serialize(&mut s)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,7 +397,7 @@ impl Serializer for &mut DynamicSerializer {
|
|||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
return Ok(StructVariantSerializer {
|
return Ok(StructVariantSerializer {
|
||||||
variant: _variant,
|
variant: _variant,
|
||||||
map: Default::default(),
|
map: Map::new(),
|
||||||
});
|
});
|
||||||
#[cfg(feature = "no_object")]
|
#[cfg(feature = "no_object")]
|
||||||
return Err(EvalAltResult::ErrorMismatchDataType(
|
return Err(EvalAltResult::ErrorMismatchDataType(
|
||||||
|
15
src/token.rs
15
src/token.rs
@ -33,13 +33,24 @@ use crate::engine::KEYWORD_IS_DEF_FN;
|
|||||||
/// # Volatile Data Structure
|
/// # Volatile Data Structure
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Hash, Copy, Default)]
|
#[derive(Debug, Clone, Eq, PartialEq, Hash, Copy)]
|
||||||
pub struct TokenizerControlBlock {
|
pub struct TokenizerControlBlock {
|
||||||
/// Is the current tokenizer position within an interpolated text string?
|
/// Is the current tokenizer position within an interpolated text string?
|
||||||
/// This flag allows switching the tokenizer back to _text_ parsing after an interpolation stream.
|
/// This flag allows switching the tokenizer back to _text_ parsing after an interpolation stream.
|
||||||
pub is_within_text: bool,
|
pub is_within_text: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TokenizerControlBlock {
|
||||||
|
/// Create a new `TokenizerControlBlock`.
|
||||||
|
#[inline(always)]
|
||||||
|
#[must_use]
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
is_within_text: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// _(internals)_ A shared object that allows control of the tokenizer from outside.
|
/// _(internals)_ A shared object that allows control of the tokenizer from outside.
|
||||||
pub type TokenizerControl = Rc<Cell<TokenizerControlBlock>>;
|
pub type TokenizerControl = Rc<Cell<TokenizerControlBlock>>;
|
||||||
|
|
||||||
@ -2281,7 +2292,7 @@ impl Engine {
|
|||||||
input: impl IntoIterator<Item = &'a &'a str>,
|
input: impl IntoIterator<Item = &'a &'a str>,
|
||||||
token_mapper: Option<&'a OnParseTokenCallback>,
|
token_mapper: Option<&'a OnParseTokenCallback>,
|
||||||
) -> (TokenIterator<'a>, TokenizerControl) {
|
) -> (TokenIterator<'a>, TokenizerControl) {
|
||||||
let buffer: TokenizerControl = Default::default();
|
let buffer: TokenizerControl = Cell::new(TokenizerControlBlock::new()).into();
|
||||||
let buffer2 = buffer.clone();
|
let buffer2 = buffer.clone();
|
||||||
|
|
||||||
(
|
(
|
||||||
|
@ -338,7 +338,7 @@ fn test_closures_external() -> Result<(), Box<EvalAltResult>> {
|
|||||||
|
|
||||||
// Create native call context
|
// Create native call context
|
||||||
let fn_name = fn_ptr.fn_name().to_string();
|
let fn_name = fn_ptr.fn_name().to_string();
|
||||||
let context = NativeCallContext::new(&engine, &fn_name, &lib, rhai::Position::NONE);
|
let context = NativeCallContext::new(&engine, &fn_name, &lib);
|
||||||
|
|
||||||
// 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(&context, None, [x.into()]);
|
let f = move |x: INT| fn_ptr.call_dynamic(&context, None, [x.into()]);
|
||||||
|
@ -196,7 +196,7 @@ fn test_custom_syntax_raw() -> Result<(), Box<EvalAltResult>> {
|
|||||||
2 => match stream[1].as_str() {
|
2 => match stream[1].as_str() {
|
||||||
"world" => Ok(Some("$$hello".into())),
|
"world" => Ok(Some("$$hello".into())),
|
||||||
"kitty" => Ok(None),
|
"kitty" => Ok(None),
|
||||||
s => Err(LexError::ImproperSymbol(s.to_string(), Default::default())
|
s => Err(LexError::ImproperSymbol(s.to_string(), String::new())
|
||||||
.into_err(Position::NONE)
|
.into_err(Position::NONE)
|
||||||
.into()),
|
.into()),
|
||||||
},
|
},
|
||||||
|
@ -59,7 +59,7 @@ fn test_expressions_eval() -> Result<(), Box<EvalAltResult>> {
|
|||||||
engine.register_get("gender", AGENT::get_gender);
|
engine.register_get("gender", AGENT::get_gender);
|
||||||
engine.register_get("age", AGENT::get_age);
|
engine.register_get("age", AGENT::get_age);
|
||||||
|
|
||||||
// Create your context, add the agent as a constant
|
// Create your scope, add the agent as a constant
|
||||||
let mut scope = Scope::new();
|
let mut scope = Scope::new();
|
||||||
scope.push_constant("agent", my_agent);
|
scope.push_constant("agent", my_agent);
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#![cfg(not(feature = "no_function"))]
|
#![cfg(not(feature = "no_function"))]
|
||||||
use rhai::{Engine, EvalAltResult, FnNamespace, Module, Shared, INT};
|
use rhai::{Engine, EvalAltResult, FnNamespace, Module, NativeCallContext, Shared, INT};
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
#[test]
|
#[test]
|
||||||
@ -43,7 +43,35 @@ fn test_functions_trait_object() -> Result<(), Box<EvalAltResult>> {
|
|||||||
fn test_functions_namespaces() -> Result<(), Box<EvalAltResult>> {
|
fn test_functions_namespaces() -> Result<(), Box<EvalAltResult>> {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
|
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
|
{
|
||||||
|
let mut m = Module::new();
|
||||||
|
let hash = m.set_native_fn("test", || Ok(999 as INT));
|
||||||
|
m.update_fn_namespace(hash, FnNamespace::Global);
|
||||||
|
|
||||||
|
engine.register_static_module("hello", m.into());
|
||||||
|
|
||||||
|
let mut m = Module::new();
|
||||||
|
m.set_var("ANSWER", 123 as INT);
|
||||||
|
|
||||||
|
assert_eq!(engine.eval::<INT>("test()")?, 999);
|
||||||
|
|
||||||
|
assert_eq!(engine.eval::<INT>("fn test() { 123 } test()")?, 123);
|
||||||
|
}
|
||||||
|
|
||||||
|
engine.register_fn("test", || 42 as INT);
|
||||||
|
|
||||||
|
assert_eq!(engine.eval::<INT>("fn test() { 123 } test()")?, 123);
|
||||||
|
|
||||||
|
assert_eq!(engine.eval::<INT>("test()")?, 42);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_functions_global_module() -> Result<(), Box<EvalAltResult>> {
|
||||||
|
let mut engine = Engine::new();
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
{
|
{
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -56,43 +84,28 @@ fn test_functions_namespaces() -> Result<(), Box<EvalAltResult>> {
|
|||||||
)?,
|
)?,
|
||||||
42
|
42
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
assert!(matches!(*engine.run("
|
||||||
|
fn foo() { global::ANSWER }
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut m = Module::new();
|
const ANSWER = 42;
|
||||||
let hash = m.set_native_fn("test", || Ok(999 as INT));
|
foo()
|
||||||
m.update_fn_namespace(hash, FnNamespace::Global);
|
|
||||||
|
|
||||||
engine.register_static_module("hello", m.into());
|
|
||||||
|
|
||||||
let mut m = Module::new();
|
|
||||||
m.set_var("ANSWER", 123 as INT);
|
|
||||||
|
|
||||||
engine.register_static_module("global", m.into());
|
|
||||||
|
|
||||||
assert_eq!(engine.eval::<INT>("test()")?, 999);
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_function"))]
|
|
||||||
assert_eq!(engine.eval::<INT>("fn test() { 123 } test()")?, 123);
|
|
||||||
}
|
}
|
||||||
|
").expect_err("should error"),
|
||||||
|
EvalAltResult::ErrorInFunctionCall(_, _, err, _)
|
||||||
|
if matches!(&*err, EvalAltResult::ErrorVariableNotFound(v, _) if v == "global::ANSWER")
|
||||||
|
));
|
||||||
|
|
||||||
engine.register_fn("test", || 42 as INT);
|
let mut module = Module::new();
|
||||||
|
module.set_var("ANSWER", 123 as INT);
|
||||||
assert_eq!(engine.eval::<INT>("test()")?, 42);
|
engine.register_static_module("global", module.into());
|
||||||
|
|
||||||
#[cfg(not(feature = "no_function"))]
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
{
|
|
||||||
assert_eq!(engine.eval::<INT>("fn test() { 123 } test()")?, 123);
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
engine.eval::<INT>(
|
engine.eval::<INT>(
|
||||||
"
|
"
|
||||||
const ANSWER = 42;
|
const ANSWER = 42;
|
||||||
|
|
||||||
fn foo() { global::ANSWER }
|
fn foo() { global::ANSWER }
|
||||||
|
|
||||||
foo()
|
foo()
|
||||||
"
|
"
|
||||||
)?,
|
)?,
|
||||||
@ -100,5 +113,23 @@ fn test_functions_namespaces() -> Result<(), Box<EvalAltResult>> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
engine.register_result_fn(
|
||||||
|
"do_stuff",
|
||||||
|
|context: NativeCallContext, callback: rhai::FnPtr| {
|
||||||
|
callback.call_dynamic(&context, None, [])
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_closure"))]
|
||||||
|
assert!(matches!(*engine.run("
|
||||||
|
do_stuff(|| {
|
||||||
|
const LOCAL_VALUE = 42;
|
||||||
|
global::LOCAL_VALUE
|
||||||
|
});
|
||||||
|
").expect_err("should error"),
|
||||||
|
EvalAltResult::ErrorInFunctionCall(_, _, err, _)
|
||||||
|
if matches!(&*err, EvalAltResult::ErrorVariableNotFound(v, _) if v == "global::LOCAL_VALUE")
|
||||||
|
));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -444,7 +444,7 @@ fn test_module_ast_namespace() -> Result<(), Box<EvalAltResult>> {
|
|||||||
|
|
||||||
let ast = engine.compile(script)?;
|
let ast = engine.compile(script)?;
|
||||||
|
|
||||||
let module = Module::eval_ast_as_new(Default::default(), &ast, &engine)?;
|
let module = Module::eval_ast_as_new(Scope::new(), &ast, &engine)?;
|
||||||
|
|
||||||
let mut resolver = StaticModuleResolver::new();
|
let mut resolver = StaticModuleResolver::new();
|
||||||
resolver.insert("testing", module);
|
resolver.insert("testing", module);
|
||||||
@ -512,6 +512,6 @@ fn test_module_file() -> Result<(), Box<EvalAltResult>> {
|
|||||||
print("top");
|
print("top");
|
||||||
"#,
|
"#,
|
||||||
)?;
|
)?;
|
||||||
Module::eval_ast_as_new(Default::default(), &ast, &engine)?;
|
Module::eval_ast_as_new(Scope::new(), &ast, &engine)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user