Use bitflags.
This commit is contained in:
parent
d911327242
commit
4e27039521
@ -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.
|
// Determine whether function generates a special calling convention for a mutable receiver.
|
||||||
let mut_receiver = match fn_all.sig.inputs.iter().nth(skip_slots) {
|
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> {
|
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)
|
self.signature.inputs.iter().skip(skip)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn arg_count(&self) -> usize {
|
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
|
self.signature.inputs.len() - skip
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ pub fn main() {
|
|||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
pub fn main() {
|
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};
|
use std::io::{stdin, stdout, Write};
|
||||||
|
|
||||||
const SCRIPT_FILE: &str = "event_handler_js/script.rhai";
|
const SCRIPT_FILE: &str = "event_handler_js/script.rhai";
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#![cfg(feature = "internals")]
|
#![cfg(feature = "internals")]
|
||||||
#![cfg(feature = "metadata")]
|
#![cfg(feature = "metadata")]
|
||||||
|
|
||||||
use crate::module::FuncInfo;
|
use crate::module::{FuncInfo, ModuleFlags};
|
||||||
use crate::tokenizer::{is_valid_function_name, Token};
|
use crate::tokenizer::{is_valid_function_name, Token};
|
||||||
use crate::{Engine, FnAccess, FnPtr, Module, Scope, INT};
|
use crate::{Engine, FnAccess, FnPtr, Module, Scope, INT};
|
||||||
|
|
||||||
@ -308,10 +308,16 @@ impl Definitions<'_> {
|
|||||||
String::new()
|
String::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let exclude_flags = if !self.config.include_standard_packages {
|
||||||
|
ModuleFlags::STANDARD_LIB
|
||||||
|
} else {
|
||||||
|
ModuleFlags::empty()
|
||||||
|
};
|
||||||
|
|
||||||
self.engine
|
self.engine
|
||||||
.global_modules
|
.global_modules
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|m| self.config.include_standard_packages || !m.standard)
|
.filter(|m| !m.flags.contains(exclude_flags))
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.for_each(|(i, m)| {
|
.for_each(|(i, m)| {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Module that defines JSON manipulation functions for [`Engine`].
|
//! Module that defines JSON manipulation functions for [`Engine`].
|
||||||
#![cfg(not(feature = "no_object"))]
|
#![cfg(not(feature = "no_object"))]
|
||||||
|
|
||||||
use crate::parser::ParseState;
|
use crate::parser::{ParseSettingFlags, ParseState};
|
||||||
use crate::tokenizer::Token;
|
use crate::tokenizer::Token;
|
||||||
use crate::{Engine, LexError, Map, OptimizationLevel, RhaiResultOf, Scope};
|
use crate::{Engine, LexError, Map, OptimizationLevel, RhaiResultOf, Scope};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
@ -122,7 +122,7 @@ impl Engine {
|
|||||||
let ast = self.parse_global_expr(
|
let ast = self.parse_global_expr(
|
||||||
&mut stream.peekable(),
|
&mut stream.peekable(),
|
||||||
&mut state,
|
&mut state,
|
||||||
|s| s.allow_unquoted_map_properties = false,
|
|s| s.flags |= ParseSettingFlags::DISALLOW_UNQUOTED_MAP_PROPERTIES,
|
||||||
#[cfg(not(feature = "no_optimize"))]
|
#[cfg(not(feature = "no_optimize"))]
|
||||||
OptimizationLevel::None,
|
OptimizationLevel::None,
|
||||||
#[cfg(feature = "no_optimize")]
|
#[cfg(feature = "no_optimize")]
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
//! Module that defines the public function/module registration API of [`Engine`].
|
//! Module that defines the public function/module registration API of [`Engine`].
|
||||||
|
|
||||||
use crate::func::{FnCallArgs, RegisterNativeFunction, SendSync};
|
use crate::func::{FnCallArgs, RegisterNativeFunction, SendSync};
|
||||||
|
use crate::module::ModuleFlags;
|
||||||
use crate::types::dynamic::Variant;
|
use crate::types::dynamic::Variant;
|
||||||
use crate::{
|
use crate::{
|
||||||
Engine, FnAccess, FnNamespace, Identifier, Module, NativeCallContext, RhaiResultOf, Shared,
|
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}")));
|
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(
|
signatures.extend(
|
||||||
self.global_modules
|
self.global_modules
|
||||||
.iter()
|
.iter()
|
||||||
.skip(1)
|
.skip(1)
|
||||||
.filter(|m| !m.internal && (include_packages || !m.standard))
|
.filter(|m| !m.flags.contains(exclude_flags))
|
||||||
.flat_map(|m| m.gen_fn_signatures()),
|
.flat_map(|m| m.gen_fn_signatures()),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ use crate::func::native::{
|
|||||||
locked_write, OnDebugCallback, OnDefVarCallback, OnParseTokenCallback, OnPrintCallback,
|
locked_write, OnDebugCallback, OnDefVarCallback, OnParseTokenCallback, OnPrintCallback,
|
||||||
OnVarCallback,
|
OnVarCallback,
|
||||||
};
|
};
|
||||||
|
use crate::module::ModuleFlags;
|
||||||
use crate::packages::{Package, StandardPackage};
|
use crate::packages::{Package, StandardPackage};
|
||||||
use crate::tokenizer::Token;
|
use crate::tokenizer::Token;
|
||||||
use crate::types::StringsInterner;
|
use crate::types::StringsInterner;
|
||||||
@ -303,7 +304,7 @@ impl Engine {
|
|||||||
|
|
||||||
// Add the global namespace module
|
// Add the global namespace module
|
||||||
let mut global_namespace = Module::with_capacity(0);
|
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.global_modules.push(global_namespace.into());
|
||||||
|
|
||||||
engine
|
engine
|
||||||
|
@ -764,6 +764,8 @@ impl Engine {
|
|||||||
// Import statement
|
// Import statement
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
Stmt::Import(x, _pos) => {
|
Stmt::Import(x, _pos) => {
|
||||||
|
use crate::ModuleResolver;
|
||||||
|
|
||||||
let (expr, export) = &**x;
|
let (expr, export) = &**x;
|
||||||
|
|
||||||
// Guard against too many modules
|
// Guard against too many modules
|
||||||
@ -777,8 +779,6 @@ impl Engine {
|
|||||||
self.make_type_mismatch_err::<crate::ImmutableString>(typ, expr.position())
|
self.make_type_mismatch_err::<crate::ImmutableString>(typ, expr.position())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
use crate::ModuleResolver;
|
|
||||||
|
|
||||||
let path_pos = expr.start_position();
|
let path_pos = expr.start_position();
|
||||||
|
|
||||||
let resolver = global.embedded_module_resolver.clone();
|
let resolver = global.embedded_module_resolver.clone();
|
||||||
|
@ -53,8 +53,7 @@ pub fn calc_index<E>(
|
|||||||
negative_count_from_end: bool,
|
negative_count_from_end: bool,
|
||||||
err_func: impl FnOnce() -> Result<usize, E>,
|
err_func: impl FnOnce() -> Result<usize, E>,
|
||||||
) -> Result<usize, E> {
|
) -> Result<usize, E> {
|
||||||
if start < 0 {
|
if start < 0 && negative_count_from_end {
|
||||||
if negative_count_from_end {
|
|
||||||
let abs_start = start.unsigned_abs() as usize;
|
let abs_start = start.unsigned_abs() as usize;
|
||||||
|
|
||||||
// Count from end if negative
|
// Count from end if negative
|
||||||
@ -62,7 +61,6 @@ pub fn calc_index<E>(
|
|||||||
return Ok(length - abs_start);
|
return Ok(length - abs_start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if start <= crate::MAX_USIZE_INT && (start as usize) < length {
|
if start <= crate::MAX_USIZE_INT && (start as usize) < length {
|
||||||
return Ok(start as usize);
|
return Ok(start as usize);
|
||||||
}
|
}
|
||||||
|
@ -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
|
// Handle ranges here because ranges are implemented as custom type
|
||||||
if type1 == TypeId::of::<ExclusiveRange>() {
|
if type1 == TypeId::of::<ExclusiveRange>() && type1 == type2 {
|
||||||
if type1 == type2 {
|
|
||||||
return match op {
|
return match op {
|
||||||
EqualsTo => Some(impl_op!(ExclusiveRange == ExclusiveRange)),
|
EqualsTo => Some(impl_op!(ExclusiveRange == ExclusiveRange)),
|
||||||
NotEqualsTo => Some(impl_op!(ExclusiveRange != ExclusiveRange)),
|
NotEqualsTo => Some(impl_op!(ExclusiveRange != ExclusiveRange)),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if type1 == TypeId::of::<InclusiveRange>() {
|
if type1 == TypeId::of::<InclusiveRange>() && type1 == type2 {
|
||||||
if type1 == type2 {
|
|
||||||
return match op {
|
return match op {
|
||||||
EqualsTo => Some(impl_op!(InclusiveRange == InclusiveRange)),
|
EqualsTo => Some(impl_op!(InclusiveRange == InclusiveRange)),
|
||||||
NotEqualsTo => Some(impl_op!(InclusiveRange != InclusiveRange)),
|
NotEqualsTo => Some(impl_op!(InclusiveRange != InclusiveRange)),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// One of the operands is a custom type, so it is never built-in
|
// One of the operands is a custom type, so it is never built-in
|
||||||
if x.is_variant() || y.is_variant() {
|
if x.is_variant() || y.is_variant() {
|
||||||
|
10
src/lib.rs
10
src/lib.rs
@ -58,11 +58,11 @@
|
|||||||
|
|
||||||
#![cfg_attr(feature = "no_std", no_std)]
|
#![cfg_attr(feature = "no_std", no_std)]
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
// #![warn(clippy::all)]
|
#![warn(clippy::all)]
|
||||||
// #![warn(clippy::pedantic)]
|
#![warn(clippy::pedantic)]
|
||||||
// #![warn(clippy::nursery)]
|
#![warn(clippy::nursery)]
|
||||||
// #![warn(clippy::cargo)]
|
#![warn(clippy::cargo)]
|
||||||
// #![warn(clippy::undocumented_unsafe_blocks)]
|
#![warn(clippy::undocumented_unsafe_blocks)]
|
||||||
#![allow(clippy::unit_arg)]
|
#![allow(clippy::unit_arg)]
|
||||||
#![allow(clippy::missing_errors_doc)]
|
#![allow(clippy::missing_errors_doc)]
|
||||||
#![allow(clippy::used_underscore_binding)]
|
#![allow(clippy::used_underscore_binding)]
|
||||||
|
@ -5,13 +5,14 @@ use crate::api::type_names::format_type;
|
|||||||
use crate::ast::FnAccess;
|
use crate::ast::FnAccess;
|
||||||
use crate::func::{
|
use crate::func::{
|
||||||
shared_take_or_clone, CallableFunction, FnCallArgs, IteratorFn, RegisterNativeFunction,
|
shared_take_or_clone, CallableFunction, FnCallArgs, IteratorFn, RegisterNativeFunction,
|
||||||
SendSync,
|
SendSync, StraightHashMap,
|
||||||
};
|
};
|
||||||
use crate::types::{dynamic::Variant, BloomFilterU64, CustomTypesCollection};
|
use crate::types::{dynamic::Variant, BloomFilterU64, CustomTypesCollection};
|
||||||
use crate::{
|
use crate::{
|
||||||
calc_fn_hash, calc_fn_hash_full, Dynamic, Identifier, ImmutableString, NativeCallContext,
|
calc_fn_hash, calc_fn_hash_full, Dynamic, Identifier, ImmutableString, NativeCallContext,
|
||||||
RhaiResultOf, Shared, SharedModule, SmartString, StaticVec,
|
RhaiResultOf, Shared, SharedModule, SmartString, StaticVec,
|
||||||
};
|
};
|
||||||
|
use bitflags::bitflags;
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
use std::{
|
use std::{
|
||||||
@ -24,8 +25,6 @@ use std::{
|
|||||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||||
use crate::func::register::Mut;
|
use crate::func::register::Mut;
|
||||||
|
|
||||||
use crate::func::StraightHashMap;
|
|
||||||
|
|
||||||
/// A type representing the namespace of a function.
|
/// A type representing the namespace of a function.
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||||
#[cfg_attr(feature = "metadata", derive(serde::Serialize))]
|
#[cfg_attr(feature = "metadata", derive(serde::Serialize))]
|
||||||
@ -94,44 +93,44 @@ impl FuncInfo {
|
|||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn gen_signature(&self) -> String {
|
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);
|
let return_type = format_type(&self.return_type, true);
|
||||||
|
|
||||||
if self.params_info.is_empty() {
|
if self.params_info.is_empty() {
|
||||||
for x in 0..self.num_params {
|
for x in 0..self.num_params {
|
||||||
sig.push('_');
|
signature.push('_');
|
||||||
if x < self.num_params - 1 {
|
if x < self.num_params - 1 {
|
||||||
sig.push_str(", ");
|
signature.push_str(", ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let params: StaticVec<_> = self
|
let params: StaticVec<_> = self
|
||||||
.params_info
|
.params_info
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| {
|
.map(|param| {
|
||||||
let mut seg = s.splitn(2, ':');
|
let mut segment = param.splitn(2, ':');
|
||||||
let name = match seg.next().unwrap().trim() {
|
let name = match segment.next().unwrap().trim() {
|
||||||
"" => "_",
|
"" => "_",
|
||||||
s => s,
|
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(),
|
Some(typ) => format!("{name}: {}", format_type(typ, false)).into(),
|
||||||
None => name.into(),
|
None => name.into(),
|
||||||
};
|
};
|
||||||
result
|
result
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
sig.push_str(¶ms.join(", "));
|
signature.push_str(¶ms.join(", "));
|
||||||
}
|
}
|
||||||
sig.push(')');
|
signature.push(')');
|
||||||
|
|
||||||
if !self.func.is_script() && !return_type.is_empty() {
|
if !self.func.is_script() && !return_type.is_empty() {
|
||||||
sig.push_str(" -> ");
|
signature.push_str(" -> ");
|
||||||
sig.push_str(&return_type);
|
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,
|
/// A module which may contain variables, sub-modules, external Rust functions,
|
||||||
/// and/or script-defined functions.
|
/// and/or script-defined functions.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -165,10 +178,6 @@ pub struct Module {
|
|||||||
/// Module documentation.
|
/// Module documentation.
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
doc: crate::SmartString,
|
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.
|
||||||
custom_types: Option<CustomTypesCollection>,
|
custom_types: Option<CustomTypesCollection>,
|
||||||
/// Sub-modules.
|
/// Sub-modules.
|
||||||
@ -188,10 +197,8 @@ pub struct Module {
|
|||||||
type_iterators: Option<BTreeMap<TypeId, Shared<IteratorFn>>>,
|
type_iterators: Option<BTreeMap<TypeId, Shared<IteratorFn>>>,
|
||||||
/// Flattened collection of iterator functions, including those in sub-modules.
|
/// Flattened collection of iterator functions, including those in sub-modules.
|
||||||
all_type_iterators: Option<BTreeMap<TypeId, Shared<IteratorFn>>>,
|
all_type_iterators: Option<BTreeMap<TypeId, Shared<IteratorFn>>>,
|
||||||
/// Is the [`Module`] indexed?
|
/// Flags.
|
||||||
indexed: bool,
|
pub(crate) flags: ModuleFlags,
|
||||||
/// Does the [`Module`] contain indexed functions that have been exposed to the global namespace?
|
|
||||||
contains_indexed_global_functions: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Module {
|
impl Default for Module {
|
||||||
@ -295,8 +302,6 @@ impl Module {
|
|||||||
id: None,
|
id: None,
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
doc: crate::SmartString::new_const(),
|
doc: crate::SmartString::new_const(),
|
||||||
internal: false,
|
|
||||||
standard: false,
|
|
||||||
custom_types: None,
|
custom_types: None,
|
||||||
modules: None,
|
modules: None,
|
||||||
variables: None,
|
variables: None,
|
||||||
@ -306,8 +311,7 @@ impl Module {
|
|||||||
dynamic_functions_filter: BloomFilterU64::new(),
|
dynamic_functions_filter: BloomFilterU64::new(),
|
||||||
type_iterators: None,
|
type_iterators: None,
|
||||||
all_type_iterators: None,
|
all_type_iterators: None,
|
||||||
indexed: true,
|
flags: ModuleFlags::empty(),
|
||||||
contains_indexed_global_functions: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,11 +441,8 @@ impl Module {
|
|||||||
/// Clear the [`Module`].
|
/// Clear the [`Module`].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
self.id = None;
|
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
self.doc.clear();
|
self.doc.clear();
|
||||||
self.internal = false;
|
|
||||||
self.standard = false;
|
|
||||||
self.custom_types = None;
|
self.custom_types = None;
|
||||||
self.modules = None;
|
self.modules = None;
|
||||||
self.variables = None;
|
self.variables = None;
|
||||||
@ -451,8 +452,7 @@ impl Module {
|
|||||||
self.dynamic_functions_filter.clear();
|
self.dynamic_functions_filter.clear();
|
||||||
self.type_iterators = None;
|
self.type_iterators = None;
|
||||||
self.all_type_iterators = None;
|
self.all_type_iterators = None;
|
||||||
self.indexed = false;
|
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
|
||||||
self.contains_indexed_global_functions = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Map a custom type to a friendly display name.
|
/// Map a custom type to a friendly display name.
|
||||||
@ -543,7 +543,7 @@ impl Module {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
!self.contains_indexed_global_functions
|
!self.flags.contains(ModuleFlags::INDEXED_GLOBAL_FUNCTIONS)
|
||||||
&& self.functions.is_empty()
|
&& self.functions.is_empty()
|
||||||
&& self.variables.as_ref().map_or(true, |m| m.is_empty())
|
&& self.variables.as_ref().map_or(true, |m| m.is_empty())
|
||||||
&& self.modules.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)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn is_indexed(&self) -> bool {
|
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`].
|
/// _(metadata)_ Generate signatures for all the non-private functions in the [`Module`].
|
||||||
@ -666,7 +666,7 @@ impl Module {
|
|||||||
let ident = name.into();
|
let ident = name.into();
|
||||||
let value = Dynamic::from(value);
|
let value = Dynamic::from(value);
|
||||||
|
|
||||||
if self.indexed {
|
if self.is_indexed() {
|
||||||
let hash_var = crate::calc_var_hash(Some(""), &ident);
|
let hash_var = crate::calc_var_hash(Some(""), &ident);
|
||||||
self.all_variables
|
self.all_variables
|
||||||
.get_or_insert_with(|| Default::default())
|
.get_or_insert_with(|| Default::default())
|
||||||
@ -717,8 +717,7 @@ impl Module {
|
|||||||
func: fn_def.into(),
|
func: fn_def.into(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
self.indexed = false;
|
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
|
||||||
self.contains_indexed_global_functions = false;
|
|
||||||
hash_script
|
hash_script
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -759,8 +758,7 @@ impl Module {
|
|||||||
self.all_functions = None;
|
self.all_functions = None;
|
||||||
self.all_variables = None;
|
self.all_variables = None;
|
||||||
self.all_type_iterators = None;
|
self.all_type_iterators = None;
|
||||||
self.indexed = false;
|
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
|
||||||
self.contains_indexed_global_functions = false;
|
|
||||||
|
|
||||||
self.modules.get_or_insert_with(|| Default::default())
|
self.modules.get_or_insert_with(|| Default::default())
|
||||||
}
|
}
|
||||||
@ -826,8 +824,7 @@ impl Module {
|
|||||||
self.modules
|
self.modules
|
||||||
.get_or_insert_with(|| Default::default())
|
.get_or_insert_with(|| Default::default())
|
||||||
.insert(name.into(), sub_module.into());
|
.insert(name.into(), sub_module.into());
|
||||||
self.indexed = false;
|
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
|
||||||
self.contains_indexed_global_functions = false;
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -942,8 +939,7 @@ impl Module {
|
|||||||
pub fn update_fn_namespace(&mut self, hash_fn: u64, namespace: FnNamespace) -> &mut Self {
|
pub fn update_fn_namespace(&mut self, hash_fn: u64, namespace: FnNamespace) -> &mut Self {
|
||||||
if let Some(f) = self.functions.get_mut(&hash_fn) {
|
if let Some(f) = self.functions.get_mut(&hash_fn) {
|
||||||
f.namespace = namespace;
|
f.namespace = namespace;
|
||||||
self.indexed = false;
|
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
|
||||||
self.contains_indexed_global_functions = false;
|
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -1051,8 +1047,7 @@ impl Module {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
self.indexed = false;
|
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
|
||||||
self.contains_indexed_global_functions = false;
|
|
||||||
|
|
||||||
hash_fn
|
hash_fn
|
||||||
}
|
}
|
||||||
@ -1607,8 +1602,7 @@ impl Module {
|
|||||||
self.all_functions = None;
|
self.all_functions = None;
|
||||||
self.all_variables = None;
|
self.all_variables = None;
|
||||||
self.all_type_iterators = None;
|
self.all_type_iterators = None;
|
||||||
self.indexed = false;
|
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
|
||||||
self.contains_indexed_global_functions = false;
|
|
||||||
|
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
if !other.doc.is_empty() {
|
if !other.doc.is_empty() {
|
||||||
@ -1650,8 +1644,7 @@ impl Module {
|
|||||||
self.all_functions = None;
|
self.all_functions = None;
|
||||||
self.all_variables = None;
|
self.all_variables = None;
|
||||||
self.all_type_iterators = None;
|
self.all_type_iterators = None;
|
||||||
self.indexed = false;
|
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
|
||||||
self.contains_indexed_global_functions = false;
|
|
||||||
|
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
if !other.doc.is_empty() {
|
if !other.doc.is_empty() {
|
||||||
@ -1702,8 +1695,7 @@ impl Module {
|
|||||||
self.all_functions = None;
|
self.all_functions = None;
|
||||||
self.all_variables = None;
|
self.all_variables = None;
|
||||||
self.all_type_iterators = None;
|
self.all_type_iterators = None;
|
||||||
self.indexed = false;
|
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
|
||||||
self.contains_indexed_global_functions = false;
|
|
||||||
|
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
if !other.doc.is_empty() {
|
if !other.doc.is_empty() {
|
||||||
@ -1775,8 +1767,7 @@ impl Module {
|
|||||||
self.all_functions = None;
|
self.all_functions = None;
|
||||||
self.all_variables = None;
|
self.all_variables = None;
|
||||||
self.all_type_iterators = None;
|
self.all_type_iterators = None;
|
||||||
self.indexed = false;
|
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
|
||||||
self.contains_indexed_global_functions = false;
|
|
||||||
|
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
if !other.doc.is_empty() {
|
if !other.doc.is_empty() {
|
||||||
@ -1811,8 +1802,7 @@ impl Module {
|
|||||||
self.all_functions = None;
|
self.all_functions = None;
|
||||||
self.all_variables = None;
|
self.all_variables = None;
|
||||||
self.all_type_iterators = None;
|
self.all_type_iterators = None;
|
||||||
self.indexed = false;
|
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
|
||||||
self.contains_indexed_global_functions = false;
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2108,7 +2098,7 @@ impl Module {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn contains_indexed_global_functions(&self) -> bool {
|
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
|
/// 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
|
contains_indexed_global_functions
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.indexed {
|
if !self.is_indexed() {
|
||||||
let mut path = Vec::with_capacity(4);
|
let mut path = Vec::with_capacity(4);
|
||||||
let mut variables = StraightHashMap::default();
|
let mut variables = StraightHashMap::default();
|
||||||
let mut functions = StraightHashMap::default();
|
let mut functions = StraightHashMap::default();
|
||||||
@ -2189,7 +2179,7 @@ impl Module {
|
|||||||
|
|
||||||
path.push("");
|
path.push("");
|
||||||
|
|
||||||
self.contains_indexed_global_functions = index_module(
|
let r = index_module(
|
||||||
self,
|
self,
|
||||||
&mut path,
|
&mut path,
|
||||||
&mut variables,
|
&mut variables,
|
||||||
@ -2197,6 +2187,10 @@ impl Module {
|
|||||||
&mut type_iterators,
|
&mut type_iterators,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if r {
|
||||||
|
self.flags |= ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
|
||||||
|
}
|
||||||
|
|
||||||
self.all_variables = if variables.is_empty() {
|
self.all_variables = if variables.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
@ -2213,7 +2207,7 @@ impl Module {
|
|||||||
Some(type_iterators)
|
Some(type_iterators)
|
||||||
};
|
};
|
||||||
|
|
||||||
self.indexed = true;
|
self.flags |= ModuleFlags::INDEXED;
|
||||||
}
|
}
|
||||||
|
|
||||||
self
|
self
|
||||||
@ -2257,7 +2251,7 @@ impl Module {
|
|||||||
func: impl Fn(Dynamic) -> Box<dyn Iterator<Item = RhaiResultOf<Dynamic>>> + SendSync + 'static,
|
func: impl Fn(Dynamic) -> Box<dyn Iterator<Item = RhaiResultOf<Dynamic>>> + SendSync + 'static,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
let func = Shared::new(func);
|
let func = Shared::new(func);
|
||||||
if self.indexed {
|
if self.is_indexed() {
|
||||||
self.all_type_iterators
|
self.all_type_iterators
|
||||||
.get_or_insert_with(|| Default::default())
|
.get_or_insert_with(|| Default::default())
|
||||||
.insert(type_id, func.clone());
|
.insert(type_id, func.clone());
|
||||||
|
@ -8,6 +8,7 @@ use crate::engine::{KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_FN_PTR, KEYWORD_PRINT,
|
|||||||
use crate::eval::{Caches, GlobalRuntimeState};
|
use crate::eval::{Caches, GlobalRuntimeState};
|
||||||
use crate::func::builtin::get_builtin_binary_op_fn;
|
use crate::func::builtin::get_builtin_binary_op_fn;
|
||||||
use crate::func::hashing::get_hasher;
|
use crate::func::hashing::get_hasher;
|
||||||
|
use crate::module::ModuleFlags;
|
||||||
use crate::tokenizer::Token;
|
use crate::tokenizer::Token;
|
||||||
use crate::types::dynamic::AccessMode;
|
use crate::types::dynamic::AccessMode;
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -168,7 +169,7 @@ fn has_native_fn_override(
|
|||||||
if engine
|
if engine
|
||||||
.global_modules
|
.global_modules
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|m| !m.standard)
|
.filter(|m| !m.flags.contains(ModuleFlags::STANDARD_LIB))
|
||||||
.any(|m| m.contains_fn(hash))
|
.any(|m| m.contains_fn(hash))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
use crate::module::ModuleFlags;
|
||||||
use crate::plugin::*;
|
use crate::plugin::*;
|
||||||
use crate::{def_package, Position, RhaiError, RhaiResultOf, ERR, INT};
|
use crate::{def_package, Position, RhaiError, RhaiResultOf, ERR, INT};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
@ -192,7 +193,7 @@ macro_rules! reg_functions {
|
|||||||
def_package! {
|
def_package! {
|
||||||
/// Basic arithmetic package.
|
/// Basic arithmetic package.
|
||||||
pub ArithmeticPackage(lib) {
|
pub ArithmeticPackage(lib) {
|
||||||
lib.standard = true;
|
lib.flags |= ModuleFlags::STANDARD_LIB;
|
||||||
|
|
||||||
combine_with_exported_module!(lib, "int", int_functions);
|
combine_with_exported_module!(lib, "int", int_functions);
|
||||||
reg_functions!(lib += signed_basic; INT);
|
reg_functions!(lib += signed_basic; INT);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
use crate::engine::OP_EQUALS;
|
use crate::engine::OP_EQUALS;
|
||||||
use crate::eval::{calc_index, calc_offset_len};
|
use crate::eval::{calc_index, calc_offset_len};
|
||||||
|
use crate::module::ModuleFlags;
|
||||||
use crate::plugin::*;
|
use crate::plugin::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
def_package, Array, Dynamic, ExclusiveRange, FnPtr, InclusiveRange, NativeCallContext,
|
def_package, Array, Dynamic, ExclusiveRange, FnPtr, InclusiveRange, NativeCallContext,
|
||||||
@ -14,7 +15,7 @@ use std::{any::TypeId, cmp::Ordering, mem};
|
|||||||
def_package! {
|
def_package! {
|
||||||
/// Package of basic array utilities.
|
/// Package of basic array utilities.
|
||||||
pub BasicArrayPackage(lib) {
|
pub BasicArrayPackage(lib) {
|
||||||
lib.standard = true;
|
lib.flags |= ModuleFlags::STANDARD_LIB;
|
||||||
|
|
||||||
combine_with_exported_module!(lib, "array", array_functions);
|
combine_with_exported_module!(lib, "array", array_functions);
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::eval::calc_index;
|
use crate::eval::calc_index;
|
||||||
|
use crate::module::ModuleFlags;
|
||||||
use crate::plugin::*;
|
use crate::plugin::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
def_package, ExclusiveRange, InclusiveRange, Position, RhaiResultOf, ERR, INT, INT_BITS,
|
def_package, ExclusiveRange, InclusiveRange, Position, RhaiResultOf, ERR, INT, INT_BITS,
|
||||||
@ -10,7 +11,7 @@ use std::prelude::v1::*;
|
|||||||
def_package! {
|
def_package! {
|
||||||
/// Package of basic bit-field utilities.
|
/// Package of basic bit-field utilities.
|
||||||
pub BitFieldPackage(lib) {
|
pub BitFieldPackage(lib) {
|
||||||
lib.standard = true;
|
lib.flags |= ModuleFlags::STANDARD_LIB;
|
||||||
|
|
||||||
combine_with_exported_module!(lib, "bit_field", bit_field_functions);
|
combine_with_exported_module!(lib, "bit_field", bit_field_functions);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#![cfg(not(feature = "no_index"))]
|
#![cfg(not(feature = "no_index"))]
|
||||||
|
|
||||||
use crate::eval::{calc_index, calc_offset_len};
|
use crate::eval::{calc_index, calc_offset_len};
|
||||||
|
use crate::module::ModuleFlags;
|
||||||
use crate::plugin::*;
|
use crate::plugin::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
def_package, Array, Blob, Dynamic, ExclusiveRange, InclusiveRange, NativeCallContext, Position,
|
def_package, Array, Blob, Dynamic, ExclusiveRange, InclusiveRange, NativeCallContext, Position,
|
||||||
@ -16,7 +17,7 @@ use crate::{FLOAT, FLOAT_BYTES};
|
|||||||
def_package! {
|
def_package! {
|
||||||
/// Package of basic BLOB utilities.
|
/// Package of basic BLOB utilities.
|
||||||
pub BasicBlobPackage(lib) {
|
pub BasicBlobPackage(lib) {
|
||||||
lib.standard = true;
|
lib.flags |= ModuleFlags::STANDARD_LIB;
|
||||||
|
|
||||||
combine_with_exported_module!(lib, "blob", blob_functions);
|
combine_with_exported_module!(lib, "blob", blob_functions);
|
||||||
combine_with_exported_module!(lib, "parse_int", parse_int_functions);
|
combine_with_exported_module!(lib, "parse_int", parse_int_functions);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#![cfg(feature = "debugging")]
|
#![cfg(feature = "debugging")]
|
||||||
|
|
||||||
use crate::def_package;
|
use crate::def_package;
|
||||||
|
use crate::module::ModuleFlags;
|
||||||
use crate::plugin::*;
|
use crate::plugin::*;
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
@ -17,7 +18,7 @@ use crate::Map;
|
|||||||
def_package! {
|
def_package! {
|
||||||
/// Package of basic debugging utilities.
|
/// Package of basic debugging utilities.
|
||||||
pub DebuggingPackage(lib) {
|
pub DebuggingPackage(lib) {
|
||||||
lib.standard = true;
|
lib.flags |= ModuleFlags::STANDARD_LIB;
|
||||||
|
|
||||||
combine_with_exported_module!(lib, "debugging", debugging_functions);
|
combine_with_exported_module!(lib, "debugging", debugging_functions);
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::module::ModuleFlags;
|
||||||
use crate::plugin::*;
|
use crate::plugin::*;
|
||||||
use crate::{def_package, FnPtr, ImmutableString, NativeCallContext};
|
use crate::{def_package, FnPtr, ImmutableString, NativeCallContext};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
@ -6,7 +7,7 @@ use std::prelude::v1::*;
|
|||||||
def_package! {
|
def_package! {
|
||||||
/// Package of basic function pointer utilities.
|
/// Package of basic function pointer utilities.
|
||||||
pub BasicFnPackage(lib) {
|
pub BasicFnPackage(lib) {
|
||||||
lib.standard = true;
|
lib.flags |= ModuleFlags::STANDARD_LIB;
|
||||||
|
|
||||||
combine_with_exported_module!(lib, "FnPtr", fn_ptr_functions);
|
combine_with_exported_module!(lib, "FnPtr", fn_ptr_functions);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::eval::calc_index;
|
use crate::eval::calc_index;
|
||||||
|
use crate::module::ModuleFlags;
|
||||||
use crate::plugin::*;
|
use crate::plugin::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
def_package, ExclusiveRange, InclusiveRange, RhaiResultOf, INT, INT_BITS, MAX_USIZE_INT,
|
def_package, ExclusiveRange, InclusiveRange, RhaiResultOf, INT, INT_BITS, MAX_USIZE_INT,
|
||||||
@ -329,7 +330,7 @@ macro_rules! reg_range {
|
|||||||
def_package! {
|
def_package! {
|
||||||
/// Package of basic range iterators
|
/// Package of basic range iterators
|
||||||
pub BasicIteratorPackage(lib) {
|
pub BasicIteratorPackage(lib) {
|
||||||
lib.standard = true;
|
lib.flags |= ModuleFlags::STANDARD_LIB;
|
||||||
|
|
||||||
reg_range!(lib | "range" => INT);
|
reg_range!(lib | "range" => INT);
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::def_package;
|
use crate::def_package;
|
||||||
|
use crate::module::ModuleFlags;
|
||||||
use crate::plugin::*;
|
use crate::plugin::*;
|
||||||
use crate::types::dynamic::Tag;
|
use crate::types::dynamic::Tag;
|
||||||
use crate::{Dynamic, RhaiResultOf, ERR, INT};
|
use crate::{Dynamic, RhaiResultOf, ERR, INT};
|
||||||
@ -8,7 +9,7 @@ use std::prelude::v1::*;
|
|||||||
def_package! {
|
def_package! {
|
||||||
/// Package of core language features.
|
/// Package of core language features.
|
||||||
pub LanguageCorePackage(lib) {
|
pub LanguageCorePackage(lib) {
|
||||||
lib.standard = true;
|
lib.flags |= ModuleFlags::STANDARD_LIB;
|
||||||
|
|
||||||
combine_with_exported_module!(lib, "core", core_functions);
|
combine_with_exported_module!(lib, "core", core_functions);
|
||||||
|
|
||||||
@ -277,7 +278,8 @@ fn collect_fn_metadata(
|
|||||||
&mut ns,
|
&mut ns,
|
||||||
"{namespace}{}{name}",
|
"{namespace}{}{name}",
|
||||||
crate::tokenizer::Token::DoubleColon.literal_syntax()
|
crate::tokenizer::Token::DoubleColon.literal_syntax()
|
||||||
);
|
)
|
||||||
|
.unwrap();
|
||||||
scan_module(dict, list, &ns, &**m, filter);
|
scan_module(dict, list, &ns, &**m, filter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::def_package;
|
use crate::def_package;
|
||||||
|
use crate::module::ModuleFlags;
|
||||||
use crate::plugin::*;
|
use crate::plugin::*;
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
@ -38,7 +39,7 @@ macro_rules! reg_functions {
|
|||||||
def_package! {
|
def_package! {
|
||||||
/// Package of basic logic operators.
|
/// Package of basic logic operators.
|
||||||
pub LogicPackage(lib) {
|
pub LogicPackage(lib) {
|
||||||
lib.standard = true;
|
lib.flags |= ModuleFlags::STANDARD_LIB;
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
#[cfg(not(feature = "only_i32"))]
|
||||||
#[cfg(not(feature = "only_i64"))]
|
#[cfg(not(feature = "only_i64"))]
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#![cfg(not(feature = "no_object"))]
|
#![cfg(not(feature = "no_object"))]
|
||||||
|
|
||||||
use crate::engine::OP_EQUALS;
|
use crate::engine::OP_EQUALS;
|
||||||
|
use crate::module::ModuleFlags;
|
||||||
use crate::plugin::*;
|
use crate::plugin::*;
|
||||||
use crate::{def_package, Dynamic, ImmutableString, Map, NativeCallContext, RhaiResultOf, INT};
|
use crate::{def_package, Dynamic, ImmutableString, Map, NativeCallContext, RhaiResultOf, INT};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
@ -12,7 +13,7 @@ use crate::Array;
|
|||||||
def_package! {
|
def_package! {
|
||||||
/// Package of basic object map utilities.
|
/// Package of basic object map utilities.
|
||||||
pub BasicMapPackage(lib) {
|
pub BasicMapPackage(lib) {
|
||||||
lib.standard = true;
|
lib.flags |= ModuleFlags::STANDARD_LIB;
|
||||||
|
|
||||||
combine_with_exported_module!(lib, "map", map_functions);
|
combine_with_exported_module!(lib, "map", map_functions);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
use crate::module::ModuleFlags;
|
||||||
use crate::plugin::*;
|
use crate::plugin::*;
|
||||||
use crate::{def_package, Position, RhaiResultOf, ERR, INT};
|
use crate::{def_package, Position, RhaiResultOf, ERR, INT};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
@ -54,7 +55,7 @@ macro_rules! reg_functions {
|
|||||||
def_package! {
|
def_package! {
|
||||||
/// Basic mathematical package.
|
/// Basic mathematical package.
|
||||||
pub BasicMathPackage(lib) {
|
pub BasicMathPackage(lib) {
|
||||||
lib.standard = true;
|
lib.flags |= ModuleFlags::STANDARD_LIB;
|
||||||
|
|
||||||
// Integer functions
|
// Integer functions
|
||||||
combine_with_exported_module!(lib, "int", int_functions);
|
combine_with_exported_module!(lib, "int", int_functions);
|
||||||
|
@ -3,6 +3,7 @@ use std::prelude::v1::*;
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::def_package;
|
use crate::def_package;
|
||||||
|
use crate::module::ModuleFlags;
|
||||||
|
|
||||||
def_package! {
|
def_package! {
|
||||||
/// Core package containing basic facilities.
|
/// Core package containing basic facilities.
|
||||||
@ -23,6 +24,6 @@ def_package! {
|
|||||||
BasicFnPackage,
|
BasicFnPackage,
|
||||||
#[cfg(feature = "debugging")] DebuggingPackage
|
#[cfg(feature = "debugging")] DebuggingPackage
|
||||||
{
|
{
|
||||||
lib.standard = true;
|
lib.flags |= ModuleFlags::STANDARD_LIB;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ use std::prelude::v1::*;
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::def_package;
|
use crate::def_package;
|
||||||
|
use crate::module::ModuleFlags;
|
||||||
|
|
||||||
def_package! {
|
def_package! {
|
||||||
/// Standard package containing all built-in features.
|
/// Standard package containing all built-in features.
|
||||||
@ -29,6 +30,6 @@ def_package! {
|
|||||||
#[cfg(not(feature = "no_time"))] BasicTimePackage,
|
#[cfg(not(feature = "no_time"))] BasicTimePackage,
|
||||||
MoreStringPackage
|
MoreStringPackage
|
||||||
{
|
{
|
||||||
lib.standard = true;
|
lib.flags |= ModuleFlags::STANDARD_LIB;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::module::ModuleFlags;
|
||||||
use crate::plugin::*;
|
use crate::plugin::*;
|
||||||
use crate::{def_package, FnPtr, SmartString, INT};
|
use crate::{def_package, FnPtr, SmartString, INT};
|
||||||
use std::any::TypeId;
|
use std::any::TypeId;
|
||||||
@ -17,7 +18,7 @@ pub const FUNC_TO_DEBUG: &str = "to_debug";
|
|||||||
def_package! {
|
def_package! {
|
||||||
/// Package of basic string utilities (e.g. printing)
|
/// Package of basic string utilities (e.g. printing)
|
||||||
pub BasicStringPackage(lib) {
|
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, "print_debug", print_debug_functions);
|
||||||
combine_with_exported_module!(lib, "number_formatting", number_formatting);
|
combine_with_exported_module!(lib, "number_formatting", number_formatting);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::module::ModuleFlags;
|
||||||
use crate::plugin::*;
|
use crate::plugin::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
def_package, Dynamic, ExclusiveRange, InclusiveRange, RhaiResultOf, StaticVec, INT,
|
def_package, Dynamic, ExclusiveRange, InclusiveRange, RhaiResultOf, StaticVec, INT,
|
||||||
@ -12,7 +13,7 @@ use super::string_basic::{print_with_func, FUNC_TO_STRING};
|
|||||||
def_package! {
|
def_package! {
|
||||||
/// Package of additional string utilities over [`BasicStringPackage`][super::BasicStringPackage]
|
/// Package of additional string utilities over [`BasicStringPackage`][super::BasicStringPackage]
|
||||||
pub MoreStringPackage(lib) {
|
pub MoreStringPackage(lib) {
|
||||||
lib.standard = true;
|
lib.flags |= ModuleFlags::STANDARD_LIB;
|
||||||
|
|
||||||
combine_with_exported_module!(lib, "string", string_functions);
|
combine_with_exported_module!(lib, "string", string_functions);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#![cfg(not(feature = "no_time"))]
|
#![cfg(not(feature = "no_time"))]
|
||||||
|
|
||||||
use super::arithmetic::make_err as make_arithmetic_err;
|
use super::arithmetic::make_err as make_arithmetic_err;
|
||||||
|
use crate::module::ModuleFlags;
|
||||||
use crate::plugin::*;
|
use crate::plugin::*;
|
||||||
use crate::{def_package, Dynamic, RhaiResult, RhaiResultOf, INT};
|
use crate::{def_package, Dynamic, RhaiResult, RhaiResultOf, INT};
|
||||||
|
|
||||||
@ -16,7 +17,7 @@ use instant::{Duration, Instant};
|
|||||||
def_package! {
|
def_package! {
|
||||||
/// Package of basic timing utilities.
|
/// Package of basic timing utilities.
|
||||||
pub BasicTimePackage(lib) {
|
pub BasicTimePackage(lib) {
|
||||||
lib.standard = true;
|
lib.flags |= ModuleFlags::STANDARD_LIB;
|
||||||
|
|
||||||
// Register date/time functions
|
// Register date/time functions
|
||||||
combine_with_exported_module!(lib, "time", time_functions);
|
combine_with_exported_module!(lib, "time", time_functions);
|
||||||
|
211
src/parser.rs
211
src/parser.rs
@ -21,6 +21,7 @@ use crate::{
|
|||||||
ImmutableString, InclusiveRange, LexError, OptimizationLevel, ParseError, Position, Scope,
|
ImmutableString, InclusiveRange, LexError, OptimizationLevel, ParseError, Position, Scope,
|
||||||
Shared, SmartString, StaticVec, AST, INT, PERR,
|
Shared, SmartString, StaticVec, AST, INT, PERR,
|
||||||
};
|
};
|
||||||
|
use bitflags::bitflags;
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
use std::{
|
use std::{
|
||||||
@ -280,24 +281,32 @@ impl<'e> ParseState<'e> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A type that encapsulates all the settings for a particular parsing function.
|
bitflags! {
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
/// Bit-flags containing all status for [`ParseSettings`].
|
||||||
pub(crate) struct ParseSettings {
|
pub struct ParseSettingFlags: u8 {
|
||||||
/// Is the construct being parsed located at global level?
|
/// 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?
|
/// Is the construct being parsed located inside a function definition?
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[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?
|
/// Is the construct being parsed located inside a closure definition?
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
pub in_closure: bool,
|
const CLOSURE_SCOPE = 0b0000_0100;
|
||||||
/// Is the construct being parsed located inside a breakable loop?
|
/// Is the construct being parsed located inside a breakable loop?
|
||||||
pub is_breakable: bool,
|
const BREAKABLE = 0b0000_1000;
|
||||||
/// Allow statements in blocks?
|
/// Disallow statements in blocks?
|
||||||
pub allow_statements: bool,
|
const DISALLOW_STATEMENTS_IN_BLOCKS = 0b0001_0000;
|
||||||
/// Allow unquoted map properties?
|
/// Disallow unquoted map properties?
|
||||||
pub allow_unquoted_map_properties: bool,
|
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).
|
/// Language options in effect (overrides Engine options).
|
||||||
pub options: LangOptions,
|
pub options: LangOptions,
|
||||||
/// Current expression nesting level.
|
/// Current expression nesting level.
|
||||||
@ -307,6 +316,18 @@ pub(crate) struct ParseSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl 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.
|
/// Create a new `ParseSettings` with one higher expression level.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
@ -585,7 +606,7 @@ impl Engine {
|
|||||||
#[cfg(any(feature = "no_function", feature = "no_module"))]
|
#[cfg(any(feature = "no_function", feature = "no_module"))]
|
||||||
let is_global = false;
|
let is_global = false;
|
||||||
|
|
||||||
if settings.options.contains(LangOptions::STRICT_VAR)
|
if settings.has_option(LangOptions::STRICT_VAR)
|
||||||
&& index.is_none()
|
&& index.is_none()
|
||||||
&& !is_global
|
&& !is_global
|
||||||
&& !state.global_imports.iter().any(|m| m.as_str() == root)
|
&& !state.global_imports.iter().any(|m| m.as_str() == root)
|
||||||
@ -653,7 +674,7 @@ impl Engine {
|
|||||||
#[cfg(any(feature = "no_function", feature = "no_module"))]
|
#[cfg(any(feature = "no_function", feature = "no_module"))]
|
||||||
let is_global = false;
|
let is_global = false;
|
||||||
|
|
||||||
if settings.options.contains(LangOptions::STRICT_VAR)
|
if settings.has_option(LangOptions::STRICT_VAR)
|
||||||
&& index.is_none()
|
&& index.is_none()
|
||||||
&& !is_global
|
&& !is_global
|
||||||
&& !state.global_imports.iter().any(|m| m.as_str() == root)
|
&& !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) {
|
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))
|
return Err(PERR::PropertyExpected.into_err(pos))
|
||||||
}
|
}
|
||||||
(Token::Identifier(s) | Token::StringConstant(s), 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 stmt = self.parse_stmt(input, state, lib, settings.level_up())?;
|
||||||
let need_comma = !stmt.is_self_terminated();
|
let need_comma = !stmt.is_self_terminated();
|
||||||
|
|
||||||
@ -1358,7 +1382,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// { - block statement as expression
|
// { - 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())? {
|
match self.parse_block(input, state, lib, settings.level_up())? {
|
||||||
block @ Stmt::Block(..) => Expr::Stmt(Box::new(block.into())),
|
block @ Stmt::Block(..) => Expr::Stmt(Box::new(block.into())),
|
||||||
stmt => unreachable!("Stmt::Block expected but gets {:?}", stmt),
|
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())?,
|
Token::LeftParen => self.parse_paren_expr(input, state, lib, settings.level_up())?,
|
||||||
|
|
||||||
// If statement is allowed to act as expressions
|
// 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())?
|
self.parse_if(input, state, lib, settings.level_up())?
|
||||||
.into(),
|
.into(),
|
||||||
)),
|
)),
|
||||||
// Loops are allowed to act as expressions
|
// 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(
|
Expr::Stmt(Box::new(
|
||||||
self.parse_while_loop(input, state, lib, settings.level_up())?
|
self.parse_while_loop(input, state, lib, settings.level_up())?
|
||||||
.into(),
|
.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())?
|
self.parse_do(input, state, lib, settings.level_up())?
|
||||||
.into(),
|
.into(),
|
||||||
)),
|
)),
|
||||||
Token::For if settings.options.contains(LangOptions::LOOP_EXPR) => {
|
Token::For if settings.has_option(LangOptions::LOOP_EXPR) => Expr::Stmt(Box::new(
|
||||||
Expr::Stmt(Box::new(
|
|
||||||
self.parse_for(input, state, lib, settings.level_up())?
|
self.parse_for(input, state, lib, settings.level_up())?
|
||||||
.into(),
|
.into(),
|
||||||
))
|
)),
|
||||||
}
|
|
||||||
// Switch statement is allowed to act as expressions
|
// Switch statement is allowed to act as expressions
|
||||||
Token::Switch if settings.options.contains(LangOptions::SWITCH_EXPR) => {
|
Token::Switch if settings.has_option(LangOptions::SWITCH_EXPR) => Expr::Stmt(Box::new(
|
||||||
Expr::Stmt(Box::new(
|
|
||||||
self.parse_switch(input, state, lib, settings.level_up())?
|
self.parse_switch(input, state, lib, settings.level_up())?
|
||||||
.into(),
|
.into(),
|
||||||
))
|
)),
|
||||||
}
|
|
||||||
|
|
||||||
// | ...
|
// | ...
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[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
|
// Build new parse state
|
||||||
let interned_strings = std::mem::take(&mut state.interned_strings);
|
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();
|
new_state.max_expr_depth = self.max_function_expr_depth();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut options = self.options;
|
#[cfg(not(feature = "no_closure"))]
|
||||||
options.set(
|
let options = self.options & !LangOptions::STRICT_VAR; // A capturing closure can access variables not defined locally
|
||||||
LangOptions::STRICT_VAR,
|
#[cfg(feature = "no_closure")]
|
||||||
if cfg!(feature = "no_closure") {
|
let options = self.options | (settings.options & LangOptions::STRICT_VAR);
|
||||||
settings.options.contains(LangOptions::STRICT_VAR)
|
|
||||||
} else {
|
let mut flags = (settings.flags
|
||||||
// A capturing closure can access variables not defined locally
|
& !ParseSettingFlags::GLOBAL_LEVEL
|
||||||
false
|
& ParseSettingFlags::BREAKABLE)
|
||||||
},
|
| ParseSettingFlags::FN_SCOPE;
|
||||||
);
|
|
||||||
|
#[cfg(not(feature = "no_closure"))]
|
||||||
|
{
|
||||||
|
flags |= ParseSettingFlags::CLOSURE_SCOPE;
|
||||||
|
}
|
||||||
|
|
||||||
let new_settings = ParseSettings {
|
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,
|
level: 0,
|
||||||
|
flags,
|
||||||
options,
|
options,
|
||||||
..settings
|
..settings
|
||||||
};
|
};
|
||||||
@ -1465,8 +1485,8 @@ impl Engine {
|
|||||||
|
|
||||||
if !is_func
|
if !is_func
|
||||||
&& index.is_none()
|
&& index.is_none()
|
||||||
&& !settings.in_closure
|
&& !settings.has_flag(ParseSettingFlags::CLOSURE_SCOPE)
|
||||||
&& settings.options.contains(LangOptions::STRICT_VAR)
|
&& settings.has_option(LangOptions::STRICT_VAR)
|
||||||
&& !state.scope.contains(name)
|
&& !state.scope.contains(name)
|
||||||
{
|
{
|
||||||
// If the parent scope is not inside another capturing closure
|
// If the parent scope is not inside another capturing closure
|
||||||
@ -1612,7 +1632,7 @@ impl Engine {
|
|||||||
if !is_property
|
if !is_property
|
||||||
&& !is_func
|
&& !is_func
|
||||||
&& index.is_none()
|
&& index.is_none()
|
||||||
&& settings.options.contains(LangOptions::STRICT_VAR)
|
&& settings.has_option(LangOptions::STRICT_VAR)
|
||||||
&& !state.scope.contains(&s)
|
&& !state.scope.contains(&s)
|
||||||
{
|
{
|
||||||
return Err(
|
return Err(
|
||||||
@ -1656,11 +1676,13 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
// Access to `this` as a variable is OK within a function scope
|
// Access to `this` as a variable is OK within a function scope
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[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, ns, 0, state.get_interned_string(*s)).into(),
|
||||||
None,
|
None,
|
||||||
settings.pos,
|
settings.pos,
|
||||||
),
|
)
|
||||||
|
}
|
||||||
// Cannot access to `this` as a variable not in a function scope
|
// Cannot access to `this` as a variable not in a function scope
|
||||||
_ if &*s == KEYWORD_THIS => {
|
_ if &*s == KEYWORD_THIS => {
|
||||||
let msg = format!("'{s}' can only be used in functions");
|
let msg = format!("'{s}' can only be used in functions");
|
||||||
@ -1852,7 +1874,7 @@ impl Engine {
|
|||||||
#[cfg(any(feature = "no_function", feature = "no_module"))]
|
#[cfg(any(feature = "no_function", feature = "no_module"))]
|
||||||
let is_global = false;
|
let is_global = false;
|
||||||
|
|
||||||
if settings.options.contains(LangOptions::STRICT_VAR)
|
if settings.has_option(LangOptions::STRICT_VAR)
|
||||||
&& index.is_none()
|
&& index.is_none()
|
||||||
&& !is_global
|
&& !is_global
|
||||||
&& !state.global_imports.iter().any(|m| m.as_str() == root)
|
&& !state.global_imports.iter().any(|m| m.as_str() == root)
|
||||||
@ -2399,12 +2421,12 @@ impl Engine {
|
|||||||
Token::Or => {
|
Token::Or => {
|
||||||
let rhs = op_base.args.pop().unwrap().ensure_bool_expr()?;
|
let rhs = op_base.args.pop().unwrap().ensure_bool_expr()?;
|
||||||
let lhs = 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 => {
|
Token::And => {
|
||||||
let rhs = op_base.args.pop().unwrap().ensure_bool_expr()?;
|
let rhs = op_base.args.pop().unwrap().ensure_bool_expr()?;
|
||||||
let lhs = 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 => {
|
Token::DoubleQuestion => {
|
||||||
let rhs = op_base.args.pop().unwrap();
|
let rhs = op_base.args.pop().unwrap();
|
||||||
@ -2590,9 +2612,7 @@ impl Engine {
|
|||||||
},
|
},
|
||||||
s => match input.next().expect(NEVER_ENDS) {
|
s => match input.next().expect(NEVER_ENDS) {
|
||||||
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
||||||
(Token::Identifier(t), ..)
|
(Token::Identifier(t) | Token::Reserved(t) | Token::Custom(t), ..)
|
||||||
| (Token::Reserved(t), ..)
|
|
||||||
| (Token::Custom(t), ..)
|
|
||||||
if *t == s =>
|
if *t == s =>
|
||||||
{
|
{
|
||||||
segments.push(required_token.clone());
|
segments.push(required_token.clone());
|
||||||
@ -2726,7 +2746,7 @@ impl Engine {
|
|||||||
token => unreachable!("Token::While or Token::Loop expected but gets {:?}", token),
|
token => unreachable!("Token::While or Token::Loop expected but gets {:?}", token),
|
||||||
};
|
};
|
||||||
settings.pos = token_pos;
|
settings.pos = token_pos;
|
||||||
settings.is_breakable = true;
|
settings.flags |= ParseSettingFlags::BREAKABLE;
|
||||||
|
|
||||||
let body = self.parse_block(input, state, lib, settings.level_up())?;
|
let body = self.parse_block(input, state, lib, settings.level_up())?;
|
||||||
|
|
||||||
@ -2749,7 +2769,7 @@ impl Engine {
|
|||||||
settings.pos = eat_token(input, Token::Do);
|
settings.pos = eat_token(input, Token::Do);
|
||||||
|
|
||||||
// do { body } [while|until] guard
|
// 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 body = self.parse_block(input, state, lib, settings.level_up())?;
|
||||||
|
|
||||||
let negated = match input.next().expect(NEVER_ENDS) {
|
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")?;
|
ensure_not_statement_expr(input, "a boolean")?;
|
||||||
let guard = self
|
let guard = self
|
||||||
@ -2859,7 +2879,7 @@ impl Engine {
|
|||||||
pos: name_pos,
|
pos: name_pos,
|
||||||
};
|
};
|
||||||
|
|
||||||
settings.is_breakable = true;
|
settings.flags |= ParseSettingFlags::BREAKABLE;
|
||||||
let body = self.parse_block(input, state, lib, settings.level_up())?;
|
let body = self.parse_block(input, state, lib, settings.level_up())?;
|
||||||
|
|
||||||
state.stack.rewind(prev_stack_len);
|
state.stack.rewind(prev_stack_len);
|
||||||
@ -3089,7 +3109,7 @@ impl Engine {
|
|||||||
|
|
||||||
let mut statements = StaticVec::new_const();
|
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())?;
|
let stmt = self.parse_expr_stmt(input, state, lib, settings.level_up())?;
|
||||||
statements.push(stmt);
|
statements.push(stmt);
|
||||||
|
|
||||||
@ -3126,7 +3146,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse statements inside the block
|
// 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())?;
|
let stmt = self.parse_stmt(input, state, lib, settings.level_up())?;
|
||||||
|
|
||||||
@ -3222,7 +3242,7 @@ impl Engine {
|
|||||||
unreachable!("doc-comment expected but gets {:?}", comment);
|
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));
|
return Err(PERR::WrongDocComment.into_err(comments_pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3264,7 +3284,7 @@ impl Engine {
|
|||||||
|
|
||||||
// fn ...
|
// fn ...
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[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))
|
Err(PERR::WrongFnDefinition.into_err(token_pos))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3307,20 +3327,14 @@ impl Engine {
|
|||||||
new_state.max_expr_depth = self.max_function_expr_depth();
|
new_state.max_expr_depth = self.max_function_expr_depth();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut options = self.options;
|
let options = self.options | (settings.options & LangOptions::STRICT_VAR);
|
||||||
options.set(
|
|
||||||
LangOptions::STRICT_VAR,
|
let flags = ParseSettingFlags::FN_SCOPE
|
||||||
settings.options.contains(LangOptions::STRICT_VAR),
|
| (settings.flags
|
||||||
);
|
& ParseSettingFlags::DISALLOW_UNQUOTED_MAP_PROPERTIES);
|
||||||
|
|
||||||
let new_settings = ParseSettings {
|
let new_settings = ParseSettings {
|
||||||
at_global_level: false,
|
flags,
|
||||||
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,
|
|
||||||
level: 0,
|
level: 0,
|
||||||
options,
|
options,
|
||||||
pos,
|
pos,
|
||||||
@ -3377,11 +3391,15 @@ impl Engine {
|
|||||||
self.parse_for(input, state, lib, settings.level_up())
|
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);
|
let pos = eat_token(input, Token::Continue);
|
||||||
Ok(Stmt::BreakLoop(None, ASTFlags::NONE, pos))
|
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 pos = eat_token(input, Token::Break);
|
||||||
|
|
||||||
let expr = match input.peek().expect(NEVER_ENDS) {
|
let expr = match input.peek().expect(NEVER_ENDS) {
|
||||||
@ -3424,7 +3442,9 @@ impl Engine {
|
|||||||
// `return`/`throw` at <EOF>
|
// `return`/`throw` at <EOF>
|
||||||
(Token::EOF, ..) => Ok(Stmt::Return(None, return_type, token_pos)),
|
(Token::EOF, ..) => Ok(Stmt::Return(None, return_type, token_pos)),
|
||||||
// `return`/`throw` at end of block
|
// `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))
|
Ok(Stmt::Return(None, return_type, token_pos))
|
||||||
}
|
}
|
||||||
// `return;` or `throw;`
|
// `return;` or `throw;`
|
||||||
@ -3446,7 +3466,7 @@ impl Engine {
|
|||||||
Token::Import => self.parse_import(input, state, lib, settings.level_up()),
|
Token::Import => self.parse_import(input, state, lib, settings.level_up()),
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[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))
|
Err(PERR::WrongExport.into_err(token_pos))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3607,7 +3627,7 @@ impl Engine {
|
|||||||
// Parse function body
|
// Parse function body
|
||||||
let body = match input.peek().expect(NEVER_ENDS) {
|
let body = match input.peek().expect(NEVER_ENDS) {
|
||||||
(Token::LeftBrace, ..) => {
|
(Token::LeftBrace, ..) => {
|
||||||
settings.is_breakable = false;
|
settings.flags &= !ParseSettingFlags::BREAKABLE;
|
||||||
self.parse_block(input, state, lib, settings.level_up())?
|
self.parse_block(input, state, lib, settings.level_up())?
|
||||||
}
|
}
|
||||||
(.., pos) => return Err(PERR::FnMissingBody(name.into()).into_err(*pos)),
|
(.., pos) => return Err(PERR::FnMissingBody(name.into()).into_err(*pos)),
|
||||||
@ -3759,7 +3779,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse function body
|
// Parse function body
|
||||||
settings.is_breakable = false;
|
settings.flags &= !ParseSettingFlags::BREAKABLE;
|
||||||
let body = self.parse_stmt(input, state, lib, settings.level_up())?;
|
let body = self.parse_stmt(input, state, lib, settings.level_up())?;
|
||||||
|
|
||||||
// External variables may need to be processed in a consistent order,
|
// External variables may need to be processed in a consistent order,
|
||||||
@ -3822,22 +3842,16 @@ impl Engine {
|
|||||||
) -> ParseResult<AST> {
|
) -> ParseResult<AST> {
|
||||||
let mut functions = StraightHashMap::default();
|
let mut functions = StraightHashMap::default();
|
||||||
|
|
||||||
let mut options = self.options;
|
let mut options = self.options & !LangOptions::STMT_EXPR & !LangOptions::LOOP_EXPR;
|
||||||
options.remove(LangOptions::STMT_EXPR | LangOptions::LOOP_EXPR);
|
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
options.remove(LangOptions::ANON_FN);
|
{
|
||||||
|
options &= !LangOptions::ANON_FN;
|
||||||
|
}
|
||||||
|
|
||||||
let mut settings = ParseSettings {
|
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,
|
level: 0,
|
||||||
|
flags: ParseSettingFlags::GLOBAL_LEVEL
|
||||||
|
| ParseSettingFlags::DISALLOW_STATEMENTS_IN_BLOCKS,
|
||||||
options,
|
options,
|
||||||
pos: Position::START,
|
pos: Position::START,
|
||||||
};
|
};
|
||||||
@ -3883,18 +3897,11 @@ impl Engine {
|
|||||||
) -> ParseResult<(StmtBlockContainer, StaticVec<Shared<ScriptFnDef>>)> {
|
) -> ParseResult<(StmtBlockContainer, StaticVec<Shared<ScriptFnDef>>)> {
|
||||||
let mut statements = StmtBlockContainer::new_const();
|
let mut statements = StmtBlockContainer::new_const();
|
||||||
let mut functions = StraightHashMap::default();
|
let mut functions = StraightHashMap::default();
|
||||||
|
|
||||||
let mut settings = ParseSettings {
|
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,
|
level: 0,
|
||||||
|
flags: ParseSettingFlags::GLOBAL_LEVEL,
|
||||||
|
options: self.options,
|
||||||
pos: Position::START,
|
pos: Position::START,
|
||||||
};
|
};
|
||||||
process_settings(&mut settings);
|
process_settings(&mut settings);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#![cfg(feature = "metadata")]
|
#![cfg(feature = "metadata")]
|
||||||
|
|
||||||
use crate::api::type_names::format_type;
|
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 crate::{calc_fn_hash, Engine, FnAccess, SmartString, StaticVec, AST};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
@ -174,10 +174,16 @@ pub fn gen_metadata_to_json(
|
|||||||
global.modules.insert(name, m.as_ref().into());
|
global.modules.insert(name, m.as_ref().into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let exclude_flags = if !include_standard_packages {
|
||||||
|
ModuleFlags::STANDARD_LIB
|
||||||
|
} else {
|
||||||
|
ModuleFlags::empty()
|
||||||
|
};
|
||||||
|
|
||||||
engine
|
engine
|
||||||
.global_modules
|
.global_modules
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|m| include_standard_packages || !m.standard)
|
.filter(|m| !m.flags.contains(exclude_flags))
|
||||||
.flat_map(|m| m.iter_fn())
|
.flat_map(|m| m.iter_fn())
|
||||||
.for_each(|f| {
|
.for_each(|f| {
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
|
@ -966,18 +966,16 @@ impl Token {
|
|||||||
use Token::*;
|
use Token::*;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
LexError(..) |
|
|
||||||
SemiColon | // ; - is unary
|
SemiColon | // ; - is unary
|
||||||
Colon | // #{ foo: - is unary
|
Colon | // #{ foo: - is unary
|
||||||
Comma | // ( ... , -expr ) - is unary
|
Comma | // ( ... , -expr ) - is unary
|
||||||
//Period |
|
//Period |
|
||||||
//Elvis |
|
//Elvis |
|
||||||
//DoubleQuestion |
|
DoubleQuestion | // ?? - is unary
|
||||||
//QuestionBracket |
|
|
||||||
ExclusiveRange | // .. - is unary
|
ExclusiveRange | // .. - is unary
|
||||||
InclusiveRange | // ..= - is unary
|
InclusiveRange | // ..= - is unary
|
||||||
LeftBrace | // { -expr } - is unary
|
LeftBrace | // { -expr } - is unary
|
||||||
// RightBrace | { expr } - expr not unary & is closing
|
// RightBrace | // { expr } - expr not unary & is closing
|
||||||
LeftParen | // ( -expr ) - is unary
|
LeftParen | // ( -expr ) - is unary
|
||||||
// RightParen | // ( expr ) - expr not unary & is closing
|
// RightParen | // ( expr ) - expr not unary & is closing
|
||||||
LeftBracket | // [ -expr ] - is unary
|
LeftBracket | // [ -expr ] - is unary
|
||||||
@ -1024,6 +1022,11 @@ impl Token {
|
|||||||
Return |
|
Return |
|
||||||
Throw => true,
|
Throw => true,
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_index"))]
|
||||||
|
QuestionBracket => true, // ?[ - is unary
|
||||||
|
|
||||||
|
LexError(..) => true,
|
||||||
|
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ fn test_fn_ptr_curry_call() -> Result<(), Box<EvalAltResult>> {
|
|||||||
|
|
||||||
engine.register_raw_fn(
|
engine.register_raw_fn(
|
||||||
"call_with_arg",
|
"call_with_arg",
|
||||||
&[TypeId::of::<FnPtr>(), TypeId::of::<INT>()],
|
[TypeId::of::<FnPtr>(), TypeId::of::<INT>()],
|
||||||
|context, args| {
|
|context, args| {
|
||||||
let fn_ptr = std::mem::take(args[0]).cast::<FnPtr>();
|
let fn_ptr = std::mem::take(args[0]).cast::<FnPtr>();
|
||||||
fn_ptr.call_raw(&context, None, [std::mem::take(args[1])])
|
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(
|
engine.register_raw_fn(
|
||||||
"custom_call",
|
"custom_call",
|
||||||
&[TypeId::of::<INT>(), TypeId::of::<FnPtr>()],
|
[TypeId::of::<INT>(), TypeId::of::<FnPtr>()],
|
||||||
|context, args| {
|
|context, args| {
|
||||||
let func = take(args[1]).cast::<FnPtr>();
|
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 p1 = Rc::new(RefCell::new(41));
|
||||||
let p2 = Rc::new(RefCell::new(1));
|
let p2 = Rc::new(RefCell::new(1));
|
||||||
|
|
||||||
f(p1.clone(), p2.clone())?;
|
f(p1.clone(), p2)?;
|
||||||
|
|
||||||
assert_eq!(*p1.borrow(), 42);
|
assert_eq!(*p1.borrow(), 42);
|
||||||
|
|
||||||
|
@ -274,8 +274,7 @@ fn test_custom_syntax_raw() -> Result<(), Box<EvalAltResult>> {
|
|||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
s => Err(LexError::ImproperSymbol(s.to_string(), String::new())
|
s => Err(LexError::ImproperSymbol(s.to_string(), String::new())
|
||||||
.into_err(Position::NONE)
|
.into_err(Position::NONE)),
|
||||||
.into()),
|
|
||||||
},
|
},
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user