Use namespace for ScriptFnDef.

This commit is contained in:
Stephen Chung 2021-03-07 22:10:54 +08:00
parent e87f981674
commit 330d3f87af
12 changed files with 106 additions and 108 deletions

View File

@ -89,6 +89,7 @@ impl fmt::Display for ScriptFnDef {
/// A type containing the metadata of a script-defined function. /// A type containing the metadata of a script-defined function.
/// ///
/// Created by [`AST::iter_functions`]. /// Created by [`AST::iter_functions`].
#[cfg(not(feature = "no_function"))]
#[derive(Debug, Eq, PartialEq, Clone, Hash)] #[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub struct ScriptFnMetadata<'a> { pub struct ScriptFnMetadata<'a> {
/// Function doc-comments (if any). /// Function doc-comments (if any).
@ -108,6 +109,7 @@ pub struct ScriptFnMetadata<'a> {
pub params: Vec<&'a str>, pub params: Vec<&'a str>,
} }
#[cfg(not(feature = "no_function"))]
impl fmt::Display for ScriptFnMetadata<'_> { impl fmt::Display for ScriptFnMetadata<'_> {
#[inline(always)] #[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@ -124,6 +126,7 @@ impl fmt::Display for ScriptFnMetadata<'_> {
} }
} }
#[cfg(not(feature = "no_function"))]
impl<'a> Into<ScriptFnMetadata<'a>> for &'a ScriptFnDef { impl<'a> Into<ScriptFnMetadata<'a>> for &'a ScriptFnDef {
#[inline(always)] #[inline(always)]
fn into(self) -> ScriptFnMetadata<'a> { fn into(self) -> ScriptFnMetadata<'a> {

View File

@ -1212,7 +1212,7 @@ impl Dynamic {
}, },
) )
} }
_ => unreachable!("self should be Shared"), _ => unreachable!(),
}, },
_ => (), _ => (),
} }
@ -1684,6 +1684,16 @@ impl<T: Variant + Clone> From<&[T]> for Dynamic {
)) ))
} }
} }
#[cfg(not(feature = "no_index"))]
impl<T: Variant + Clone> crate::stdlib::iter::FromIterator<T> for Dynamic {
#[inline(always)]
fn from_iter<X: IntoIterator<Item = T>>(iter: X) -> Self {
Self(Union::Array(
Box::new(iter.into_iter().map(Dynamic::from).collect()),
AccessMode::ReadWrite,
))
}
}
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
impl<K: Into<ImmutableString>, T: Variant + Clone> From<crate::stdlib::collections::HashMap<K, T>> impl<K: Into<ImmutableString>, T: Variant + Clone> From<crate::stdlib::collections::HashMap<K, T>>
for Dynamic for Dynamic

View File

@ -108,6 +108,7 @@ impl Imports {
self.0.iter().rev().map(|(n, m)| (n, m)) self.0.iter().rev().map(|(n, m)| (n, m))
} }
/// Get an iterator to this stack of imported [modules][Module] in forward order. /// Get an iterator to this stack of imported [modules][Module] in forward order.
#[allow(dead_code)]
#[inline(always)] #[inline(always)]
pub(crate) fn scan_raw(&self) -> impl Iterator<Item = (&ImmutableString, &Shared<Module>)> { pub(crate) fn scan_raw(&self) -> impl Iterator<Item = (&ImmutableString, &Shared<Module>)> {
self.0.iter().map(|(n, m)| (n, m)) self.0.iter().map(|(n, m)| (n, m))
@ -405,8 +406,8 @@ impl<'a> Target<'a> {
Self::LockGuard((r, _)) => **r = new_val, Self::LockGuard((r, _)) => **r = new_val,
Self::Value(_) => panic!("cannot update a value"), Self::Value(_) => panic!("cannot update a value"),
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
Self::StringChar(s, index, _) if s.is::<ImmutableString>() => { Self::StringChar(s, index, _) => {
let mut s = s.write_lock::<ImmutableString>().unwrap(); let s = &mut *s.write_lock::<ImmutableString>().unwrap();
// Replace the character at the specified index position // Replace the character at the specified index position
let new_ch = new_val.as_char().map_err(|err| { let new_ch = new_val.as_char().map_err(|err| {
@ -417,20 +418,15 @@ impl<'a> Target<'a> {
)) ))
})?; })?;
let mut chars = s.chars().collect::<StaticVec<_>>(); let index = *index;
// See if changed - if so, update the String *s = s
if chars[*index] != new_ch { .chars()
chars[*index] = new_ch; .enumerate()
*s = chars.iter().collect::<String>().into(); .map(|(i, ch)| if i == index { new_ch } else { ch })
.collect();
} }
} }
#[cfg(not(feature = "no_index"))]
Self::StringChar(s, _, _) => unreachable!(
"Target::StringChar should contain only a string, not {}",
s.type_name()
),
}
Ok(()) Ok(())
} }
@ -543,6 +539,7 @@ impl State {
self.fn_resolution_caches.last_mut().unwrap() self.fn_resolution_caches.last_mut().unwrap()
} }
/// Push an empty functions resolution cache onto the stack and make it current. /// Push an empty functions resolution cache onto the stack and make it current.
#[allow(dead_code)]
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(Default::default());
} }
@ -550,14 +547,6 @@ impl State {
pub fn pop_fn_resolution_cache(&mut self) { pub fn pop_fn_resolution_cache(&mut self) {
self.fn_resolution_caches.pop(); self.fn_resolution_caches.pop();
} }
/// Clear the current functions resolution cache.
///
/// # Panics
///
/// Panics if there is no current functions resolution cache.
pub fn clear_fn_resolution_cache(&mut self) {
self.fn_resolution_caches.last_mut().unwrap().clear();
}
} }
/// _(INTERNALS)_ A type containing all the limits imposed by the [`Engine`]. /// _(INTERNALS)_ A type containing all the limits imposed by the [`Engine`].
@ -1066,9 +1055,7 @@ impl Engine {
level: usize, level: usize,
new_val: Option<((Dynamic, Position), (&str, Position))>, new_val: Option<((Dynamic, Position), (&str, Position))>,
) -> Result<(Dynamic, bool), Box<EvalAltResult>> { ) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
if chain_type == ChainType::NonChaining { assert!(chain_type != ChainType::NonChaining);
unreachable!("should not be ChainType::NonChaining");
}
let is_ref = target.is_ref(); let is_ref = target.is_ref();
@ -1875,7 +1862,7 @@ impl Engine {
restore_prev_state: bool, restore_prev_state: bool,
level: usize, level: usize,
) -> RhaiResult { ) -> RhaiResult {
let mut _restore_fn_resolution_cache = false; let mut _extra_fn_resolution_cache = false;
let prev_always_search = state.always_search; let prev_always_search = state.always_search;
let prev_scope_len = scope.len(); let prev_scope_len = scope.len();
let prev_mods_len = mods.len(); let prev_mods_len = mods.len();
@ -1898,15 +1885,18 @@ impl Engine {
.skip(_mods_len) .skip(_mods_len)
.any(|(_, m)| m.contains_indexed_global_functions()) .any(|(_, m)| m.contains_indexed_global_functions())
{ {
if _restore_fn_resolution_cache { if _extra_fn_resolution_cache {
// When new module is imported with global functions and there is already // When new module is imported with global functions and there is already
// a new cache, clear it - notice that this is expensive as all function // a new cache, clear it - notice that this is expensive as all function
// resolutions must start again // resolutions must start again
state.clear_fn_resolution_cache(); state.fn_resolution_cache_mut().clear();
} else if restore_prev_state { } else if restore_prev_state {
// When new module is imported with global functions, push a new cache // When new module is imported with global functions, push a new cache
state.push_fn_resolution_cache(); state.push_fn_resolution_cache();
_restore_fn_resolution_cache = true; _extra_fn_resolution_cache = true;
} else {
// When the block is to be evaluated in-place, just clear the current cache
state.fn_resolution_cache_mut().clear();
} }
} }
} }
@ -1914,12 +1904,13 @@ impl Engine {
Ok(r) Ok(r)
}); });
if restore_prev_state { if _extra_fn_resolution_cache {
scope.rewind(prev_scope_len);
if _restore_fn_resolution_cache {
// If imports list is modified, pop the functions lookup cache // If imports list is modified, pop the functions lookup cache
state.pop_fn_resolution_cache(); state.pop_fn_resolution_cache();
} }
if restore_prev_state {
scope.rewind(prev_scope_len);
mods.truncate(prev_mods_len); mods.truncate(prev_mods_len);
state.scope_level -= 1; state.scope_level -= 1;

View File

@ -28,7 +28,7 @@ use crate::{
}; };
use crate::{ use crate::{
calc_native_fn_hash, calc_script_fn_hash, Dynamic, Engine, EvalAltResult, FnPtr, calc_native_fn_hash, calc_script_fn_hash, Dynamic, Engine, EvalAltResult, FnPtr,
ImmutableString, Module, ParseErrorType, Position, Scope, StaticVec, INT, ImmutableString, Module, ParseErrorType, Position, Scope, StaticVec,
}; };
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
@ -649,7 +649,7 @@ impl Engine {
state: &mut State, state: &mut State,
lib: &[&Module], lib: &[&Module],
fn_name: &str, fn_name: &str,
hash_script: Option<NonZeroU64>, _hash_script: Option<NonZeroU64>,
args: &mut FnCallArgs, args: &mut FnCallArgs,
is_ref: bool, is_ref: bool,
_is_method: bool, _is_method: bool,
@ -675,7 +675,7 @@ impl Engine {
// Handle is_def_fn() // Handle is_def_fn()
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
crate::engine::KEYWORD_IS_DEF_FN crate::engine::KEYWORD_IS_DEF_FN
if args.len() == 2 && args[0].is::<FnPtr>() && args[1].is::<INT>() => if args.len() == 2 && args[0].is::<FnPtr>() && args[1].is::<crate::INT>() =>
{ {
let fn_name = args[0].read_lock::<ImmutableString>().unwrap(); let fn_name = args[0].read_lock::<ImmutableString>().unwrap();
let num_params = args[1].as_int().unwrap(); let num_params = args[1].as_int().unwrap();
@ -732,7 +732,7 @@ impl Engine {
} }
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
if let Some((func, source)) = hash_script.and_then(|hash| { if let Some((func, source)) = _hash_script.and_then(|hash| {
self.resolve_function(mods, state, lib, fn_name, hash, args, false, false) self.resolve_function(mods, state, lib, fn_name, hash, args, false, false)
.as_ref() .as_ref()
.map(|(f, s)| (f.clone(), s.clone())) .map(|(f, s)| (f.clone(), s.clone()))
@ -1139,7 +1139,7 @@ impl Engine {
.eval_expr(scope, mods, state, lib, this_ptr, &args_expr[1], level)? .eval_expr(scope, mods, state, lib, this_ptr, &args_expr[1], level)?
.as_int() .as_int()
.map_err(|err| { .map_err(|err| {
self.make_type_mismatch_err::<INT>(err, args_expr[0].position()) self.make_type_mismatch_err::<crate::INT>(err, args_expr[0].position())
})?; })?;
return Ok(if num_params < 0 { return Ok(if num_params < 0 {

View File

@ -1,6 +1,6 @@
//! Module defining interfaces to native-Rust functions. //! Module defining interfaces to native-Rust functions.
use crate::ast::{FnAccess, ScriptFnDef}; use crate::ast::FnAccess;
use crate::engine::Imports; use crate::engine::Imports;
use crate::plugin::PluginFunction; use crate::plugin::PluginFunction;
use crate::stdlib::{ use crate::stdlib::{
@ -143,6 +143,7 @@ impl<'a> NativeCallContext<'a> {
} }
/// Get an iterator over the current set of modules imported via `import` statements. /// Get an iterator over the current set of modules imported via `import` statements.
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
#[allow(dead_code)]
#[inline(always)] #[inline(always)]
pub(crate) fn iter_imports_raw( pub(crate) fn iter_imports_raw(
&self, &self,
@ -438,7 +439,7 @@ pub enum CallableFunction {
Plugin(Shared<FnPlugin>), Plugin(Shared<FnPlugin>),
/// A script-defined function. /// A script-defined function.
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
Script(Shared<ScriptFnDef>), Script(Shared<crate::ast::ScriptFnDef>),
} }
impl fmt::Debug for CallableFunction { impl fmt::Debug for CallableFunction {
@ -576,7 +577,7 @@ impl CallableFunction {
/// Panics if the [`CallableFunction`] is not [`Script`][CallableFunction::Script]. /// Panics if the [`CallableFunction`] is not [`Script`][CallableFunction::Script].
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
#[inline(always)] #[inline(always)]
pub fn get_fn_def(&self) -> &ScriptFnDef { pub fn get_fn_def(&self) -> &crate::ast::ScriptFnDef {
match self { match self {
Self::Pure(_) | Self::Method(_) | Self::Iterator(_) | Self::Plugin(_) => { Self::Pure(_) | Self::Method(_) | Self::Iterator(_) | Self::Plugin(_) => {
panic!("function should be scripted") panic!("function should be scripted")
@ -642,24 +643,18 @@ impl From<IteratorFn> for CallableFunction {
} }
} }
impl From<ScriptFnDef> for CallableFunction { #[cfg(not(feature = "no_function"))]
impl From<crate::ast::ScriptFnDef> for CallableFunction {
#[inline(always)] #[inline(always)]
fn from(_func: ScriptFnDef) -> Self { fn from(_func: crate::ast::ScriptFnDef) -> Self {
#[cfg(feature = "no_function")]
unreachable!("no_function active");
#[cfg(not(feature = "no_function"))]
Self::Script(_func.into()) Self::Script(_func.into())
} }
} }
impl From<Shared<ScriptFnDef>> for CallableFunction { #[cfg(not(feature = "no_function"))]
impl From<Shared<crate::ast::ScriptFnDef>> for CallableFunction {
#[inline(always)] #[inline(always)]
fn from(_func: Shared<ScriptFnDef>) -> Self { fn from(_func: Shared<crate::ast::ScriptFnDef>) -> Self {
#[cfg(feature = "no_function")]
unreachable!("no_function active");
#[cfg(not(feature = "no_function"))]
Self::Script(_func) Self::Script(_func)
} }
} }

View File

@ -131,8 +131,7 @@ macro_rules! make_func {
// The arguments are assumed to be of the correct number and types! // The arguments are assumed to be of the correct number and types!
let mut _drain = args.iter_mut(); let mut _drain = args.iter_mut();
$($let)* $($let $par = ($convert)(_drain.next().unwrap()); )*
$($par = ($convert)(_drain.next().unwrap()); )*
// Call the function with each argument value // Call the function with each argument value
let r = $fn($($arg),*); let r = $fn($($arg),*);
@ -216,8 +215,8 @@ macro_rules! def_register {
($p0:ident $(, $p:ident)*) => { ($p0:ident $(, $p:ident)*) => {
def_register!(imp from_pure : $p0 => $p0 => $p0 => $p0 => let $p0 => by_value $(, $p => $p => $p => $p => let $p => by_value)*); def_register!(imp from_pure : $p0 => $p0 => $p0 => $p0 => let $p0 => by_value $(, $p => $p => $p => $p => let $p => by_value)*);
def_register!(imp from_method : $p0 => &mut $p0 => Mut<$p0> => &mut $p0 => let mut $p0 => by_ref $(, $p => $p => $p => $p => let $p => by_value)*); def_register!(imp from_method : $p0 => &mut $p0 => Mut<$p0> => &mut $p0 => let mut $p0 => by_ref $(, $p => $p => $p => $p => let $p => by_value)*);
// ^ CallableFunction // ^ CallableFunction constructor
// handle the first parameter ^ first parameter passed through // ^ first parameter passed through
// ^ others passed by value (by_value) // ^ others passed by value (by_value)
// Currently does not support first argument which is a reference, as there will be // Currently does not support first argument which is a reference, as there will be

View File

@ -122,7 +122,7 @@ pub type FLOAT = f64;
#[cfg(feature = "f32_float")] #[cfg(feature = "f32_float")]
pub type FLOAT = f32; pub type FLOAT = f32;
pub use ast::{FnAccess, ScriptFnMetadata, AST}; pub use ast::{FnAccess, AST};
pub use dynamic::Dynamic; pub use dynamic::Dynamic;
pub use engine::{Engine, EvalContext}; pub use engine::{Engine, EvalContext};
pub use fn_native::{FnPtr, NativeCallContext}; pub use fn_native::{FnPtr, NativeCallContext};
@ -155,6 +155,9 @@ pub use fn_func::Func;
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
pub use fn_args::FuncArgs; pub use fn_args::FuncArgs;
#[cfg(not(feature = "no_function"))]
pub use ast::ScriptFnMetadata;
/// Variable-sized array of [`Dynamic`] values. /// Variable-sized array of [`Dynamic`] values.
/// ///
/// Not available under `no_index`. /// Not available under `no_index`.

View File

@ -22,9 +22,6 @@ use crate::{
Dynamic, EvalAltResult, ImmutableString, NativeCallContext, Position, Shared, StaticVec, Dynamic, EvalAltResult, ImmutableString, NativeCallContext, Position, Shared, StaticVec,
}; };
#[cfg(not(feature = "no_function"))]
use crate::ast::ScriptFnDef;
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
use crate::Array; use crate::Array;
@ -460,7 +457,10 @@ impl Module {
/// If there is an existing function of the same name and number of arguments, it is replaced. /// If there is an existing function of the same name and number of arguments, it is replaced.
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
#[inline] #[inline]
pub(crate) fn set_script_fn(&mut self, fn_def: impl Into<Shared<ScriptFnDef>>) -> NonZeroU64 { pub(crate) fn set_script_fn(
&mut self,
fn_def: impl Into<Shared<crate::ast::ScriptFnDef>>,
) -> NonZeroU64 {
let fn_def = fn_def.into(); let fn_def = fn_def.into();
// None + function name + number of arguments. // None + function name + number of arguments.
@ -493,7 +493,7 @@ impl Module {
name: &str, name: &str,
num_params: usize, num_params: usize,
public_only: bool, public_only: bool,
) -> Option<&ScriptFnDef> { ) -> Option<&crate::ast::ScriptFnDef> {
self.functions self.functions
.values() .values()
.find( .find(
@ -1692,7 +1692,8 @@ impl Module {
#[inline(always)] #[inline(always)]
pub(crate) fn iter_script_fn( pub(crate) fn iter_script_fn(
&self, &self,
) -> impl Iterator<Item = (FnNamespace, FnAccess, &str, usize, &ScriptFnDef)> + '_ { ) -> impl Iterator<Item = (FnNamespace, FnAccess, &str, usize, &crate::ast::ScriptFnDef)> + '_
{
self.functions.values().filter(|f| f.func.is_script()).map( self.functions.values().filter(|f| f.func.is_script()).map(
|FuncInfo { |FuncInfo {
namespace, namespace,
@ -1751,7 +1752,7 @@ impl Module {
#[inline(always)] #[inline(always)]
pub fn iter_script_fn_info( pub fn iter_script_fn_info(
&self, &self,
) -> impl Iterator<Item = (FnNamespace, FnAccess, &str, usize, &ScriptFnDef)> { ) -> impl Iterator<Item = (FnNamespace, FnAccess, &str, usize, &crate::ast::ScriptFnDef)> {
self.iter_script_fn() self.iter_script_fn()
} }

View File

@ -1,6 +1,6 @@
//! Module implementing the [`AST`] optimizer. //! Module implementing the [`AST`] optimizer.
use crate::ast::{Expr, ScriptFnDef, Stmt}; use crate::ast::{Expr, Stmt};
use crate::dynamic::AccessMode; use crate::dynamic::AccessMode;
use crate::engine::{KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_PRINT, KEYWORD_TYPE_OF}; use crate::engine::{KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_PRINT, KEYWORD_TYPE_OF};
use crate::fn_builtin::get_builtin_binary_op_fn; use crate::fn_builtin::get_builtin_binary_op_fn;
@ -872,7 +872,7 @@ pub fn optimize_into_ast(
engine: &Engine, engine: &Engine,
scope: &Scope, scope: &Scope,
mut statements: Vec<Stmt>, mut statements: Vec<Stmt>,
_functions: Vec<ScriptFnDef>, _functions: Vec<crate::ast::ScriptFnDef>,
level: OptimizationLevel, level: OptimizationLevel,
) -> AST { ) -> AST {
let level = if cfg!(feature = "no_optimize") { let level = if cfg!(feature = "no_optimize") {
@ -891,7 +891,7 @@ pub fn optimize_into_ast(
_functions _functions
.iter() .iter()
.map(|fn_def| 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: Default::default(),

View File

@ -1,11 +1,6 @@
use crate::plugin::*; use crate::plugin::*;
use crate::{def_package, FnPtr, ImmutableString, NativeCallContext}; use crate::{def_package, FnPtr, ImmutableString, NativeCallContext};
#[cfg(not(feature = "no_function"))]
#[cfg(not(feature = "no_index"))]
#[cfg(not(feature = "no_object"))]
use crate::{ast::ScriptFnDef, stdlib::collections::HashMap, Array, Map};
def_package!(crate:BasicFnPackage:"Basic Fn functions.", lib, { def_package!(crate:BasicFnPackage:"Basic Fn functions.", lib, {
combine_with_exported_module!(lib, "FnPtr", fn_ptr_functions); combine_with_exported_module!(lib, "FnPtr", fn_ptr_functions);
}); });
@ -29,7 +24,7 @@ mod fn_ptr_functions {
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
pub mod functions_and_maps { pub mod functions_and_maps {
pub fn get_fn_metadata_list(ctx: NativeCallContext) -> Array { pub fn get_fn_metadata_list(ctx: NativeCallContext) -> crate::Array {
collect_fn_metadata(ctx) collect_fn_metadata(ctx)
} }
} }
@ -38,7 +33,9 @@ mod fn_ptr_functions {
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
fn collect_fn_metadata(ctx: NativeCallContext) -> Array { fn collect_fn_metadata(ctx: NativeCallContext) -> crate::Array {
use crate::{ast::ScriptFnDef, stdlib::collections::HashMap, Array, Map};
// Create a metadata record for a function. // Create a metadata record for a function.
fn make_metadata( fn make_metadata(
dict: &HashMap<&str, ImmutableString>, dict: &HashMap<&str, ImmutableString>,
@ -76,22 +73,6 @@ fn collect_fn_metadata(ctx: NativeCallContext) -> Array {
map.into() map.into()
} }
// Recursively scan modules for script-defined functions.
fn scan_module(
list: &mut Array,
dict: &HashMap<&str, ImmutableString>,
namespace: ImmutableString,
module: &Module,
) {
module.iter_script_fn().for_each(|(_, _, _, _, f)| {
list.push(make_metadata(dict, Some(namespace.clone()), f).into())
});
module.iter_sub_modules().for_each(|(ns, m)| {
let ns: ImmutableString = format!("{}::{}", namespace, ns).into();
scan_module(list, dict, ns, m.as_ref())
});
}
// Intern strings // Intern strings
let mut dict = HashMap::<&str, ImmutableString>::with_capacity(8); let mut dict = HashMap::<&str, ImmutableString>::with_capacity(8);
[ [
@ -115,8 +96,26 @@ fn collect_fn_metadata(ctx: NativeCallContext) -> Array {
.for_each(|(_, _, _, _, f)| list.push(make_metadata(&dict, None, f).into())); .for_each(|(_, _, _, _, f)| list.push(make_metadata(&dict, None, f).into()));
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
{
// Recursively scan modules for script-defined functions.
fn scan_module(
list: &mut Array,
dict: &HashMap<&str, ImmutableString>,
namespace: ImmutableString,
module: &Module,
) {
module.iter_script_fn().for_each(|(_, _, _, _, f)| {
list.push(make_metadata(dict, Some(namespace.clone()), f).into())
});
module.iter_sub_modules().for_each(|(ns, m)| {
let ns: ImmutableString = format!("{}::{}", namespace, ns).into();
scan_module(list, dict, ns, m.as_ref())
});
}
ctx.iter_imports_raw() ctx.iter_imports_raw()
.for_each(|(ns, m)| scan_module(&mut list, &dict, ns.clone(), m.as_ref())); .for_each(|(ns, m)| scan_module(&mut list, &dict, ns.clone(), m.as_ref()));
}
list list
} }

View File

@ -948,7 +948,7 @@ fn parse_primary(
} }
Token::True => Expr::BoolConstant(true, settings.pos), Token::True => Expr::BoolConstant(true, settings.pos),
Token::False => Expr::BoolConstant(false, settings.pos), Token::False => Expr::BoolConstant(false, settings.pos),
t => unreachable!("unexpected token: {:?}", t), _ => unreachable!(),
}, },
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
Token::FloatConstant(x) => { Token::FloatConstant(x) => {
@ -1033,7 +1033,7 @@ fn parse_primary(
Token::Identifier(_) => { Token::Identifier(_) => {
let s = match input.next().unwrap().0 { let s = match input.next().unwrap().0 {
Token::Identifier(s) => s, Token::Identifier(s) => s,
t => unreachable!("expecting Token::Identifier, but gets {:?}", t), _ => unreachable!(),
}; };
match input.peek().unwrap().0 { match input.peek().unwrap().0 {
@ -1080,7 +1080,7 @@ fn parse_primary(
Token::Reserved(_) => { Token::Reserved(_) => {
let s = match input.next().unwrap().0 { let s = match input.next().unwrap().0 {
Token::Reserved(s) => s, Token::Reserved(s) => s,
t => unreachable!("expecting Token::Reserved, but gets {:?}", t), _ => unreachable!(),
}; };
match input.peek().unwrap().0 { match input.peek().unwrap().0 {
@ -1115,7 +1115,7 @@ fn parse_primary(
Token::LexError(_) => { Token::LexError(_) => {
let err = match input.next().unwrap().0 { let err = match input.next().unwrap().0 {
Token::LexError(err) => err, Token::LexError(err) => err,
t => unreachable!("expecting Token::LexError, but gets {:?}", t), _ => unreachable!(),
}; };
return Err(err.into_err(settings.pos)); return Err(err.into_err(settings.pos));
@ -2126,7 +2126,7 @@ fn parse_while_loop(
(Some(expr), pos) (Some(expr), pos)
} }
(Token::Loop, pos) => (None, pos), (Token::Loop, pos) => (None, pos),
(t, _) => unreachable!("expecting Token::While or Token::Loop, but gets {:?}", t), _ => unreachable!(),
}; };
settings.pos = token_pos; settings.pos = token_pos;
@ -2544,7 +2544,7 @@ fn parse_stmt(
_ => return Err(PERR::WrongDocComment.into_err(comments_pos)), _ => return Err(PERR::WrongDocComment.into_err(comments_pos)),
} }
} }
t => unreachable!("expecting Token::Comment, but gets {:?}", t), _ => unreachable!(),
} }
} }
} }
@ -2651,10 +2651,7 @@ fn parse_stmt(
match token { match token {
Token::Return => ReturnType::Return, Token::Return => ReturnType::Return,
Token::Throw => ReturnType::Exception, Token::Throw => ReturnType::Exception,
t => unreachable!( _ => unreachable!(),
"expecting Token::Return or Token::Throw, but gets {:?}",
t
),
}, },
pos, pos,
) )

View File

@ -480,7 +480,7 @@ impl Token {
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
As => "as", As => "as",
EOF => "{EOF}", EOF => "{EOF}",
_ => unreachable!("operator should be matched in outer scope"), t => unreachable!("operator should be matched in outer scope: {:?}", t),
} }
.into(), .into(),
} }
@ -892,7 +892,7 @@ pub fn parse_string_literal(
'x' => 2, 'x' => 2,
'u' => 4, 'u' => 4,
'U' => 8, 'U' => 8,
_ => unreachable!("expecting 'x', 'u' or 'U', but gets {}", ch), _ => unreachable!(),
}; };
for _ in 0..len { for _ in 0..len {
@ -1190,14 +1190,14 @@ fn get_next_token_inner(
'x' | 'X' => is_hex_digit, 'x' | 'X' => is_hex_digit,
'o' | 'O' => is_numeric_digit, 'o' | 'O' => is_numeric_digit,
'b' | 'B' => is_numeric_digit, 'b' | 'B' => is_numeric_digit,
_ => unreachable!("expecting 'x', 'o' or 'b', but gets {}", ch), _ => unreachable!(),
}; };
radix_base = Some(match ch { radix_base = Some(match ch {
'x' | 'X' => 16, 'x' | 'X' => 16,
'o' | 'O' => 8, 'o' | 'O' => 8,
'b' | 'B' => 2, 'b' | 'B' => 2,
_ => unreachable!("expecting 'x', 'o' or 'b', but gets {}", ch), _ => unreachable!(),
}); });
} }