Use bitflags.

This commit is contained in:
Stephen Chung 2022-11-23 11:36:30 +08:00
parent d911327242
commit 4e27039521
33 changed files with 294 additions and 259 deletions

View File

@ -313,7 +313,7 @@ impl Parse for ExportedFn {
}
}
let skip_slots = if pass_context { 1 } else { 0 };
let skip_slots = usize::from(pass_context);
// Determine whether function generates a special calling convention for a mutable receiver.
let mut_receiver = match fn_all.sig.inputs.iter().nth(skip_slots) {
@ -485,12 +485,12 @@ impl ExportedFn {
}
pub fn arg_list(&self) -> impl Iterator<Item = &syn::FnArg> {
let skip = if self.pass_context { 1 } else { 0 };
let skip = usize::from(self.pass_context);
self.signature.inputs.iter().skip(skip)
}
pub fn arg_count(&self) -> usize {
let skip = if self.pass_context { 1 } else { 0 };
let skip = usize::from(self.pass_context);
self.signature.inputs.len() - skip
}

View File

@ -8,7 +8,7 @@ pub fn main() {
#[cfg(not(feature = "no_function"))]
#[cfg(not(feature = "no_object"))]
pub fn main() {
use rhai::{CallFnOptions, Dynamic, Engine, ImmutableString, Map, Scope, AST};
use rhai::{CallFnOptions, Dynamic, Engine, Map, Scope, AST};
use std::io::{stdin, stdout, Write};
const SCRIPT_FILE: &str = "event_handler_js/script.rhai";

View File

@ -2,7 +2,7 @@
#![cfg(feature = "internals")]
#![cfg(feature = "metadata")]
use crate::module::FuncInfo;
use crate::module::{FuncInfo, ModuleFlags};
use crate::tokenizer::{is_valid_function_name, Token};
use crate::{Engine, FnAccess, FnPtr, Module, Scope, INT};
@ -308,10 +308,16 @@ impl Definitions<'_> {
String::new()
};
let exclude_flags = if !self.config.include_standard_packages {
ModuleFlags::STANDARD_LIB
} else {
ModuleFlags::empty()
};
self.engine
.global_modules
.iter()
.filter(|m| self.config.include_standard_packages || !m.standard)
.filter(|m| !m.flags.contains(exclude_flags))
.enumerate()
.for_each(|(i, m)| {
if i > 0 {

View File

@ -1,7 +1,7 @@
//! Module that defines JSON manipulation functions for [`Engine`].
#![cfg(not(feature = "no_object"))]
use crate::parser::ParseState;
use crate::parser::{ParseSettingFlags, ParseState};
use crate::tokenizer::Token;
use crate::{Engine, LexError, Map, OptimizationLevel, RhaiResultOf, Scope};
#[cfg(feature = "no_std")]
@ -122,7 +122,7 @@ impl Engine {
let ast = self.parse_global_expr(
&mut stream.peekable(),
&mut state,
|s| s.allow_unquoted_map_properties = false,
|s| s.flags |= ParseSettingFlags::DISALLOW_UNQUOTED_MAP_PROPERTIES,
#[cfg(not(feature = "no_optimize"))]
OptimizationLevel::None,
#[cfg(feature = "no_optimize")]

View File

@ -1,6 +1,7 @@
//! Module that defines the public function/module registration API of [`Engine`].
use crate::func::{FnCallArgs, RegisterNativeFunction, SendSync};
use crate::module::ModuleFlags;
use crate::types::dynamic::Variant;
use crate::{
Engine, FnAccess, FnNamespace, Identifier, Module, NativeCallContext, RhaiResultOf, Shared,
@ -741,11 +742,17 @@ impl Engine {
signatures.extend(m.gen_fn_signatures().map(|f| format!("{name}::{f}")));
}
let exclude_flags = if !include_packages {
ModuleFlags::INTERNAL | ModuleFlags::STANDARD_LIB
} else {
ModuleFlags::INTERNAL
};
signatures.extend(
self.global_modules
.iter()
.skip(1)
.filter(|m| !m.internal && (include_packages || !m.standard))
.filter(|m| !m.flags.contains(exclude_flags))
.flat_map(|m| m.gen_fn_signatures()),
);

View File

@ -5,6 +5,7 @@ use crate::func::native::{
locked_write, OnDebugCallback, OnDefVarCallback, OnParseTokenCallback, OnPrintCallback,
OnVarCallback,
};
use crate::module::ModuleFlags;
use crate::packages::{Package, StandardPackage};
use crate::tokenizer::Token;
use crate::types::StringsInterner;
@ -303,7 +304,7 @@ impl Engine {
// Add the global namespace module
let mut global_namespace = Module::with_capacity(0);
global_namespace.internal = true;
global_namespace.flags |= ModuleFlags::INTERNAL;
engine.global_modules.push(global_namespace.into());
engine

View File

@ -764,6 +764,8 @@ impl Engine {
// Import statement
#[cfg(not(feature = "no_module"))]
Stmt::Import(x, _pos) => {
use crate::ModuleResolver;
let (expr, export) = &**x;
// Guard against too many modules
@ -777,8 +779,6 @@ impl Engine {
self.make_type_mismatch_err::<crate::ImmutableString>(typ, expr.position())
})?;
use crate::ModuleResolver;
let path_pos = expr.start_position();
let resolver = global.embedded_module_resolver.clone();

View File

@ -53,8 +53,7 @@ pub fn calc_index<E>(
negative_count_from_end: bool,
err_func: impl FnOnce() -> Result<usize, E>,
) -> Result<usize, E> {
if start < 0 {
if negative_count_from_end {
if start < 0 && negative_count_from_end {
let abs_start = start.unsigned_abs() as usize;
// Count from end if negative
@ -62,7 +61,6 @@ pub fn calc_index<E>(
return Ok(length - abs_start);
}
}
}
if start <= crate::MAX_USIZE_INT && (start as usize) < length {
return Ok(start as usize);
}

View File

@ -529,25 +529,21 @@ pub fn get_builtin_binary_op_fn(op: &Token, x: &Dynamic, y: &Dynamic) -> Option<
}
// Handle ranges here because ranges are implemented as custom type
if type1 == TypeId::of::<ExclusiveRange>() {
if type1 == type2 {
if type1 == TypeId::of::<ExclusiveRange>() && type1 == type2 {
return match op {
EqualsTo => Some(impl_op!(ExclusiveRange == ExclusiveRange)),
NotEqualsTo => Some(impl_op!(ExclusiveRange != ExclusiveRange)),
_ => None,
};
}
}
if type1 == TypeId::of::<InclusiveRange>() {
if type1 == type2 {
if type1 == TypeId::of::<InclusiveRange>() && type1 == type2 {
return match op {
EqualsTo => Some(impl_op!(InclusiveRange == InclusiveRange)),
NotEqualsTo => Some(impl_op!(InclusiveRange != InclusiveRange)),
_ => None,
};
}
}
// One of the operands is a custom type, so it is never built-in
if x.is_variant() || y.is_variant() {

View File

@ -58,11 +58,11 @@
#![cfg_attr(feature = "no_std", no_std)]
#![deny(missing_docs)]
// #![warn(clippy::all)]
// #![warn(clippy::pedantic)]
// #![warn(clippy::nursery)]
// #![warn(clippy::cargo)]
// #![warn(clippy::undocumented_unsafe_blocks)]
#![warn(clippy::all)]
#![warn(clippy::pedantic)]
#![warn(clippy::nursery)]
#![warn(clippy::cargo)]
#![warn(clippy::undocumented_unsafe_blocks)]
#![allow(clippy::unit_arg)]
#![allow(clippy::missing_errors_doc)]
#![allow(clippy::used_underscore_binding)]

View File

@ -5,13 +5,14 @@ use crate::api::type_names::format_type;
use crate::ast::FnAccess;
use crate::func::{
shared_take_or_clone, CallableFunction, FnCallArgs, IteratorFn, RegisterNativeFunction,
SendSync,
SendSync, StraightHashMap,
};
use crate::types::{dynamic::Variant, BloomFilterU64, CustomTypesCollection};
use crate::{
calc_fn_hash, calc_fn_hash_full, Dynamic, Identifier, ImmutableString, NativeCallContext,
RhaiResultOf, Shared, SharedModule, SmartString, StaticVec,
};
use bitflags::bitflags;
#[cfg(feature = "no_std")]
use std::prelude::v1::*;
use std::{
@ -24,8 +25,6 @@ use std::{
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
use crate::func::register::Mut;
use crate::func::StraightHashMap;
/// A type representing the namespace of a function.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[cfg_attr(feature = "metadata", derive(serde::Serialize))]
@ -94,44 +93,44 @@ impl FuncInfo {
#[cfg(feature = "metadata")]
#[must_use]
pub fn gen_signature(&self) -> String {
let mut sig = format!("{}(", self.name);
let mut signature = format!("{}(", self.name);
let return_type = format_type(&self.return_type, true);
if self.params_info.is_empty() {
for x in 0..self.num_params {
sig.push('_');
signature.push('_');
if x < self.num_params - 1 {
sig.push_str(", ");
signature.push_str(", ");
}
}
} else {
let params: StaticVec<_> = self
.params_info
.iter()
.map(|s| {
let mut seg = s.splitn(2, ':');
let name = match seg.next().unwrap().trim() {
.map(|param| {
let mut segment = param.splitn(2, ':');
let name = match segment.next().unwrap().trim() {
"" => "_",
s => s,
};
let result: std::borrow::Cow<str> = match seg.next() {
let result: std::borrow::Cow<str> = match segment.next() {
Some(typ) => format!("{name}: {}", format_type(typ, false)).into(),
None => name.into(),
};
result
})
.collect();
sig.push_str(&params.join(", "));
signature.push_str(&params.join(", "));
}
sig.push(')');
signature.push(')');
if !self.func.is_script() && !return_type.is_empty() {
sig.push_str(" -> ");
sig.push_str(&return_type);
signature.push_str(" -> ");
signature.push_str(&return_type);
}
sig
signature
}
}
@ -156,6 +155,20 @@ pub fn calc_native_fn_hash<'a>(
)
}
bitflags! {
/// Bit-flags containing all status for [`Module`].
pub struct ModuleFlags: u8 {
/// Is the [`Module`] internal?
const INTERNAL = 0b0000_0001;
/// Is the [`Module`] part of a standard library?
const STANDARD_LIB = 0b0000_0010;
/// Is the [`Module`] indexed?
const INDEXED = 0b0000_0100;
/// Does the [`Module`] contain indexed functions that have been exposed to the global namespace?
const INDEXED_GLOBAL_FUNCTIONS = 0b0000_1000;
}
}
/// A module which may contain variables, sub-modules, external Rust functions,
/// and/or script-defined functions.
#[derive(Clone)]
@ -165,10 +178,6 @@ pub struct Module {
/// Module documentation.
#[cfg(feature = "metadata")]
doc: crate::SmartString,
/// Is this module internal?
pub(crate) internal: bool,
/// Is this module part of a standard library?
pub(crate) standard: bool,
/// Custom types.
custom_types: Option<CustomTypesCollection>,
/// Sub-modules.
@ -188,10 +197,8 @@ pub struct Module {
type_iterators: Option<BTreeMap<TypeId, Shared<IteratorFn>>>,
/// Flattened collection of iterator functions, including those in sub-modules.
all_type_iterators: Option<BTreeMap<TypeId, Shared<IteratorFn>>>,
/// Is the [`Module`] indexed?
indexed: bool,
/// Does the [`Module`] contain indexed functions that have been exposed to the global namespace?
contains_indexed_global_functions: bool,
/// Flags.
pub(crate) flags: ModuleFlags,
}
impl Default for Module {
@ -295,8 +302,6 @@ impl Module {
id: None,
#[cfg(feature = "metadata")]
doc: crate::SmartString::new_const(),
internal: false,
standard: false,
custom_types: None,
modules: None,
variables: None,
@ -306,8 +311,7 @@ impl Module {
dynamic_functions_filter: BloomFilterU64::new(),
type_iterators: None,
all_type_iterators: None,
indexed: true,
contains_indexed_global_functions: false,
flags: ModuleFlags::empty(),
}
}
@ -437,11 +441,8 @@ impl Module {
/// Clear the [`Module`].
#[inline(always)]
pub fn clear(&mut self) {
self.id = None;
#[cfg(feature = "metadata")]
self.doc.clear();
self.internal = false;
self.standard = false;
self.custom_types = None;
self.modules = None;
self.variables = None;
@ -451,8 +452,7 @@ impl Module {
self.dynamic_functions_filter.clear();
self.type_iterators = None;
self.all_type_iterators = None;
self.indexed = false;
self.contains_indexed_global_functions = false;
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
}
/// Map a custom type to a friendly display name.
@ -543,7 +543,7 @@ impl Module {
#[inline]
#[must_use]
pub fn is_empty(&self) -> bool {
!self.contains_indexed_global_functions
!self.flags.contains(ModuleFlags::INDEXED_GLOBAL_FUNCTIONS)
&& self.functions.is_empty()
&& self.variables.as_ref().map_or(true, |m| m.is_empty())
&& self.modules.as_ref().map_or(true, |m| m.is_empty())
@ -579,7 +579,7 @@ impl Module {
#[inline(always)]
#[must_use]
pub const fn is_indexed(&self) -> bool {
self.indexed
self.flags.contains(ModuleFlags::INDEXED)
}
/// _(metadata)_ Generate signatures for all the non-private functions in the [`Module`].
@ -666,7 +666,7 @@ impl Module {
let ident = name.into();
let value = Dynamic::from(value);
if self.indexed {
if self.is_indexed() {
let hash_var = crate::calc_var_hash(Some(""), &ident);
self.all_variables
.get_or_insert_with(|| Default::default())
@ -717,8 +717,7 @@ impl Module {
func: fn_def.into(),
},
);
self.indexed = false;
self.contains_indexed_global_functions = false;
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
hash_script
}
@ -759,8 +758,7 @@ impl Module {
self.all_functions = None;
self.all_variables = None;
self.all_type_iterators = None;
self.indexed = false;
self.contains_indexed_global_functions = false;
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
self.modules.get_or_insert_with(|| Default::default())
}
@ -826,8 +824,7 @@ impl Module {
self.modules
.get_or_insert_with(|| Default::default())
.insert(name.into(), sub_module.into());
self.indexed = false;
self.contains_indexed_global_functions = false;
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
self
}
@ -942,8 +939,7 @@ impl Module {
pub fn update_fn_namespace(&mut self, hash_fn: u64, namespace: FnNamespace) -> &mut Self {
if let Some(f) = self.functions.get_mut(&hash_fn) {
f.namespace = namespace;
self.indexed = false;
self.contains_indexed_global_functions = false;
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
}
self
}
@ -1051,8 +1047,7 @@ impl Module {
},
);
self.indexed = false;
self.contains_indexed_global_functions = false;
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
hash_fn
}
@ -1607,8 +1602,7 @@ impl Module {
self.all_functions = None;
self.all_variables = None;
self.all_type_iterators = None;
self.indexed = false;
self.contains_indexed_global_functions = false;
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
#[cfg(feature = "metadata")]
if !other.doc.is_empty() {
@ -1650,8 +1644,7 @@ impl Module {
self.all_functions = None;
self.all_variables = None;
self.all_type_iterators = None;
self.indexed = false;
self.contains_indexed_global_functions = false;
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
#[cfg(feature = "metadata")]
if !other.doc.is_empty() {
@ -1702,8 +1695,7 @@ impl Module {
self.all_functions = None;
self.all_variables = None;
self.all_type_iterators = None;
self.indexed = false;
self.contains_indexed_global_functions = false;
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
#[cfg(feature = "metadata")]
if !other.doc.is_empty() {
@ -1775,8 +1767,7 @@ impl Module {
self.all_functions = None;
self.all_variables = None;
self.all_type_iterators = None;
self.indexed = false;
self.contains_indexed_global_functions = false;
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
#[cfg(feature = "metadata")]
if !other.doc.is_empty() {
@ -1811,8 +1802,7 @@ impl Module {
self.all_functions = None;
self.all_variables = None;
self.all_type_iterators = None;
self.indexed = false;
self.contains_indexed_global_functions = false;
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
self
}
@ -2108,7 +2098,7 @@ impl Module {
#[inline(always)]
#[must_use]
pub fn contains_indexed_global_functions(&self) -> bool {
self.contains_indexed_global_functions
self.flags.contains(ModuleFlags::INDEXED_GLOBAL_FUNCTIONS)
}
/// Scan through all the sub-modules in the [`Module`] and build a hash index of all
@ -2181,7 +2171,7 @@ impl Module {
contains_indexed_global_functions
}
if !self.indexed {
if !self.is_indexed() {
let mut path = Vec::with_capacity(4);
let mut variables = StraightHashMap::default();
let mut functions = StraightHashMap::default();
@ -2189,7 +2179,7 @@ impl Module {
path.push("");
self.contains_indexed_global_functions = index_module(
let r = index_module(
self,
&mut path,
&mut variables,
@ -2197,6 +2187,10 @@ impl Module {
&mut type_iterators,
);
if r {
self.flags |= ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
}
self.all_variables = if variables.is_empty() {
None
} else {
@ -2213,7 +2207,7 @@ impl Module {
Some(type_iterators)
};
self.indexed = true;
self.flags |= ModuleFlags::INDEXED;
}
self
@ -2257,7 +2251,7 @@ impl Module {
func: impl Fn(Dynamic) -> Box<dyn Iterator<Item = RhaiResultOf<Dynamic>>> + SendSync + 'static,
) -> &mut Self {
let func = Shared::new(func);
if self.indexed {
if self.is_indexed() {
self.all_type_iterators
.get_or_insert_with(|| Default::default())
.insert(type_id, func.clone());

View File

@ -8,6 +8,7 @@ use crate::engine::{KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_FN_PTR, KEYWORD_PRINT,
use crate::eval::{Caches, GlobalRuntimeState};
use crate::func::builtin::get_builtin_binary_op_fn;
use crate::func::hashing::get_hasher;
use crate::module::ModuleFlags;
use crate::tokenizer::Token;
use crate::types::dynamic::AccessMode;
use crate::{
@ -168,7 +169,7 @@ fn has_native_fn_override(
if engine
.global_modules
.iter()
.filter(|m| !m.standard)
.filter(|m| !m.flags.contains(ModuleFlags::STANDARD_LIB))
.any(|m| m.contains_fn(hash))
{
return true;

View File

@ -1,5 +1,6 @@
#![allow(non_snake_case)]
use crate::module::ModuleFlags;
use crate::plugin::*;
use crate::{def_package, Position, RhaiError, RhaiResultOf, ERR, INT};
#[cfg(feature = "no_std")]
@ -192,7 +193,7 @@ macro_rules! reg_functions {
def_package! {
/// Basic arithmetic package.
pub ArithmeticPackage(lib) {
lib.standard = true;
lib.flags |= ModuleFlags::STANDARD_LIB;
combine_with_exported_module!(lib, "int", int_functions);
reg_functions!(lib += signed_basic; INT);

View File

@ -2,6 +2,7 @@
use crate::engine::OP_EQUALS;
use crate::eval::{calc_index, calc_offset_len};
use crate::module::ModuleFlags;
use crate::plugin::*;
use crate::{
def_package, Array, Dynamic, ExclusiveRange, FnPtr, InclusiveRange, NativeCallContext,
@ -14,7 +15,7 @@ use std::{any::TypeId, cmp::Ordering, mem};
def_package! {
/// Package of basic array utilities.
pub BasicArrayPackage(lib) {
lib.standard = true;
lib.flags |= ModuleFlags::STANDARD_LIB;
combine_with_exported_module!(lib, "array", array_functions);

View File

@ -1,4 +1,5 @@
use crate::eval::calc_index;
use crate::module::ModuleFlags;
use crate::plugin::*;
use crate::{
def_package, ExclusiveRange, InclusiveRange, Position, RhaiResultOf, ERR, INT, INT_BITS,
@ -10,7 +11,7 @@ use std::prelude::v1::*;
def_package! {
/// Package of basic bit-field utilities.
pub BitFieldPackage(lib) {
lib.standard = true;
lib.flags |= ModuleFlags::STANDARD_LIB;
combine_with_exported_module!(lib, "bit_field", bit_field_functions);
}

View File

@ -1,6 +1,7 @@
#![cfg(not(feature = "no_index"))]
use crate::eval::{calc_index, calc_offset_len};
use crate::module::ModuleFlags;
use crate::plugin::*;
use crate::{
def_package, Array, Blob, Dynamic, ExclusiveRange, InclusiveRange, NativeCallContext, Position,
@ -16,7 +17,7 @@ use crate::{FLOAT, FLOAT_BYTES};
def_package! {
/// Package of basic BLOB utilities.
pub BasicBlobPackage(lib) {
lib.standard = true;
lib.flags |= ModuleFlags::STANDARD_LIB;
combine_with_exported_module!(lib, "blob", blob_functions);
combine_with_exported_module!(lib, "parse_int", parse_int_functions);

View File

@ -1,6 +1,7 @@
#![cfg(feature = "debugging")]
use crate::def_package;
use crate::module::ModuleFlags;
use crate::plugin::*;
#[cfg(feature = "no_std")]
use std::prelude::v1::*;
@ -17,7 +18,7 @@ use crate::Map;
def_package! {
/// Package of basic debugging utilities.
pub DebuggingPackage(lib) {
lib.standard = true;
lib.flags |= ModuleFlags::STANDARD_LIB;
combine_with_exported_module!(lib, "debugging", debugging_functions);
}

View File

@ -1,3 +1,4 @@
use crate::module::ModuleFlags;
use crate::plugin::*;
use crate::{def_package, FnPtr, ImmutableString, NativeCallContext};
#[cfg(feature = "no_std")]
@ -6,7 +7,7 @@ use std::prelude::v1::*;
def_package! {
/// Package of basic function pointer utilities.
pub BasicFnPackage(lib) {
lib.standard = true;
lib.flags |= ModuleFlags::STANDARD_LIB;
combine_with_exported_module!(lib, "FnPtr", fn_ptr_functions);
}

View File

@ -1,4 +1,5 @@
use crate::eval::calc_index;
use crate::module::ModuleFlags;
use crate::plugin::*;
use crate::{
def_package, ExclusiveRange, InclusiveRange, RhaiResultOf, INT, INT_BITS, MAX_USIZE_INT,
@ -329,7 +330,7 @@ macro_rules! reg_range {
def_package! {
/// Package of basic range iterators
pub BasicIteratorPackage(lib) {
lib.standard = true;
lib.flags |= ModuleFlags::STANDARD_LIB;
reg_range!(lib | "range" => INT);

View File

@ -1,4 +1,5 @@
use crate::def_package;
use crate::module::ModuleFlags;
use crate::plugin::*;
use crate::types::dynamic::Tag;
use crate::{Dynamic, RhaiResultOf, ERR, INT};
@ -8,7 +9,7 @@ use std::prelude::v1::*;
def_package! {
/// Package of core language features.
pub LanguageCorePackage(lib) {
lib.standard = true;
lib.flags |= ModuleFlags::STANDARD_LIB;
combine_with_exported_module!(lib, "core", core_functions);
@ -277,7 +278,8 @@ fn collect_fn_metadata(
&mut ns,
"{namespace}{}{name}",
crate::tokenizer::Token::DoubleColon.literal_syntax()
);
)
.unwrap();
scan_module(dict, list, &ns, &**m, filter);
}
}

View File

@ -1,4 +1,5 @@
use crate::def_package;
use crate::module::ModuleFlags;
use crate::plugin::*;
#[cfg(feature = "no_std")]
use std::prelude::v1::*;
@ -38,7 +39,7 @@ macro_rules! reg_functions {
def_package! {
/// Package of basic logic operators.
pub LogicPackage(lib) {
lib.standard = true;
lib.flags |= ModuleFlags::STANDARD_LIB;
#[cfg(not(feature = "only_i32"))]
#[cfg(not(feature = "only_i64"))]

View File

@ -1,6 +1,7 @@
#![cfg(not(feature = "no_object"))]
use crate::engine::OP_EQUALS;
use crate::module::ModuleFlags;
use crate::plugin::*;
use crate::{def_package, Dynamic, ImmutableString, Map, NativeCallContext, RhaiResultOf, INT};
#[cfg(feature = "no_std")]
@ -12,7 +13,7 @@ use crate::Array;
def_package! {
/// Package of basic object map utilities.
pub BasicMapPackage(lib) {
lib.standard = true;
lib.flags |= ModuleFlags::STANDARD_LIB;
combine_with_exported_module!(lib, "map", map_functions);
}

View File

@ -1,5 +1,6 @@
#![allow(non_snake_case)]
use crate::module::ModuleFlags;
use crate::plugin::*;
use crate::{def_package, Position, RhaiResultOf, ERR, INT};
#[cfg(feature = "no_std")]
@ -54,7 +55,7 @@ macro_rules! reg_functions {
def_package! {
/// Basic mathematical package.
pub BasicMathPackage(lib) {
lib.standard = true;
lib.flags |= ModuleFlags::STANDARD_LIB;
// Integer functions
combine_with_exported_module!(lib, "int", int_functions);

View File

@ -3,6 +3,7 @@ use std::prelude::v1::*;
use super::*;
use crate::def_package;
use crate::module::ModuleFlags;
def_package! {
/// Core package containing basic facilities.
@ -23,6 +24,6 @@ def_package! {
BasicFnPackage,
#[cfg(feature = "debugging")] DebuggingPackage
{
lib.standard = true;
lib.flags |= ModuleFlags::STANDARD_LIB;
}
}

View File

@ -3,6 +3,7 @@ use std::prelude::v1::*;
use super::*;
use crate::def_package;
use crate::module::ModuleFlags;
def_package! {
/// Standard package containing all built-in features.
@ -29,6 +30,6 @@ def_package! {
#[cfg(not(feature = "no_time"))] BasicTimePackage,
MoreStringPackage
{
lib.standard = true;
lib.flags |= ModuleFlags::STANDARD_LIB;
}
}

View File

@ -1,3 +1,4 @@
use crate::module::ModuleFlags;
use crate::plugin::*;
use crate::{def_package, FnPtr, SmartString, INT};
use std::any::TypeId;
@ -17,7 +18,7 @@ pub const FUNC_TO_DEBUG: &str = "to_debug";
def_package! {
/// Package of basic string utilities (e.g. printing)
pub BasicStringPackage(lib) {
lib.standard = true;
lib.flags |= ModuleFlags::STANDARD_LIB;
combine_with_exported_module!(lib, "print_debug", print_debug_functions);
combine_with_exported_module!(lib, "number_formatting", number_formatting);

View File

@ -1,3 +1,4 @@
use crate::module::ModuleFlags;
use crate::plugin::*;
use crate::{
def_package, Dynamic, ExclusiveRange, InclusiveRange, RhaiResultOf, StaticVec, INT,
@ -12,7 +13,7 @@ use super::string_basic::{print_with_func, FUNC_TO_STRING};
def_package! {
/// Package of additional string utilities over [`BasicStringPackage`][super::BasicStringPackage]
pub MoreStringPackage(lib) {
lib.standard = true;
lib.flags |= ModuleFlags::STANDARD_LIB;
combine_with_exported_module!(lib, "string", string_functions);
}

View File

@ -1,6 +1,7 @@
#![cfg(not(feature = "no_time"))]
use super::arithmetic::make_err as make_arithmetic_err;
use crate::module::ModuleFlags;
use crate::plugin::*;
use crate::{def_package, Dynamic, RhaiResult, RhaiResultOf, INT};
@ -16,7 +17,7 @@ use instant::{Duration, Instant};
def_package! {
/// Package of basic timing utilities.
pub BasicTimePackage(lib) {
lib.standard = true;
lib.flags |= ModuleFlags::STANDARD_LIB;
// Register date/time functions
combine_with_exported_module!(lib, "time", time_functions);

View File

@ -21,6 +21,7 @@ use crate::{
ImmutableString, InclusiveRange, LexError, OptimizationLevel, ParseError, Position, Scope,
Shared, SmartString, StaticVec, AST, INT, PERR,
};
use bitflags::bitflags;
#[cfg(feature = "no_std")]
use std::prelude::v1::*;
use std::{
@ -280,24 +281,32 @@ impl<'e> ParseState<'e> {
}
}
/// A type that encapsulates all the settings for a particular parsing function.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub(crate) struct ParseSettings {
bitflags! {
/// Bit-flags containing all status for [`ParseSettings`].
pub struct ParseSettingFlags: u8 {
/// Is the construct being parsed located at global level?
pub at_global_level: bool,
const GLOBAL_LEVEL = 0b0000_0001;
/// Is the construct being parsed located inside a function definition?
#[cfg(not(feature = "no_function"))]
pub in_fn_scope: bool,
const FN_SCOPE = 0b0000_0010;
/// Is the construct being parsed located inside a closure definition?
#[cfg(not(feature = "no_function"))]
#[cfg(not(feature = "no_closure"))]
pub in_closure: bool,
const CLOSURE_SCOPE = 0b0000_0100;
/// Is the construct being parsed located inside a breakable loop?
pub is_breakable: bool,
/// Allow statements in blocks?
pub allow_statements: bool,
/// Allow unquoted map properties?
pub allow_unquoted_map_properties: bool,
const BREAKABLE = 0b0000_1000;
/// Disallow statements in blocks?
const DISALLOW_STATEMENTS_IN_BLOCKS = 0b0001_0000;
/// Disallow unquoted map properties?
const DISALLOW_UNQUOTED_MAP_PROPERTIES = 0b0010_0000;
}
}
/// A type that encapsulates all the settings for a particular parsing function.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub struct ParseSettings {
/// Flags.
pub flags: ParseSettingFlags,
/// Language options in effect (overrides Engine options).
pub options: LangOptions,
/// Current expression nesting level.
@ -307,6 +316,18 @@ pub(crate) struct ParseSettings {
}
impl ParseSettings {
/// Is a particular flag on?
#[inline(always)]
#[must_use]
pub const fn has_flag(&self, flag: ParseSettingFlags) -> bool {
self.flags.contains(flag)
}
/// Is a particular language option on?
#[inline(always)]
#[must_use]
pub const fn has_option(&self, option: LangOptions) -> bool {
self.options.contains(option)
}
/// Create a new `ParseSettings` with one higher expression level.
#[inline]
#[must_use]
@ -585,7 +606,7 @@ impl Engine {
#[cfg(any(feature = "no_function", feature = "no_module"))]
let is_global = false;
if settings.options.contains(LangOptions::STRICT_VAR)
if settings.has_option(LangOptions::STRICT_VAR)
&& index.is_none()
&& !is_global
&& !state.global_imports.iter().any(|m| m.as_str() == root)
@ -653,7 +674,7 @@ impl Engine {
#[cfg(any(feature = "no_function", feature = "no_module"))]
let is_global = false;
if settings.options.contains(LangOptions::STRICT_VAR)
if settings.has_option(LangOptions::STRICT_VAR)
&& index.is_none()
&& !is_global
&& !state.global_imports.iter().any(|m| m.as_str() == root)
@ -995,7 +1016,9 @@ impl Engine {
}
let (name, pos) = match input.next().expect(NEVER_ENDS) {
(Token::Identifier(..), pos) if !settings.allow_unquoted_map_properties => {
(Token::Identifier(..), pos)
if settings.has_flag(ParseSettingFlags::DISALLOW_UNQUOTED_MAP_PROPERTIES) =>
{
return Err(PERR::PropertyExpected.into_err(pos))
}
(Token::Identifier(s) | Token::StringConstant(s), pos) => {
@ -1196,7 +1219,8 @@ impl Engine {
}
};
let (action_expr, need_comma) = if settings.allow_statements {
let (action_expr, need_comma) =
if !settings.has_flag(ParseSettingFlags::DISALLOW_STATEMENTS_IN_BLOCKS) {
let stmt = self.parse_stmt(input, state, lib, settings.level_up())?;
let need_comma = !stmt.is_self_terminated();
@ -1358,7 +1382,7 @@ impl Engine {
}
// { - block statement as expression
Token::LeftBrace if settings.options.contains(LangOptions::STMT_EXPR) => {
Token::LeftBrace if settings.has_option(LangOptions::STMT_EXPR) => {
match self.parse_block(input, state, lib, settings.level_up())? {
block @ Stmt::Block(..) => Expr::Stmt(Box::new(block.into())),
stmt => unreachable!("Stmt::Block expected but gets {:?}", stmt),
@ -1369,38 +1393,34 @@ impl Engine {
Token::LeftParen => self.parse_paren_expr(input, state, lib, settings.level_up())?,
// If statement is allowed to act as expressions
Token::If if settings.options.contains(LangOptions::IF_EXPR) => Expr::Stmt(Box::new(
Token::If if settings.has_option(LangOptions::IF_EXPR) => Expr::Stmt(Box::new(
self.parse_if(input, state, lib, settings.level_up())?
.into(),
)),
// Loops are allowed to act as expressions
Token::While | Token::Loop if settings.options.contains(LangOptions::LOOP_EXPR) => {
Token::While | Token::Loop if settings.has_option(LangOptions::LOOP_EXPR) => {
Expr::Stmt(Box::new(
self.parse_while_loop(input, state, lib, settings.level_up())?
.into(),
))
}
Token::Do if settings.options.contains(LangOptions::LOOP_EXPR) => Expr::Stmt(Box::new(
Token::Do if settings.has_option(LangOptions::LOOP_EXPR) => Expr::Stmt(Box::new(
self.parse_do(input, state, lib, settings.level_up())?
.into(),
)),
Token::For if settings.options.contains(LangOptions::LOOP_EXPR) => {
Expr::Stmt(Box::new(
Token::For if settings.has_option(LangOptions::LOOP_EXPR) => Expr::Stmt(Box::new(
self.parse_for(input, state, lib, settings.level_up())?
.into(),
))
}
)),
// Switch statement is allowed to act as expressions
Token::Switch if settings.options.contains(LangOptions::SWITCH_EXPR) => {
Expr::Stmt(Box::new(
Token::Switch if settings.has_option(LangOptions::SWITCH_EXPR) => Expr::Stmt(Box::new(
self.parse_switch(input, state, lib, settings.level_up())?
.into(),
))
}
)),
// | ...
#[cfg(not(feature = "no_function"))]
Token::Pipe | Token::Or if settings.options.contains(LangOptions::ANON_FN) => {
Token::Pipe | Token::Or if settings.has_option(LangOptions::ANON_FN) => {
// Build new parse state
let interned_strings = std::mem::take(&mut state.interned_strings);
@ -1429,24 +1449,24 @@ impl Engine {
new_state.max_expr_depth = self.max_function_expr_depth();
}
let mut options = self.options;
options.set(
LangOptions::STRICT_VAR,
if cfg!(feature = "no_closure") {
settings.options.contains(LangOptions::STRICT_VAR)
} else {
// A capturing closure can access variables not defined locally
false
},
);
#[cfg(not(feature = "no_closure"))]
let options = self.options & !LangOptions::STRICT_VAR; // A capturing closure can access variables not defined locally
#[cfg(feature = "no_closure")]
let options = self.options | (settings.options & LangOptions::STRICT_VAR);
let mut flags = (settings.flags
& !ParseSettingFlags::GLOBAL_LEVEL
& ParseSettingFlags::BREAKABLE)
| ParseSettingFlags::FN_SCOPE;
#[cfg(not(feature = "no_closure"))]
{
flags |= ParseSettingFlags::CLOSURE_SCOPE;
}
let new_settings = ParseSettings {
at_global_level: false,
in_fn_scope: true,
#[cfg(not(feature = "no_closure"))]
in_closure: true,
is_breakable: false,
level: 0,
flags,
options,
..settings
};
@ -1465,8 +1485,8 @@ impl Engine {
if !is_func
&& index.is_none()
&& !settings.in_closure
&& settings.options.contains(LangOptions::STRICT_VAR)
&& !settings.has_flag(ParseSettingFlags::CLOSURE_SCOPE)
&& settings.has_option(LangOptions::STRICT_VAR)
&& !state.scope.contains(name)
{
// If the parent scope is not inside another capturing closure
@ -1612,7 +1632,7 @@ impl Engine {
if !is_property
&& !is_func
&& index.is_none()
&& settings.options.contains(LangOptions::STRICT_VAR)
&& settings.has_option(LangOptions::STRICT_VAR)
&& !state.scope.contains(&s)
{
return Err(
@ -1656,11 +1676,13 @@ impl Engine {
}
// Access to `this` as a variable is OK within a function scope
#[cfg(not(feature = "no_function"))]
_ if &*s == KEYWORD_THIS && settings.in_fn_scope => Expr::Variable(
_ if &*s == KEYWORD_THIS && settings.has_flag(ParseSettingFlags::FN_SCOPE) => {
Expr::Variable(
(None, ns, 0, state.get_interned_string(*s)).into(),
None,
settings.pos,
),
)
}
// Cannot access to `this` as a variable not in a function scope
_ if &*s == KEYWORD_THIS => {
let msg = format!("'{s}' can only be used in functions");
@ -1852,7 +1874,7 @@ impl Engine {
#[cfg(any(feature = "no_function", feature = "no_module"))]
let is_global = false;
if settings.options.contains(LangOptions::STRICT_VAR)
if settings.has_option(LangOptions::STRICT_VAR)
&& index.is_none()
&& !is_global
&& !state.global_imports.iter().any(|m| m.as_str() == root)
@ -2399,12 +2421,12 @@ impl Engine {
Token::Or => {
let rhs = op_base.args.pop().unwrap().ensure_bool_expr()?;
let lhs = op_base.args.pop().unwrap().ensure_bool_expr()?;
Expr::Or(BinaryExpr { lhs: lhs, rhs: rhs }.into(), pos)
Expr::Or(BinaryExpr { lhs, rhs }.into(), pos)
}
Token::And => {
let rhs = op_base.args.pop().unwrap().ensure_bool_expr()?;
let lhs = op_base.args.pop().unwrap().ensure_bool_expr()?;
Expr::And(BinaryExpr { lhs: lhs, rhs: rhs }.into(), pos)
Expr::And(BinaryExpr { lhs, rhs }.into(), pos)
}
Token::DoubleQuestion => {
let rhs = op_base.args.pop().unwrap();
@ -2590,9 +2612,7 @@ impl Engine {
},
s => match input.next().expect(NEVER_ENDS) {
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
(Token::Identifier(t), ..)
| (Token::Reserved(t), ..)
| (Token::Custom(t), ..)
(Token::Identifier(t) | Token::Reserved(t) | Token::Custom(t), ..)
if *t == s =>
{
segments.push(required_token.clone());
@ -2726,7 +2746,7 @@ impl Engine {
token => unreachable!("Token::While or Token::Loop expected but gets {:?}", token),
};
settings.pos = token_pos;
settings.is_breakable = true;
settings.flags |= ParseSettingFlags::BREAKABLE;
let body = self.parse_block(input, state, lib, settings.level_up())?;
@ -2749,7 +2769,7 @@ impl Engine {
settings.pos = eat_token(input, Token::Do);
// do { body } [while|until] guard
settings.is_breakable = true;
settings.flags |= ParseSettingFlags::BREAKABLE;
let body = self.parse_block(input, state, lib, settings.level_up())?;
let negated = match input.next().expect(NEVER_ENDS) {
@ -2763,7 +2783,7 @@ impl Engine {
}
};
settings.is_breakable = false;
settings.flags &= !ParseSettingFlags::BREAKABLE;
ensure_not_statement_expr(input, "a boolean")?;
let guard = self
@ -2859,7 +2879,7 @@ impl Engine {
pos: name_pos,
};
settings.is_breakable = true;
settings.flags |= ParseSettingFlags::BREAKABLE;
let body = self.parse_block(input, state, lib, settings.level_up())?;
state.stack.rewind(prev_stack_len);
@ -3089,7 +3109,7 @@ impl Engine {
let mut statements = StaticVec::new_const();
if !settings.allow_statements {
if settings.has_flag(ParseSettingFlags::DISALLOW_STATEMENTS_IN_BLOCKS) {
let stmt = self.parse_expr_stmt(input, state, lib, settings.level_up())?;
statements.push(stmt);
@ -3126,7 +3146,7 @@ impl Engine {
}
// Parse statements inside the block
settings.at_global_level = false;
settings.flags &= !ParseSettingFlags::GLOBAL_LEVEL;
let stmt = self.parse_stmt(input, state, lib, settings.level_up())?;
@ -3222,7 +3242,7 @@ impl Engine {
unreachable!("doc-comment expected but gets {:?}", comment);
}
if !settings.at_global_level {
if !settings.has_flag(ParseSettingFlags::GLOBAL_LEVEL) {
return Err(PERR::WrongDocComment.into_err(comments_pos));
}
@ -3264,7 +3284,7 @@ impl Engine {
// fn ...
#[cfg(not(feature = "no_function"))]
Token::Fn if !settings.at_global_level => {
Token::Fn if !settings.has_flag(ParseSettingFlags::GLOBAL_LEVEL) => {
Err(PERR::WrongFnDefinition.into_err(token_pos))
}
@ -3307,20 +3327,14 @@ impl Engine {
new_state.max_expr_depth = self.max_function_expr_depth();
}
let mut options = self.options;
options.set(
LangOptions::STRICT_VAR,
settings.options.contains(LangOptions::STRICT_VAR),
);
let options = self.options | (settings.options & LangOptions::STRICT_VAR);
let flags = ParseSettingFlags::FN_SCOPE
| (settings.flags
& ParseSettingFlags::DISALLOW_UNQUOTED_MAP_PROPERTIES);
let new_settings = ParseSettings {
at_global_level: false,
in_fn_scope: true,
#[cfg(not(feature = "no_closure"))]
in_closure: false,
is_breakable: false,
allow_statements: true,
allow_unquoted_map_properties: settings.allow_unquoted_map_properties,
flags,
level: 0,
options,
pos,
@ -3377,11 +3391,15 @@ impl Engine {
self.parse_for(input, state, lib, settings.level_up())
}
Token::Continue if self.allow_looping() && settings.is_breakable => {
Token::Continue
if self.allow_looping() && settings.has_flag(ParseSettingFlags::BREAKABLE) =>
{
let pos = eat_token(input, Token::Continue);
Ok(Stmt::BreakLoop(None, ASTFlags::NONE, pos))
}
Token::Break if self.allow_looping() && settings.is_breakable => {
Token::Break
if self.allow_looping() && settings.has_flag(ParseSettingFlags::BREAKABLE) =>
{
let pos = eat_token(input, Token::Break);
let expr = match input.peek().expect(NEVER_ENDS) {
@ -3424,7 +3442,9 @@ impl Engine {
// `return`/`throw` at <EOF>
(Token::EOF, ..) => Ok(Stmt::Return(None, return_type, token_pos)),
// `return`/`throw` at end of block
(Token::RightBrace, ..) if !settings.at_global_level => {
(Token::RightBrace, ..)
if !settings.has_flag(ParseSettingFlags::GLOBAL_LEVEL) =>
{
Ok(Stmt::Return(None, return_type, token_pos))
}
// `return;` or `throw;`
@ -3446,7 +3466,7 @@ impl Engine {
Token::Import => self.parse_import(input, state, lib, settings.level_up()),
#[cfg(not(feature = "no_module"))]
Token::Export if !settings.at_global_level => {
Token::Export if !settings.has_flag(ParseSettingFlags::GLOBAL_LEVEL) => {
Err(PERR::WrongExport.into_err(token_pos))
}
@ -3607,7 +3627,7 @@ impl Engine {
// Parse function body
let body = match input.peek().expect(NEVER_ENDS) {
(Token::LeftBrace, ..) => {
settings.is_breakable = false;
settings.flags &= !ParseSettingFlags::BREAKABLE;
self.parse_block(input, state, lib, settings.level_up())?
}
(.., pos) => return Err(PERR::FnMissingBody(name.into()).into_err(*pos)),
@ -3759,7 +3779,7 @@ impl Engine {
}
// Parse function body
settings.is_breakable = false;
settings.flags &= !ParseSettingFlags::BREAKABLE;
let body = self.parse_stmt(input, state, lib, settings.level_up())?;
// External variables may need to be processed in a consistent order,
@ -3822,22 +3842,16 @@ impl Engine {
) -> ParseResult<AST> {
let mut functions = StraightHashMap::default();
let mut options = self.options;
options.remove(LangOptions::STMT_EXPR | LangOptions::LOOP_EXPR);
let mut options = self.options & !LangOptions::STMT_EXPR & !LangOptions::LOOP_EXPR;
#[cfg(not(feature = "no_function"))]
options.remove(LangOptions::ANON_FN);
{
options &= !LangOptions::ANON_FN;
}
let mut settings = ParseSettings {
at_global_level: true,
#[cfg(not(feature = "no_function"))]
in_fn_scope: false,
#[cfg(not(feature = "no_function"))]
#[cfg(not(feature = "no_closure"))]
in_closure: false,
is_breakable: false,
allow_statements: false,
allow_unquoted_map_properties: true,
level: 0,
flags: ParseSettingFlags::GLOBAL_LEVEL
| ParseSettingFlags::DISALLOW_STATEMENTS_IN_BLOCKS,
options,
pos: Position::START,
};
@ -3883,18 +3897,11 @@ impl Engine {
) -> ParseResult<(StmtBlockContainer, StaticVec<Shared<ScriptFnDef>>)> {
let mut statements = StmtBlockContainer::new_const();
let mut functions = StraightHashMap::default();
let mut settings = ParseSettings {
at_global_level: true,
#[cfg(not(feature = "no_function"))]
in_fn_scope: false,
#[cfg(not(feature = "no_function"))]
#[cfg(not(feature = "no_closure"))]
in_closure: false,
is_breakable: false,
allow_statements: true,
allow_unquoted_map_properties: true,
options: self.options,
level: 0,
flags: ParseSettingFlags::GLOBAL_LEVEL,
options: self.options,
pos: Position::START,
};
process_settings(&mut settings);

View File

@ -2,7 +2,7 @@
#![cfg(feature = "metadata")]
use crate::api::type_names::format_type;
use crate::module::{calc_native_fn_hash, FuncInfo};
use crate::module::{calc_native_fn_hash, FuncInfo, ModuleFlags};
use crate::{calc_fn_hash, Engine, FnAccess, SmartString, StaticVec, AST};
use serde::Serialize;
#[cfg(feature = "no_std")]
@ -174,10 +174,16 @@ pub fn gen_metadata_to_json(
global.modules.insert(name, m.as_ref().into());
}
let exclude_flags = if !include_standard_packages {
ModuleFlags::STANDARD_LIB
} else {
ModuleFlags::empty()
};
engine
.global_modules
.iter()
.filter(|m| include_standard_packages || !m.standard)
.filter(|m| !m.flags.contains(exclude_flags))
.flat_map(|m| m.iter_fn())
.for_each(|f| {
#[allow(unused_mut)]

View File

@ -966,18 +966,16 @@ impl Token {
use Token::*;
match self {
LexError(..) |
SemiColon | // ; - is unary
Colon | // #{ foo: - is unary
Comma | // ( ... , -expr ) - is unary
//Period |
//Elvis |
//DoubleQuestion |
//QuestionBracket |
DoubleQuestion | // ?? - is unary
ExclusiveRange | // .. - is unary
InclusiveRange | // ..= - is unary
LeftBrace | // { -expr } - is unary
// RightBrace | { expr } - expr not unary & is closing
// RightBrace | // { expr } - expr not unary & is closing
LeftParen | // ( -expr ) - is unary
// RightParen | // ( expr ) - expr not unary & is closing
LeftBracket | // [ -expr ] - is unary
@ -1024,6 +1022,11 @@ impl Token {
Return |
Throw => true,
#[cfg(not(feature = "no_index"))]
QuestionBracket => true, // ?[ - is unary
LexError(..) => true,
_ => false,
}
}

View File

@ -14,7 +14,7 @@ fn test_fn_ptr_curry_call() -> Result<(), Box<EvalAltResult>> {
engine.register_raw_fn(
"call_with_arg",
&[TypeId::of::<FnPtr>(), TypeId::of::<INT>()],
[TypeId::of::<FnPtr>(), TypeId::of::<INT>()],
|context, args| {
let fn_ptr = std::mem::take(args[0]).cast::<FnPtr>();
fn_ptr.call_raw(&context, None, [std::mem::take(args[1])])
@ -165,7 +165,7 @@ fn test_closures() -> Result<(), Box<EvalAltResult>> {
engine.register_raw_fn(
"custom_call",
&[TypeId::of::<INT>(), TypeId::of::<FnPtr>()],
[TypeId::of::<INT>(), TypeId::of::<FnPtr>()],
|context, args| {
let func = take(args[1]).cast::<FnPtr>();
@ -348,7 +348,7 @@ fn test_closures_shared_obj() -> Result<(), Box<EvalAltResult>> {
let p1 = Rc::new(RefCell::new(41));
let p2 = Rc::new(RefCell::new(1));
f(p1.clone(), p2.clone())?;
f(p1.clone(), p2)?;
assert_eq!(*p1.borrow(), 42);

View File

@ -274,8 +274,7 @@ fn test_custom_syntax_raw() -> Result<(), Box<EvalAltResult>> {
Ok(None)
}
s => Err(LexError::ImproperSymbol(s.to_string(), String::new())
.into_err(Position::NONE)
.into()),
.into_err(Position::NONE)),
},
_ => unreachable!(),
},