diff --git a/src/syntax.rs b/src/syntax.rs index 16e95695..edc1b9b3 100644 --- a/src/syntax.rs +++ b/src/syntax.rs @@ -1,13 +1,16 @@ //! Module implementing custom syntax for [`Engine`]. use crate::ast::Expr; +use crate::dynamic::Variant; use crate::engine::EvalContext; use crate::fn_native::SendSync; +use crate::r#unsafe::unsafe_try_cast; use crate::token::{is_valid_identifier, Token}; use crate::{ - Dynamic, Engine, Identifier, ImmutableString, LexError, ParseError, Position, RhaiResult, - Shared, StaticVec, + Engine, Identifier, ImmutableString, LexError, ParseError, Position, RhaiResult, Shared, + StaticVec, INT, }; +use std::any::TypeId; #[cfg(feature = "no_std")] use std::prelude::v1::*; @@ -67,10 +70,53 @@ impl Expression<'_> { self.0.position() } /// Get the value of this expression if it is a literal constant. + /// Supports [`INT`][crate::INT], [`FLOAT`][crate::FLOAT], `()`, `char`, `bool` and + /// [`ImmutableString`][crate::ImmutableString]. + /// + /// Returns [`None`] also if the constant is not of the specified type. #[inline(always)] #[must_use] - pub fn get_literal_value(&self) -> Option { - self.0.get_literal_value() + pub fn get_literal_value(&self) -> Option { + // Coded this way in order to maximally leverage potentials for dead-code removal. + + if TypeId::of::() == TypeId::of::() { + return match self.0 { + Expr::IntegerConstant(x, _) => unsafe_try_cast(*x).ok(), + _ => None, + }; + } + #[cfg(not(feature = "no_float"))] + if TypeId::of::() == TypeId::of::() { + return match self.0 { + Expr::FloatConstant(x, _) => unsafe_try_cast(*x).ok(), + _ => None, + }; + } + if TypeId::of::() == TypeId::of::() { + return match self.0 { + Expr::CharConstant(x, _) => unsafe_try_cast(*x).ok(), + _ => None, + }; + } + if TypeId::of::() == TypeId::of::() { + return match self.0 { + Expr::StringConstant(x, _) => unsafe_try_cast(x.clone()).ok(), + _ => None, + }; + } + if TypeId::of::() == TypeId::of::() { + return match self.0 { + Expr::BoolConstant(x, _) => unsafe_try_cast(*x).ok(), + _ => None, + }; + } + if TypeId::of::() == TypeId::of::<()>() { + return match self.0 { + Expr::Unit(_) => unsafe_try_cast(()).ok(), + _ => None, + }; + } + None } } diff --git a/tests/syntax.rs b/tests/syntax.rs index 8fbeedb5..a0ce0ab8 100644 --- a/tests/syntax.rs +++ b/tests/syntax.rs @@ -24,7 +24,7 @@ fn test_custom_syntax() -> Result<(), Box> { true, |context, inputs| { let var_name = inputs[0].get_variable_name().unwrap().to_string(); - let max = inputs[1].get_literal_value().unwrap().as_int().unwrap(); + let max = inputs[1].get_literal_value::().unwrap(); let stmt = inputs.get(2).unwrap(); let condition = inputs.get(3).unwrap();