Mark simple functions const.

This commit is contained in:
Stephen Chung 2021-06-28 18:06:05 +08:00
parent 0c99165007
commit e40e81ac1a
16 changed files with 243 additions and 210 deletions

View File

@ -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<F: Float> FloatWrapper<F> {
/// 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<F: Float> FloatWrapper<F> {
#[cfg(not(feature = "no_float"))]
impl FloatWrapper<FLOAT> {
/// 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.

View File

@ -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

View File

@ -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::<u8>() {
@ -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<T: Variant + Clone>(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::<T>() == TypeId::of::<Dynamic>() {
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<bool> 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<INT> 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<FLOAT> 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<FloatWrapper<FLOAT>> for Dynamic {
#[inline(always)]
fn from(value: FloatWrapper<FLOAT>) -> 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<Decimal> for Dynamic {
impl From<char> 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<S: Into<ImmutableString>> From<S> 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<T: Variant + Clone> From<Vec<T>> for Dynamic {
fn from(value: Vec<T>) -> Self {
Self(Union::Array(
Box::new(value.into_iter().map(Dynamic::from).collect()),
DEFAULT_TAG,
DEFAULT_TAG_VALUE,
ReadWrite,
))
}
@ -1947,7 +1944,7 @@ impl<T: Variant + Clone> 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<T: Variant + Clone> std::iter::FromIterator<T> for Dynamic {
fn from_iter<X: IntoIterator<Item = T>>(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<K: Into<crate::Identifier>, T: Variant + Clone> From<std::collections::Hash
.map(|(k, v)| (k.into(), Dynamic::from(v)))
.collect(),
),
DEFAULT_TAG,
DEFAULT_TAG_VALUE,
ReadWrite,
))
}
@ -2003,7 +2000,7 @@ impl<K: Into<crate::Identifier>, T: Variant + Clone> From<std::collections::BTre
.map(|(k, v)| (k.into(), Dynamic::from(v)))
.collect(),
),
DEFAULT_TAG,
DEFAULT_TAG_VALUE,
ReadWrite,
))
}
@ -2011,26 +2008,30 @@ impl<K: Into<crate::Identifier>, T: Variant + Clone> From<std::collections::BTre
impl From<FnPtr> 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<Box<FnPtr>> for Dynamic {
#[inline(always)]
fn from(value: Box<FnPtr>) -> Self {
Self(Union::FnPtr(value, DEFAULT_TAG, ReadWrite))
Self(Union::FnPtr(value, DEFAULT_TAG_VALUE, ReadWrite))
}
}
#[cfg(not(feature = "no_std"))]
impl From<Instant> 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<crate::Shared<crate::Locked<Dynamic>>> for Dynamic {
#[inline(always)]
fn from(value: crate::Shared<crate::Locked<Self>>) -> Self {
Self(Union::Shared(value.into(), DEFAULT_TAG, ReadWrite))
Self(Union::Shared(value.into(), DEFAULT_TAG_VALUE, ReadWrite))
}
}

View File

@ -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")]

View File

@ -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`].
///

View File

@ -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,

View File

@ -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?

View File

@ -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))
}

View File

@ -108,6 +108,6 @@ pub fn calc_fn_params_hash(params: impl Iterator<Item = TypeId>) -> 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
}

View File

@ -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<FnAny> {
pub fn get_native_fn(&self) -> Option<&Shared<FnAny>> {
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<crate::ast::ScriptFnDef> {
pub const fn get_script_fn_def(&self) -> Option<&Shared<crate::ast::ScriptFnDef>> {
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<IteratorFn> {
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<FnPlugin> {
pub fn get_plugin_fn<'s>(&'s self) -> Option<&Shared<FnPlugin>> {
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`].

View File

@ -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.

View File

@ -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<NonZeroUsize> {
pub(crate) const fn index(&self) -> Option<NonZeroUsize> {
self.index
}
/// Set the [`Scope`][crate::Scope] index offset.

View File

@ -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.

View File

@ -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<u64, Shared<ScriptFnDef>>;
/// 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<NonZeroUsize>,
) -> 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);
}

View File

@ -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<Box<StaticVec<Identifier>>>)>,
}
@ -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`].
///

View File

@ -41,7 +41,7 @@ pub type TokenizerControl = Rc<Cell<TokenizerControlBlock>>;
type LERR = LexError;
/// Separator character for numbers.
const NUM_SEP: char = '_';
const NUMBER_SEPARATOR: char = '_';
/// A stream of tokens.
pub type TokenStream<'a> = Peekable<TokenIterator<'a>>;
@ -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<Self> {
pub const fn map_op_assignment(&self) -> Option<Self> {
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<Self> {
pub const fn make_op_assignment(&self) -> Option<Self> {
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<Precedence> {
pub const fn precedence(&self) -> Option<Precedence> {
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