diff --git a/src/ast.rs b/src/ast.rs index 3748d061..7d6309f8 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -911,7 +911,7 @@ impl StmtBlock { /// Get the position of this statements block. #[inline(always)] #[must_use] - pub fn position(&self) -> Position { + pub const fn position(&self) -> Position { self.1 } /// Get the statements of this statements block. @@ -1044,7 +1044,7 @@ impl Stmt { /// Is this statement [`Noop`][Stmt::Noop]? #[inline(always)] #[must_use] - pub fn is_noop(&self) -> bool { + pub const fn is_noop(&self) -> bool { match self { Self::Noop(_) => true, _ => false, @@ -1117,7 +1117,7 @@ impl Stmt { } /// Does this statement return a value? #[must_use] - pub fn returns_value(&self) -> bool { + pub const fn returns_value(&self) -> bool { match self { Self::If(_, _, _) | Self::Switch(_, _, _) @@ -1142,12 +1142,12 @@ impl Stmt { Self::Import(_, _, _) | Self::Export(_, _) => false, #[cfg(not(feature = "no_closure"))] - Self::Share(_) => unreachable!("Stmt::Share should not be parsed"), + Self::Share(_) => false, } } /// Is this statement self-terminated (i.e. no need for a semicolon terminator)? #[must_use] - pub fn is_self_terminated(&self) -> bool { + pub const fn is_self_terminated(&self) -> bool { match self { Self::If(_, _, _) | Self::Switch(_, _, _) @@ -1173,7 +1173,7 @@ impl Stmt { Self::Import(_, _, _) | Self::Export(_, _) => false, #[cfg(not(feature = "no_closure"))] - Self::Share(_) => unreachable!("Stmt::Share should not be parsed"), + Self::Share(_) => false, } } /// Is this statement _pure_? @@ -1247,7 +1247,7 @@ impl Stmt { /// All statements following this statement will essentially be dead code. #[inline(always)] #[must_use] - pub fn is_control_flow_break(&self) -> bool { + pub const fn is_control_flow_break(&self) -> bool { match self { Self::Return(_, _, _) | Self::Break(_) | Self::Continue(_) => true, _ => false, @@ -1512,7 +1512,7 @@ impl FnCallHashes { /// Create a [`FnCallHashes`] with only the native Rust hash. #[inline(always)] #[must_use] - pub fn from_native(hash: u64) -> Self { + pub const fn from_native(hash: u64) -> Self { Self { script: None, native: hash, @@ -1521,7 +1521,7 @@ impl FnCallHashes { /// Create a [`FnCallHashes`] with both native Rust and script function hashes set to the same value. #[inline(always)] #[must_use] - pub fn from_script(hash: u64) -> Self { + pub const fn from_script(hash: u64) -> Self { Self { script: Some(hash), native: hash, @@ -1530,7 +1530,7 @@ impl FnCallHashes { /// Create a [`FnCallHashes`] with both native Rust and script function hashes. #[inline(always)] #[must_use] - pub fn from_script_and_native(script: u64, native: u64) -> Self { + pub const fn from_script_and_native(script: u64, native: u64) -> Self { Self { script: Some(script), native, @@ -1539,7 +1539,7 @@ impl FnCallHashes { /// Is this [`FnCallHashes`] native Rust only? #[inline(always)] #[must_use] - pub fn is_native_only(&self) -> bool { + pub const fn is_native_only(&self) -> bool { self.script.is_none() } } @@ -1570,7 +1570,7 @@ impl FnCallExpr { /// Does this function call contain a qualified namespace? #[inline(always)] #[must_use] - pub fn is_qualified(&self) -> bool { + pub const fn is_qualified(&self) -> bool { self.namespace.is_some() } /// Convert this into a [`FnCall`][Expr::FnCall]. @@ -1683,6 +1683,7 @@ impl FloatWrapper { /// Minimum floating-point number for natural display before switching to scientific notation. pub const MIN_NATURAL_FLOAT_FOR_DISPLAY: f32 = 0.0000000000001; + /// Create a new [`FloatWrapper`]. #[inline(always)] #[must_use] pub fn new(value: F) -> Self { @@ -1692,6 +1693,7 @@ impl FloatWrapper { #[cfg(not(feature = "no_float"))] impl FloatWrapper { + /// Create a new [`FloatWrapper`]. #[inline(always)] #[must_use] pub(crate) const fn const_new(value: FLOAT) -> Self { @@ -1928,7 +1930,7 @@ impl Expr { /// Is the expression a simple variable access? #[inline(always)] #[must_use] - pub(crate) fn is_variable_access(&self, non_qualified: bool) -> bool { + pub(crate) const fn is_variable_access(&self, non_qualified: bool) -> bool { match self { Self::Variable(_, _, x) => !non_qualified || x.1.is_none(), _ => false, @@ -2038,7 +2040,7 @@ impl Expr { /// Is the expression the unit `()` literal? #[inline(always)] #[must_use] - pub fn is_unit(&self) -> bool { + pub const fn is_unit(&self) -> bool { match self { Self::Unit(_) => true, _ => false, @@ -2070,7 +2072,7 @@ impl Expr { /// Is a particular [token][Token] allowed as a postfix operator to this expression? #[inline] #[must_use] - pub fn is_valid_postfix(&self, token: &Token) -> bool { + pub const fn is_valid_postfix(&self, token: &Token) -> bool { match token { #[cfg(not(feature = "no_object"))] Token::Period => return true, @@ -2120,7 +2122,7 @@ impl Expr { Self::Custom(_, _) => false, - Self::Stack(_, _) => unreachable!("Expr::Stack should not occur naturally"), + Self::Stack(_, _) => false, } } /// Recursively walk this expression. diff --git a/src/custom_syntax.rs b/src/custom_syntax.rs index edc1b9b3..3b3b18a0 100644 --- a/src/custom_syntax.rs +++ b/src/custom_syntax.rs @@ -14,14 +14,21 @@ use std::any::TypeId; #[cfg(feature = "no_std")] use std::prelude::v1::*; -pub const MARKER_EXPR: &str = "$expr$"; -pub const MARKER_BLOCK: &str = "$block$"; -pub const MARKER_IDENT: &str = "$ident$"; -pub const MARKER_STRING: &str = "$string$"; -pub const MARKER_INT: &str = "$int$"; +/// Special marker for matching an expression. +pub const CUSTOM_SYNTAX_MARKER_EXPR: &str = "$expr$"; +/// Special marker for matching a statements block. +pub const CUSTOM_SYNTAX_MARKER_BLOCK: &str = "$block$"; +/// Special marker for matching an identifier. +pub const CUSTOM_SYNTAX_MARKER_IDENT: &str = "$ident$"; +/// Special marker for matching a string literal. +pub const CUSTOM_SYNTAX_MARKER_STRING: &str = "$string$"; +/// Special marker for matching an integer number. +pub const CUSTOM_SYNTAX_MARKER_INT: &str = "$int$"; +/// Special marker for matching a floating-point number. #[cfg(not(feature = "no_float"))] -pub const MARKER_FLOAT: &str = "$float$"; -pub const MARKER_BOOL: &str = "$bool$"; +pub const CUSTOM_SYNTAX_MARKER_FLOAT: &str = "$float$"; +/// Special marker for matching a boolean value. +pub const CUSTOM_SYNTAX_MARKER_BOOL: &str = "$bool$"; /// A general expression evaluation trait object. #[cfg(not(feature = "sync"))] @@ -185,7 +192,7 @@ impl Engine { for s in keywords { let s = s.as_ref().trim(); - // skip empty keywords + // Skip empty keywords if s.is_empty() { continue; } @@ -194,15 +201,19 @@ impl Engine { let seg = match s { // Markers not in first position - MARKER_IDENT | MARKER_EXPR | MARKER_BLOCK | MARKER_BOOL | MARKER_INT - | MARKER_STRING + CUSTOM_SYNTAX_MARKER_IDENT + | CUSTOM_SYNTAX_MARKER_EXPR + | CUSTOM_SYNTAX_MARKER_BLOCK + | CUSTOM_SYNTAX_MARKER_BOOL + | CUSTOM_SYNTAX_MARKER_INT + | CUSTOM_SYNTAX_MARKER_STRING if !segments.is_empty() => { s.into() } // Markers not in first position #[cfg(not(feature = "no_float"))] - MARKER_FLOAT if !segments.is_empty() => s.into(), + CUSTOM_SYNTAX_MARKER_FLOAT if !segments.is_empty() => s.into(), // Standard or reserved keyword/symbol not in first position s if !segments.is_empty() && token.is_some() => { // Make it a custom keyword/symbol if it is disabled or reserved diff --git a/src/dynamic.rs b/src/dynamic.rs index 49d5de9d..584e33ac 100644 --- a/src/dynamic.rs +++ b/src/dynamic.rs @@ -33,6 +33,7 @@ use fmt::Debug; #[cfg(any(target_arch = "wasm32", target_arch = "wasm64"))] use instant::Instant; +/// The message: never fails because the type was checked const CHECKED: &str = "never fails because the type was checked"; mod private { @@ -164,7 +165,7 @@ pub type Tag = i32; pub type Tag = i16; /// Default tag value for [`Dynamic`]. -const DEFAULT_TAG: Tag = 0; +const DEFAULT_TAG_VALUE: Tag = 0; /// Dynamic type containing any value. pub struct Dynamic(pub(crate) Union); @@ -711,8 +712,6 @@ impl fmt::Debug for Dynamic { let _value_any = (***value).as_any(); let _type_id = _value_any.type_id(); - const CHECKED: &str = "never fails because the type was checked"; - #[cfg(not(feature = "only_i32"))] #[cfg(not(feature = "only_i64"))] if _type_id == TypeId::of::() { @@ -819,28 +818,28 @@ impl Default for Dynamic { impl Dynamic { /// A [`Dynamic`] containing a `()`. - pub const UNIT: Dynamic = Self(Union::Unit((), DEFAULT_TAG, ReadWrite)); + pub const UNIT: Dynamic = Self(Union::Unit((), DEFAULT_TAG_VALUE, ReadWrite)); /// A [`Dynamic`] containing a `true`. - pub const TRUE: Dynamic = Self(Union::Bool(true, DEFAULT_TAG, ReadWrite)); + pub const TRUE: Dynamic = Self(Union::Bool(true, DEFAULT_TAG_VALUE, ReadWrite)); /// A [`Dynamic`] containing a [`false`]. - pub const FALSE: Dynamic = Self(Union::Bool(false, DEFAULT_TAG, ReadWrite)); + pub const FALSE: Dynamic = Self(Union::Bool(false, DEFAULT_TAG_VALUE, ReadWrite)); /// A [`Dynamic`] containing the integer zero. - pub const ZERO: Dynamic = Self(Union::Int(0, DEFAULT_TAG, ReadWrite)); + pub const ZERO: Dynamic = Self(Union::Int(0, DEFAULT_TAG_VALUE, ReadWrite)); /// A [`Dynamic`] containing the integer one. - pub const ONE: Dynamic = Self(Union::Int(1, DEFAULT_TAG, ReadWrite)); + pub const ONE: Dynamic = Self(Union::Int(1, DEFAULT_TAG_VALUE, ReadWrite)); /// A [`Dynamic`] containing the integer two. - pub const TWO: Dynamic = Self(Union::Int(2, DEFAULT_TAG, ReadWrite)); + pub const TWO: Dynamic = Self(Union::Int(2, DEFAULT_TAG_VALUE, ReadWrite)); /// A [`Dynamic`] containing the integer ten. - pub const TEN: Dynamic = Self(Union::Int(10, DEFAULT_TAG, ReadWrite)); + pub const TEN: Dynamic = Self(Union::Int(10, DEFAULT_TAG_VALUE, ReadWrite)); /// A [`Dynamic`] containing the integer negative one. - pub const NEGATIVE_ONE: Dynamic = Self(Union::Int(-1, DEFAULT_TAG, ReadWrite)); + pub const NEGATIVE_ONE: Dynamic = Self(Union::Int(-1, DEFAULT_TAG_VALUE, ReadWrite)); /// A [`Dynamic`] containing `0.0`. /// /// Not available under `no_float`. #[cfg(not(feature = "no_float"))] pub const FLOAT_ZERO: Dynamic = Self(Union::Float( FloatWrapper::const_new(0.0), - DEFAULT_TAG, + DEFAULT_TAG_VALUE, ReadWrite, )); /// A [`Dynamic`] containing `1.0`. @@ -849,7 +848,7 @@ impl Dynamic { #[cfg(not(feature = "no_float"))] pub const FLOAT_ONE: Dynamic = Self(Union::Float( FloatWrapper::const_new(1.0), - DEFAULT_TAG, + DEFAULT_TAG_VALUE, ReadWrite, )); /// A [`Dynamic`] containing `2.0`. @@ -858,7 +857,7 @@ impl Dynamic { #[cfg(not(feature = "no_float"))] pub const FLOAT_TWO: Dynamic = Self(Union::Float( FloatWrapper::const_new(2.0), - DEFAULT_TAG, + DEFAULT_TAG_VALUE, ReadWrite, )); /// A [`Dynamic`] containing `10.0`. @@ -867,7 +866,7 @@ impl Dynamic { #[cfg(not(feature = "no_float"))] pub const FLOAT_TEN: Dynamic = Self(Union::Float( FloatWrapper::const_new(10.0), - DEFAULT_TAG, + DEFAULT_TAG_VALUE, ReadWrite, )); /// A [`Dynamic`] containing the `-1.0`. @@ -876,7 +875,7 @@ impl Dynamic { #[cfg(not(feature = "no_float"))] pub const FLOAT_NEGATIVE_ONE: Dynamic = Self(Union::Float( FloatWrapper::const_new(-1.0), - DEFAULT_TAG, + DEFAULT_TAG_VALUE, ReadWrite, )); @@ -1043,8 +1042,6 @@ impl Dynamic { pub fn from(mut value: T) -> Self { // Coded this way in order to maximally leverage potentials for dead-code removal. - const CHECKED: &str = "never fails because the type was checked"; - if TypeId::of::() == TypeId::of::() { return unsafe_try_cast::<_, Dynamic>(value).ok().expect(CHECKED); } @@ -1125,7 +1122,7 @@ impl Dynamic { Self(Union::Variant( Box::new(Box::new(value)), - DEFAULT_TAG, + DEFAULT_TAG_VALUE, ReadWrite, )) } @@ -1153,7 +1150,7 @@ impl Dynamic { Union::Shared(_, _, _) => self, _ => Self(Union::Shared( crate::Locked::new(self).into(), - DEFAULT_TAG, + DEFAULT_TAG_VALUE, _access, )), } @@ -1857,33 +1854,33 @@ impl Dynamic { impl From<()> for Dynamic { #[inline(always)] fn from(value: ()) -> Self { - Self(Union::Unit(value, DEFAULT_TAG, ReadWrite)) + Self(Union::Unit(value, DEFAULT_TAG_VALUE, ReadWrite)) } } impl From for Dynamic { #[inline(always)] fn from(value: bool) -> Self { - Self(Union::Bool(value, DEFAULT_TAG, ReadWrite)) + Self(Union::Bool(value, DEFAULT_TAG_VALUE, ReadWrite)) } } impl From for Dynamic { #[inline(always)] fn from(value: INT) -> Self { - Self(Union::Int(value, DEFAULT_TAG, ReadWrite)) + Self(Union::Int(value, DEFAULT_TAG_VALUE, ReadWrite)) } } #[cfg(not(feature = "no_float"))] impl From for Dynamic { #[inline(always)] fn from(value: FLOAT) -> Self { - Self(Union::Float(value.into(), DEFAULT_TAG, ReadWrite)) + Self(Union::Float(value.into(), DEFAULT_TAG_VALUE, ReadWrite)) } } #[cfg(not(feature = "no_float"))] impl From> for Dynamic { #[inline(always)] fn from(value: FloatWrapper) -> Self { - Self(Union::Float(value, DEFAULT_TAG, ReadWrite)) + Self(Union::Float(value, DEFAULT_TAG_VALUE, ReadWrite)) } } #[cfg(feature = "decimal")] @@ -1900,13 +1897,13 @@ impl From for Dynamic { impl From for Dynamic { #[inline(always)] fn from(value: char) -> Self { - Self(Union::Char(value, DEFAULT_TAG, ReadWrite)) + Self(Union::Char(value, DEFAULT_TAG_VALUE, ReadWrite)) } } impl> From for Dynamic { #[inline(always)] fn from(value: S) -> Self { - Self(Union::Str(value.into(), DEFAULT_TAG, ReadWrite)) + Self(Union::Str(value.into(), DEFAULT_TAG_VALUE, ReadWrite)) } } impl From<&ImmutableString> for Dynamic { @@ -1927,7 +1924,7 @@ impl Dynamic { /// Create a [`Dynamic`] from an [`Array`]. #[inline(always)] pub(crate) fn from_array(array: Array) -> Self { - Self(Union::Array(Box::new(array), DEFAULT_TAG, ReadWrite)) + Self(Union::Array(Box::new(array), DEFAULT_TAG_VALUE, ReadWrite)) } } #[cfg(not(feature = "no_index"))] @@ -1936,7 +1933,7 @@ impl From> for Dynamic { fn from(value: Vec) -> Self { Self(Union::Array( Box::new(value.into_iter().map(Dynamic::from).collect()), - DEFAULT_TAG, + DEFAULT_TAG_VALUE, ReadWrite, )) } @@ -1947,7 +1944,7 @@ impl From<&[T]> for Dynamic { fn from(value: &[T]) -> Self { Self(Union::Array( Box::new(value.iter().cloned().map(Dynamic::from).collect()), - DEFAULT_TAG, + DEFAULT_TAG_VALUE, ReadWrite, )) } @@ -1958,7 +1955,7 @@ impl std::iter::FromIterator for Dynamic { fn from_iter>(iter: X) -> Self { Self(Union::Array( Box::new(iter.into_iter().map(Dynamic::from).collect()), - DEFAULT_TAG, + DEFAULT_TAG_VALUE, ReadWrite, )) } @@ -1968,7 +1965,7 @@ impl Dynamic { /// Create a [`Dynamic`] from a [`Map`]. #[inline(always)] pub(crate) fn from_map(map: Map) -> Self { - Self(Union::Map(Box::new(map), DEFAULT_TAG, ReadWrite)) + Self(Union::Map(Box::new(map), DEFAULT_TAG_VALUE, ReadWrite)) } } #[cfg(not(feature = "no_object"))] @@ -1985,7 +1982,7 @@ impl, T: Variant + Clone> From, T: Variant + Clone> From, T: Variant + Clone> From for Dynamic { #[inline(always)] fn from(value: FnPtr) -> Self { - Self(Union::FnPtr(Box::new(value), DEFAULT_TAG, ReadWrite)) + Self(Union::FnPtr(Box::new(value), DEFAULT_TAG_VALUE, ReadWrite)) } } impl From> for Dynamic { #[inline(always)] fn from(value: Box) -> Self { - Self(Union::FnPtr(value, DEFAULT_TAG, ReadWrite)) + Self(Union::FnPtr(value, DEFAULT_TAG_VALUE, ReadWrite)) } } #[cfg(not(feature = "no_std"))] impl From for Dynamic { #[inline(always)] fn from(value: Instant) -> Self { - Self(Union::TimeStamp(Box::new(value), DEFAULT_TAG, ReadWrite)) + Self(Union::TimeStamp( + Box::new(value), + DEFAULT_TAG_VALUE, + ReadWrite, + )) } } #[cfg(not(feature = "no_closure"))] impl From>> for Dynamic { #[inline(always)] fn from(value: crate::Shared>) -> Self { - Self(Union::Shared(value.into(), DEFAULT_TAG, ReadWrite)) + Self(Union::Shared(value.into(), DEFAULT_TAG_VALUE, ReadWrite)) } } diff --git a/src/engine_api.rs b/src/engine_api.rs index fff7aca6..c012e3b7 100644 --- a/src/engine_api.rs +++ b/src/engine_api.rs @@ -2064,7 +2064,12 @@ impl Engine { .lib() .iter_fn() .filter(|f| f.func.is_script()) - .map(|f| f.func.get_fn_def().clone()) + .map(|f| { + f.func + .get_script_fn_def() + .expect("never fails because the function is scripted") + .clone() + }) .collect(); #[cfg(feature = "no_function")] diff --git a/src/engine_settings.rs b/src/engine_settings.rs index fb16e9fd..dbadafd9 100644 --- a/src/engine_settings.rs +++ b/src/engine_settings.rs @@ -50,7 +50,7 @@ impl Engine { #[cfg(not(feature = "no_function"))] #[inline(always)] #[must_use] - pub fn max_call_levels(&self) -> usize { + pub const fn max_call_levels(&self) -> usize { self.limits.max_call_stack_depth } /// Set the maximum number of operations allowed for a script to run to avoid @@ -69,8 +69,12 @@ impl Engine { #[cfg(not(feature = "unchecked"))] #[inline(always)] #[must_use] - pub fn max_operations(&self) -> u64 { - self.limits.max_operations.map_or(0, NonZeroU64::get) + pub const fn max_operations(&self) -> u64 { + if let Some(n) = self.limits.max_operations { + n.get() + } else { + 0 + } } /// Set the maximum number of imported [modules][crate::Module] allowed for a script. /// @@ -89,7 +93,7 @@ impl Engine { #[cfg(not(feature = "no_module"))] #[inline(always)] #[must_use] - pub fn max_modules(&self) -> usize { + pub const fn max_modules(&self) -> usize { self.limits.max_modules } /// Set the depth limits for expressions (0 for unlimited). @@ -115,8 +119,12 @@ impl Engine { #[cfg(not(feature = "unchecked"))] #[inline(always)] #[must_use] - pub fn max_expr_depth(&self) -> usize { - self.limits.max_expr_depth.map_or(0, NonZeroUsize::get) + pub const fn max_expr_depth(&self) -> usize { + if let Some(n) = self.limits.max_expr_depth { + n.get() + } else { + 0 + } } /// The depth limit for expressions in functions (0 for unlimited). /// @@ -125,10 +133,12 @@ impl Engine { #[cfg(not(feature = "no_function"))] #[inline(always)] #[must_use] - pub fn max_function_expr_depth(&self) -> usize { - self.limits - .max_function_expr_depth - .map_or(0, NonZeroUsize::get) + pub const fn max_function_expr_depth(&self) -> usize { + if let Some(n) = self.limits.max_function_expr_depth { + n.get() + } else { + 0 + } } /// Set the maximum length of [strings][crate::ImmutableString] (0 for unlimited). /// @@ -145,8 +155,12 @@ impl Engine { #[cfg(not(feature = "unchecked"))] #[inline(always)] #[must_use] - pub fn max_string_size(&self) -> usize { - self.limits.max_string_size.map_or(0, NonZeroUsize::get) + pub const fn max_string_size(&self) -> usize { + if let Some(n) = self.limits.max_string_size { + n.get() + } else { + 0 + } } /// Set the maximum length of [arrays][crate::Array] (0 for unlimited). /// @@ -166,7 +180,11 @@ impl Engine { #[inline(always)] #[must_use] pub fn max_array_size(&self) -> usize { - self.limits.max_array_size.map_or(0, NonZeroUsize::get) + if let Some(n) = self.limits.max_array_size { + n.get() + } else { + 0 + } } /// Set the maximum size of [object maps][crate::Map] (0 for unlimited). /// @@ -185,8 +203,12 @@ impl Engine { #[cfg(not(feature = "no_object"))] #[inline(always)] #[must_use] - pub fn max_map_size(&self) -> usize { - self.limits.max_map_size.map_or(0, NonZeroUsize::get) + pub const fn max_map_size(&self) -> usize { + if let Some(n) = self.limits.max_map_size { + n.get() + } else { + 0 + } } /// Set the module resolution service used by the [`Engine`]. /// diff --git a/src/error.rs b/src/error.rs index 61edc035..6dd09b70 100644 --- a/src/error.rs +++ b/src/error.rs @@ -237,19 +237,15 @@ impl EvalAltResult { /// /// [`LoopBreak`][EvalAltResult::LoopBreak] and [`Return`][EvalAltResult::Return] are pseudo errors. #[must_use] - pub fn is_pseudo_error(&self) -> bool { + pub const fn is_pseudo_error(&self) -> bool { match self { Self::LoopBreak(_, _) | Self::Return(_, _) => true, _ => false, } } /// Can this error be caught? - /// - /// # Panics - /// - /// Panics when [`LoopBreak`][EvalAltResult::LoopBreak] or [`Return`][EvalAltResult::Return]. #[must_use] - pub fn is_catchable(&self) -> bool { + pub const fn is_catchable(&self) -> bool { match self { Self::ErrorSystem(_, _) => false, Self::ErrorParsing(_, _) => false, @@ -279,17 +275,12 @@ impl EvalAltResult { | Self::ErrorDataTooLarge(_, _) | Self::ErrorTerminated(_, _) => false, - Self::LoopBreak(_, _) => panic!("EvalAltResult::LoopBreak should not occur naturally"), - Self::Return(_, _) => panic!("EvalAltResult::Return should not occur naturally"), + Self::LoopBreak(_, _) | Self::Return(_, _) => false, } } /// Is this error a system exception? - /// - /// # Panics - /// - /// Panics when [`LoopBreak`][EvalAltResult::LoopBreak] or [`Return`][EvalAltResult::Return]. #[must_use] - pub fn is_system_exception(&self) -> bool { + pub const fn is_system_exception(&self) -> bool { match self { Self::ErrorSystem(_, _) => true, Self::ErrorParsing(_, _) => true, @@ -301,9 +292,6 @@ impl EvalAltResult { Self::ErrorTerminated(_, _) => true, - Self::LoopBreak(_, _) => panic!("EvalAltResult::LoopBreak should not occur naturally"), - Self::Return(_, _) => panic!("EvalAltResult::Return should not occur naturally"), - _ => false, } } @@ -377,7 +365,7 @@ impl EvalAltResult { } /// Get the [position][Position] of this error. #[must_use] - pub fn position(&self) -> Position { + pub const fn position(&self) -> Position { match self { Self::ErrorSystem(_, _) => Position::NONE, diff --git a/src/fn_builtin.rs b/src/fn_builtin.rs index d01e8381..3d4346bf 100644 --- a/src/fn_builtin.rs +++ b/src/fn_builtin.rs @@ -14,6 +14,7 @@ use crate::FLOAT; #[cfg(feature = "decimal")] use rust_decimal::Decimal; +/// The message: never fails because this is built-in code and the type is already checked const BUILTIN: &str = "never fails because this is built-in code and the type is already checked"; /// Is the type a numeric type? diff --git a/src/fn_call.rs b/src/fn_call.rs index a0310c0c..b0693fad 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -302,9 +302,13 @@ impl Engine { let result = if func.is_plugin_fn() { func.get_plugin_fn() + .expect("never fails because the function is a plugin") .call((self, name, source, mods, lib).into(), args) } else { - func.get_native_fn()((self, name, source, mods, lib).into(), args) + let func = func + .get_native_fn() + .expect("never fails because the function is native"); + func((self, name, source, mods, lib).into(), args) }; // Restore the original reference @@ -681,7 +685,9 @@ impl Engine { // Script function call assert!(func.is_script()); - let func = func.get_fn_def(); + let func = func + .get_script_fn_def() + .expect("never fails because the function is scripted"); if func.body.is_empty() { return Ok((Dynamic::UNIT, false)); @@ -1384,7 +1390,9 @@ impl Engine { match func { #[cfg(not(feature = "no_function"))] Some(f) if f.is_script() => { - let fn_def = f.get_fn_def(); + let fn_def = f + .get_script_fn_def() + .expect("never fails because the function is scripted"); if fn_def.body.is_empty() { Ok(Dynamic::UNIT) @@ -1408,12 +1416,16 @@ impl Engine { Some(f) if f.is_plugin_fn() => f .get_plugin_fn() + .expect("never fails because the function is a plugin") .clone() .call((self, fn_name, module.id(), &*mods, lib).into(), &mut args) .map_err(|err| err.fill_position(pos)), Some(f) if f.is_native() => { - f.get_native_fn()((self, fn_name, module.id(), &*mods, lib).into(), &mut args) + let func = f + .get_native_fn() + .expect("never fails because the function is native"); + func((self, fn_name, module.id(), &*mods, lib).into(), &mut args) .map_err(|err| err.fill_position(pos)) } diff --git a/src/fn_hash.rs b/src/fn_hash.rs index e74d0a9b..c503daf5 100644 --- a/src/fn_hash.rs +++ b/src/fn_hash.rs @@ -108,6 +108,6 @@ pub fn calc_fn_params_hash(params: impl Iterator) -> u64 { /// Combine two [`u64`] hashes by taking the XOR of them. #[inline(always)] #[must_use] -pub(crate) fn combine_hashes(a: u64, b: u64) -> u64 { +pub(crate) const fn combine_hashes(a: u64, b: u64) -> u64 { a ^ b } diff --git a/src/fn_native.rs b/src/fn_native.rs index 95fa9f94..6ca637d5 100644 --- a/src/fn_native.rs +++ b/src/fn_native.rs @@ -89,7 +89,7 @@ impl<'a> NativeCallContext<'a> { /// Create a new [`NativeCallContext`]. #[inline(always)] #[must_use] - pub fn new(engine: &'a Engine, fn_name: &'a str, lib: &'a [&Module]) -> Self { + pub const fn new(engine: &'a Engine, fn_name: &'a str, lib: &'a [&Module]) -> Self { Self { engine, fn_name, @@ -106,7 +106,7 @@ impl<'a> NativeCallContext<'a> { #[cfg(not(feature = "no_module"))] #[inline(always)] #[must_use] - pub fn new_with_all_fields( + pub const fn new_with_all_fields( engine: &'a Engine, fn_name: &'a str, source: &'a Option<&str>, @@ -124,19 +124,19 @@ impl<'a> NativeCallContext<'a> { /// The current [`Engine`]. #[inline(always)] #[must_use] - pub fn engine(&self) -> &Engine { + pub const fn engine(&self) -> &Engine { self.engine } /// Name of the function called. #[inline(always)] #[must_use] - pub fn fn_name(&self) -> &str { + pub const fn fn_name(&self) -> &str { self.fn_name } /// The current source. #[inline(always)] #[must_use] - pub fn source(&self) -> Option<&str> { + pub const fn source(&self) -> Option<&str> { self.source } /// Get an iterator over the current set of modules imported via `import` statements. @@ -166,7 +166,7 @@ impl<'a> NativeCallContext<'a> { #[cfg(not(feature = "no_module"))] #[inline(always)] #[must_use] - pub fn imports(&self) -> Option<&Imports> { + pub const fn imports(&self) -> Option<&Imports> { self.mods } /// Get an iterator over the namespaces containing definitions of all script-defined functions. @@ -180,7 +180,7 @@ impl<'a> NativeCallContext<'a> { #[cfg(feature = "internals")] #[inline(always)] #[must_use] - pub fn namespaces(&self) -> &[&Module] { + pub const fn namespaces(&self) -> &[&Module] { self.lib } /// Call a function inside the call context. @@ -457,74 +457,51 @@ impl CallableFunction { } } /// Get a shared reference to a native Rust function. - /// - /// # Panics - /// - /// Panics if the [`CallableFunction`] is not [`Pure`][CallableFunction::Pure] or - /// [`Method`][CallableFunction::Method]. #[inline(always)] #[must_use] - pub fn get_native_fn(&self) -> &Shared { + pub fn get_native_fn(&self) -> Option<&Shared> { match self { - Self::Pure(f) | Self::Method(f) => f, - Self::Iterator(_) | Self::Plugin(_) => panic!("function should be native"), + Self::Pure(f) | Self::Method(f) => Some(f), + Self::Iterator(_) | Self::Plugin(_) => None, #[cfg(not(feature = "no_function"))] - Self::Script(_) => panic!("function should be native"), + Self::Script(_) => None, } } /// Get a shared reference to a script-defined function definition. /// /// Not available under `no_function`. - /// - /// # Panics - /// - /// Panics if the [`CallableFunction`] is not [`Script`][CallableFunction::Script]. #[cfg(not(feature = "no_function"))] #[inline(always)] #[must_use] - pub fn get_fn_def(&self) -> &Shared { + pub const fn get_script_fn_def(&self) -> Option<&Shared> { match self { - Self::Pure(_) | Self::Method(_) | Self::Iterator(_) | Self::Plugin(_) => { - panic!("function should be scripted") - } - Self::Script(f) => f, + Self::Pure(_) | Self::Method(_) | Self::Iterator(_) | Self::Plugin(_) => None, + Self::Script(f) => Some(f), } } /// Get a reference to an iterator function. - /// - /// # Panics - /// - /// Panics if the [`CallableFunction`] is not [`Iterator`][CallableFunction::Iterator]. #[inline(always)] #[must_use] - pub fn get_iter_fn(&self) -> IteratorFn { + pub fn get_iter_fn(&self) -> Option { match self { - Self::Iterator(f) => *f, - Self::Pure(_) | Self::Method(_) | Self::Plugin(_) => { - panic!("function should an iterator") - } + Self::Iterator(f) => Some(*f), + Self::Pure(_) | Self::Method(_) | Self::Plugin(_) => None, #[cfg(not(feature = "no_function"))] - Self::Script(_) => panic!("function should be an iterator"), + Self::Script(_) => None, } } /// Get a shared reference to a plugin function. - /// - /// # Panics - /// - /// Panics if the [`CallableFunction`] is not [`Plugin`][CallableFunction::Plugin]. #[inline(always)] #[must_use] - pub fn get_plugin_fn<'s>(&'s self) -> &Shared { + pub fn get_plugin_fn<'s>(&'s self) -> Option<&Shared> { match self { - Self::Plugin(f) => f, - Self::Pure(_) | Self::Method(_) | Self::Iterator(_) => { - panic!("function should a plugin") - } + Self::Plugin(f) => Some(f), + Self::Pure(_) | Self::Method(_) | Self::Iterator(_) => None, #[cfg(not(feature = "no_function"))] - Self::Script(_) => panic!("function should a plugin"), + Self::Script(_) => None, } } /// Create a new [`CallableFunction::Pure`]. diff --git a/src/fn_ptr.rs b/src/fn_ptr.rs index fefe90ba..77544d38 100644 --- a/src/fn_ptr.rs +++ b/src/fn_ptr.rs @@ -38,7 +38,7 @@ impl FnPtr { /// Get the name of the function. #[inline(always)] #[must_use] - pub(crate) fn get_fn_name(&self) -> &Identifier { + pub(crate) const fn get_fn_name(&self) -> &Identifier { &self.0 } /// Get the underlying data of the function pointer. diff --git a/src/module/mod.rs b/src/module/mod.rs index 07a2d070..f23b883f 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -278,7 +278,7 @@ impl Module { /// Get the ID of the [`Module`] as an [`Identifier`], if any. #[inline(always)] #[must_use] - pub(crate) fn id_raw(&self) -> Option<&Identifier> { + pub(crate) const fn id_raw(&self) -> Option<&Identifier> { self.id.as_ref() } @@ -358,7 +358,7 @@ impl Module { /// ``` #[inline(always)] #[must_use] - pub fn is_indexed(&self) -> bool { + pub const fn is_indexed(&self) -> bool { self.indexed } @@ -508,7 +508,7 @@ impl Module { self.functions .values() .find(|f| f.params == num_params && f.name == name) - .map(|f| f.func.get_fn_def()) + .and_then(|f| f.func.get_script_fn_def()) } /// Get a mutable reference to the underlying [`BTreeMap`] of sub-modules. @@ -1341,7 +1341,9 @@ impl Module { f.access, f.name.as_str(), f.params, - f.func.get_fn_def(), + f.func + .get_script_fn_def() + .expect("never fails because the function is scripted"), ) }) } @@ -1466,7 +1468,12 @@ impl Module { .filter(|f| f.func.is_script()) .for_each(|f| { // Encapsulate AST environment - let mut func = f.func.get_fn_def().as_ref().clone(); + let mut func = f + .func + .get_script_fn_def() + .expect("never fails because the function is scripted") + .as_ref() + .clone(); func.lib = Some(ast.shared_lib()); func.mods = func_mods.clone(); module.set_script_fn(func); @@ -1725,7 +1732,7 @@ impl NamespaceRef { /// Get the [`Scope`][crate::Scope] index offset. #[inline(always)] #[must_use] - pub(crate) fn index(&self) -> Option { + pub(crate) const fn index(&self) -> Option { self.index } /// Set the [`Scope`][crate::Scope] index offset. diff --git a/src/optimize.rs b/src/optimize.rs index 8d3054bf..1282f92a 100644 --- a/src/optimize.rs +++ b/src/optimize.rs @@ -61,7 +61,7 @@ struct State<'a> { impl<'a> State<'a> { /// Create a new State. #[inline(always)] - pub fn new( + pub const fn new( engine: &'a Engine, lib: &'a [&'a Module], optimization_level: OptimizationLevel, @@ -87,7 +87,7 @@ impl<'a> State<'a> { } /// Is the [`AST`] dirty (i.e. changed)? #[inline(always)] - pub fn is_dirty(&self) -> bool { + pub const fn is_dirty(&self) -> bool { self.changed } /// Prune the list of constants back to a specified size. diff --git a/src/parse.rs b/src/parse.rs index ece916a4..13a48ce7 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -5,7 +5,8 @@ use crate::ast::{ ScriptFnDef, Stmt, StmtBlock, }; use crate::custom_syntax::{ - CustomSyntax, MARKER_BLOCK, MARKER_BOOL, MARKER_EXPR, MARKER_IDENT, MARKER_INT, MARKER_STRING, + CustomSyntax, CUSTOM_SYNTAX_MARKER_BLOCK, CUSTOM_SYNTAX_MARKER_BOOL, CUSTOM_SYNTAX_MARKER_EXPR, + CUSTOM_SYNTAX_MARKER_IDENT, CUSTOM_SYNTAX_MARKER_INT, CUSTOM_SYNTAX_MARKER_STRING, }; use crate::dynamic::{AccessMode, Union}; use crate::engine::{Precedence, KEYWORD_THIS, OP_CONTAINS}; @@ -29,7 +30,7 @@ use std::{ }; #[cfg(not(feature = "no_float"))] -use crate::{custom_syntax::MARKER_FLOAT, FLOAT}; +use crate::{custom_syntax::CUSTOM_SYNTAX_MARKER_FLOAT, FLOAT}; #[cfg(not(feature = "no_function"))] use crate::FnAccess; @@ -38,6 +39,10 @@ type PERR = ParseErrorType; type FunctionsLib = BTreeMap>; +/// Invalid variable name that acts as a search barrier in a [`Scope`]. +const SCOPE_SEARCH_BARRIER_MARKER: &str = "$BARRIER$"; + +/// The message: never fails because `TokenStream` never ends const NEVER_ENDS: &str = "never fails because `TokenStream` never ends"; /// A factory of identifiers from text strings. @@ -147,8 +152,8 @@ impl<'e> ParseState<'e> { .rev() .enumerate() .find(|(_, (n, _))| { - if n.is_empty() { - // Do not go beyond empty variable names + if n == SCOPE_SEARCH_BARRIER_MARKER { + // Do not go beyond the barrier barrier = true; false } else { @@ -230,7 +235,7 @@ impl ParseSettings { /// Create a new `ParseSettings` with one higher expression level. #[inline(always)] #[must_use] - pub fn level_up(&self) -> Self { + pub const fn level_up(&self) -> Self { Self { level: self.level + 1, ..*self @@ -244,8 +249,10 @@ impl ParseSettings { &self, limit: Option, ) -> Result<(), ParseError> { - if limit.map(|limit| self.level > limit.get()).unwrap_or(false) { - return Err(PERR::ExprTooDeep.into_err(self.pos)); + if let Some(limit) = limit { + if self.level > limit.get() { + return Err(PERR::ExprTooDeep.into_err(self.pos)); + } } Ok(()) } @@ -1894,7 +1901,7 @@ fn parse_custom_syntax( // Add an empty variable name to the stack. // Empty variable names act as a barrier so earlier variables will not be matched. // Variable searches stop at the first empty variable name. - let empty = state.get_identifier(""); + let empty = state.get_identifier(SCOPE_SEARCH_BARRIER_MARKER); state.stack.push((empty, AccessMode::ReadWrite)); } @@ -1915,32 +1922,32 @@ fn parse_custom_syntax( }; match required_token.as_str() { - MARKER_IDENT => { + CUSTOM_SYNTAX_MARKER_IDENT => { let (name, pos) = parse_var_name(input)?; let name = state.get_identifier(name); segments.push(name.clone().into()); - tokens.push(state.get_identifier(MARKER_IDENT)); + tokens.push(state.get_identifier(CUSTOM_SYNTAX_MARKER_IDENT)); keywords.push(Expr::Variable(None, pos, Box::new((None, None, name)))); } - MARKER_EXPR => { + CUSTOM_SYNTAX_MARKER_EXPR => { keywords.push(parse_expr(input, state, lib, settings)?); - let keyword = state.get_identifier(MARKER_EXPR); + let keyword = state.get_identifier(CUSTOM_SYNTAX_MARKER_EXPR); segments.push(keyword.clone().into()); tokens.push(keyword); } - MARKER_BLOCK => match parse_block(input, state, lib, settings)? { + CUSTOM_SYNTAX_MARKER_BLOCK => match parse_block(input, state, lib, settings)? { block @ Stmt::Block(_, _) => { keywords.push(Expr::Stmt(Box::new(block.into()))); - let keyword = state.get_identifier(MARKER_BLOCK); + let keyword = state.get_identifier(CUSTOM_SYNTAX_MARKER_BLOCK); segments.push(keyword.clone().into()); tokens.push(keyword); } stmt => unreachable!("expecting Stmt::Block, but gets {:?}", stmt), }, - MARKER_BOOL => match input.next().expect(NEVER_ENDS) { + CUSTOM_SYNTAX_MARKER_BOOL => match input.next().expect(NEVER_ENDS) { (b @ Token::True, pos) | (b @ Token::False, pos) => { keywords.push(Expr::BoolConstant(b == Token::True, pos)); - let keyword = state.get_identifier(MARKER_BOOL); + let keyword = state.get_identifier(CUSTOM_SYNTAX_MARKER_BOOL); segments.push(keyword.clone().into()); tokens.push(keyword); } @@ -1951,10 +1958,10 @@ fn parse_custom_syntax( ) } }, - MARKER_INT => match input.next().expect(NEVER_ENDS) { + CUSTOM_SYNTAX_MARKER_INT => match input.next().expect(NEVER_ENDS) { (Token::IntegerConstant(i), pos) => { keywords.push(Expr::IntegerConstant(i, pos)); - let keyword = state.get_identifier(MARKER_INT); + let keyword = state.get_identifier(CUSTOM_SYNTAX_MARKER_INT); segments.push(keyword.clone().into()); tokens.push(keyword); } @@ -1966,10 +1973,10 @@ fn parse_custom_syntax( } }, #[cfg(not(feature = "no_float"))] - MARKER_FLOAT => match input.next().expect(NEVER_ENDS) { + CUSTOM_SYNTAX_MARKER_FLOAT => match input.next().expect(NEVER_ENDS) { (Token::FloatConstant(f), pos) => { keywords.push(Expr::FloatConstant(f, pos)); - let keyword = state.get_identifier(MARKER_FLOAT); + let keyword = state.get_identifier(CUSTOM_SYNTAX_MARKER_FLOAT); segments.push(keyword.clone().into()); tokens.push(keyword); } @@ -1980,10 +1987,10 @@ fn parse_custom_syntax( .into_err(pos)) } }, - MARKER_STRING => match input.next().expect(NEVER_ENDS) { + CUSTOM_SYNTAX_MARKER_STRING => match input.next().expect(NEVER_ENDS) { (Token::StringConstant(s), pos) => { keywords.push(Expr::StringConstant(state.get_identifier(s).into(), pos)); - let keyword = state.get_identifier(MARKER_STRING); + let keyword = state.get_identifier(CUSTOM_SYNTAX_MARKER_STRING); segments.push(keyword.clone().into()); tokens.push(keyword); } diff --git a/src/scope.rs b/src/scope.rs index 513a9e89..2fe9bcfb 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -7,7 +7,7 @@ use std::prelude::v1::*; use std::{borrow::Cow, iter::Extend}; /// Keep a number of entries inline (since [`Dynamic`] is usually small enough). -const SCOPE_SIZE: usize = 8; +const SCOPE_ENTRIES_INLINED: usize = 8; /// Type containing information about the current scope. /// Useful for keeping state between [`Engine`][crate::Engine] evaluation runs. @@ -54,7 +54,7 @@ const SCOPE_SIZE: usize = 8; #[derive(Debug, Clone, Hash)] pub struct Scope<'a> { /// Current value of the entry. - values: smallvec::SmallVec<[Dynamic; SCOPE_SIZE]>, + values: smallvec::SmallVec<[Dynamic; SCOPE_ENTRIES_INLINED]>, /// (Name, aliases) of the entry. names: Vec<(Cow<'a, str>, Option>>)>, } @@ -161,7 +161,7 @@ impl<'a> Scope<'a> { #[inline(always)] #[must_use] pub fn is_empty(&self) -> bool { - self.values.len() == 0 + self.values.is_empty() } /// Add (push) a new entry to the [`Scope`]. /// diff --git a/src/token.rs b/src/token.rs index aaac31c7..0e8878fb 100644 --- a/src/token.rs +++ b/src/token.rs @@ -41,7 +41,7 @@ pub type TokenizerControl = Rc>; type LERR = LexError; /// Separator character for numbers. -const NUM_SEP: char = '_'; +const NUMBER_SEPARATOR: char = '_'; /// A stream of tokens. pub type TokenStream<'a> = Peekable>; @@ -110,7 +110,7 @@ impl Position { #[cfg(not(feature = "no_position"))] return Some(self.line as usize); #[cfg(feature = "no_position")] - unreachable!(); + unreachable!("there is no Position"); } } /// Get the character position (1-based), or [`None`] if at beginning of a line. @@ -128,7 +128,7 @@ impl Position { }; #[cfg(feature = "no_position")] - unreachable!(); + unreachable!("there is no Position"); } } /// Advance by one character position. @@ -175,7 +175,7 @@ impl Position { /// Is this [`Position`] at the beginning of a line? #[inline(always)] #[must_use] - pub fn is_beginning_of_line(self) -> bool { + pub const fn is_beginning_of_line(self) -> bool { #[cfg(not(feature = "no_position"))] return self.pos == 0 && !self.is_none(); #[cfg(feature = "no_position")] @@ -184,9 +184,9 @@ impl Position { /// Is there no [`Position`]? #[inline(always)] #[must_use] - pub fn is_none(self) -> bool { + pub const fn is_none(self) -> bool { #[cfg(not(feature = "no_position"))] - return self == Self::NONE; + return self.line == 0 && self.pos == 0; #[cfg(feature = "no_position")] return true; } @@ -467,12 +467,8 @@ pub enum Token { impl Token { /// Get the syntax of the token if it is a keyword. - /// - /// # Panics - /// - /// Panics if the token is not a keyword. #[must_use] - pub fn keyword_syntax(&self) -> &'static str { + pub const fn keyword_syntax(&self) -> &'static str { use Token::*; match self { @@ -556,7 +552,7 @@ impl Token { #[cfg(not(feature = "no_module"))] As => "as", - t => unreachable!("{:?} is not a keyword", t), + _ => "ERROR: NOT A KEYWORD", } } @@ -589,7 +585,7 @@ impl Token { /// Is this token an op-assignment operator? #[inline] #[must_use] - pub fn is_op_assignment(&self) -> bool { + pub const fn is_op_assignment(&self) -> bool { match self { Self::PlusAssign | Self::MinusAssign @@ -608,7 +604,7 @@ impl Token { /// Get the corresponding operator of the token if it is an op-assignment operator. #[must_use] - pub fn map_op_assignment(&self) -> Option { + pub const fn map_op_assignment(&self) -> Option { Some(match self { Self::PlusAssign => Self::Plus, Self::MinusAssign => Self::Minus, @@ -628,7 +624,7 @@ impl Token { /// Has this token a corresponding op-assignment operator? #[inline] #[must_use] - pub fn has_op_assignment(&self) -> bool { + pub const fn has_op_assignment(&self) -> bool { match self { Self::Plus | Self::Minus @@ -647,7 +643,7 @@ impl Token { /// Get the corresponding op-assignment operator of the token. #[must_use] - pub fn make_op_assignment(&self) -> Option { + pub const fn make_op_assignment(&self) -> Option { Some(match self { Self::Plus => Self::PlusAssign, Self::Minus => Self::MinusAssign, @@ -777,7 +773,7 @@ impl Token { // Is this token [`EOF`][Token::EOF]? #[inline(always)] #[must_use] - pub fn is_eof(&self) -> bool { + pub const fn is_eof(&self) -> bool { use Token::*; match self { @@ -789,7 +785,7 @@ impl Token { // If another operator is after these, it's probably an unary operator // (not sure about `fn` name). #[must_use] - pub fn is_next_unary(&self) -> bool { + pub const fn is_next_unary(&self) -> bool { use Token::*; match self { @@ -850,7 +846,7 @@ impl Token { /// Get the precedence number of the token. #[must_use] - pub fn precedence(&self) -> Option { + pub const fn precedence(&self) -> Option { use Token::*; Precedence::new(match self { @@ -885,7 +881,7 @@ impl Token { /// Does an expression bind to the right (instead of left)? #[must_use] - pub fn is_bind_right(&self) -> bool { + pub const fn is_bind_right(&self) -> bool { use Token::*; match self { @@ -906,7 +902,7 @@ impl Token { /// Is this token a standard symbol used in the language? #[must_use] - pub fn is_symbol(&self) -> bool { + pub const fn is_symbol(&self) -> bool { use Token::*; match self { @@ -924,7 +920,7 @@ impl Token { /// Is this token an active standard keyword? #[must_use] - pub fn is_keyword(&self) -> bool { + pub const fn is_keyword(&self) -> bool { use Token::*; match self { @@ -944,7 +940,7 @@ impl Token { /// Is this token a reserved symbol? #[inline(always)] #[must_use] - pub fn is_reserved(&self) -> bool { + pub const fn is_reserved(&self) -> bool { match self { Self::Reserved(_) => true, _ => false, @@ -964,7 +960,7 @@ impl Token { /// Is this token a custom keyword? #[inline(always)] #[must_use] - pub fn is_custom(&self) -> bool { + pub const fn is_custom(&self) -> bool { match self { Self::Custom(_) => true, _ => false, @@ -1435,7 +1431,7 @@ fn get_next_token_inner( while let Some(next_char) = stream.peek_next() { match next_char { - ch if valid(ch) || ch == NUM_SEP => { + ch if valid(ch) || ch == NUMBER_SEPARATOR => { result.push(next_char); eat_next(stream, pos); } @@ -1536,8 +1532,11 @@ fn get_next_token_inner( // Parse number return Some(( if let Some(radix) = radix_base { - let out: String = - result.iter().skip(2).filter(|&&c| c != NUM_SEP).collect(); + let out: String = result + .iter() + .skip(2) + .filter(|&&c| c != NUMBER_SEPARATOR) + .collect(); INT::from_str_radix(&out, radix) .map(Token::IntegerConstant) @@ -1545,7 +1544,8 @@ fn get_next_token_inner( Token::LexError(LERR::MalformedNumber(result.into_iter().collect())) }) } else { - let out: String = result.iter().filter(|&&c| c != NUM_SEP).collect(); + let out: String = + result.iter().filter(|&&c| c != NUMBER_SEPARATOR).collect(); let num = INT::from_str(&out).map(Token::IntegerConstant); // If integer parsing is unnecessary, try float instead