Refine debug print-out.
This commit is contained in:
parent
7ec49a9510
commit
f17a826f99
152
src/ast.rs
152
src/ast.rs
@ -25,6 +25,9 @@ use crate::{
|
|||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
use crate::{stdlib::str::FromStr, FLOAT};
|
use crate::{stdlib::str::FromStr, FLOAT};
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
use num_traits::Float;
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
use crate::Array;
|
use crate::Array;
|
||||||
|
|
||||||
@ -776,7 +779,7 @@ pub struct Ident {
|
|||||||
impl fmt::Debug for Ident {
|
impl fmt::Debug for Ident {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "Ident({:?} @ {:?})", self.name, self.pos)
|
write!(f, "{:?} @ {:?}", self.name, self.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1440,13 +1443,13 @@ impl FnCallExpr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A type that wraps a [`FLOAT`] and implements [`Hash`].
|
/// A type that wraps a floating-point number and implements [`Hash`].
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
#[derive(Clone, Copy, PartialEq, PartialOrd)]
|
#[derive(Clone, Copy, PartialEq, PartialOrd)]
|
||||||
pub struct FloatWrapper(FLOAT);
|
pub struct FloatWrapper<F>(F);
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
impl Hash for FloatWrapper {
|
impl Hash for FloatWrapper<FLOAT> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn hash<H: crate::stdlib::hash::Hasher>(&self, state: &mut H) {
|
fn hash<H: crate::stdlib::hash::Hasher>(&self, state: &mut H) {
|
||||||
self.0.to_ne_bytes().hash(state);
|
self.0.to_ne_bytes().hash(state);
|
||||||
@ -1454,24 +1457,24 @@ impl Hash for FloatWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
impl AsRef<FLOAT> for FloatWrapper {
|
impl<F: Float> AsRef<F> for FloatWrapper<F> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn as_ref(&self) -> &FLOAT {
|
fn as_ref(&self) -> &F {
|
||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
impl AsMut<FLOAT> for FloatWrapper {
|
impl<F: Float> AsMut<F> for FloatWrapper<F> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn as_mut(&mut self) -> &mut FLOAT {
|
fn as_mut(&mut self) -> &mut F {
|
||||||
&mut self.0
|
&mut self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
impl crate::stdlib::ops::Deref for FloatWrapper {
|
impl<F: Float> crate::stdlib::ops::Deref for FloatWrapper<F> {
|
||||||
type Target = FLOAT;
|
type Target = F;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
@ -1480,7 +1483,7 @@ impl crate::stdlib::ops::Deref for FloatWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
impl crate::stdlib::ops::DerefMut for FloatWrapper {
|
impl<F: Float> crate::stdlib::ops::DerefMut for FloatWrapper<F> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
&mut self.0
|
&mut self.0
|
||||||
@ -1488,52 +1491,67 @@ impl crate::stdlib::ops::DerefMut for FloatWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
impl fmt::Debug for FloatWrapper {
|
impl<F: Float + fmt::Display> fmt::Debug for FloatWrapper<F> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
fmt::Display::fmt(self, f)
|
fmt::Display::fmt(&self.0, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
impl fmt::Display for FloatWrapper {
|
impl<F: Float + fmt::Display + fmt::LowerExp + From<f32>> fmt::Display for FloatWrapper<F> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
#[cfg(feature = "no_std")]
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
|
||||||
use num_traits::Float;
|
|
||||||
|
|
||||||
let abs = self.0.abs();
|
let abs = self.0.abs();
|
||||||
if abs > 10000000000000.0 || abs < 0.0000000000001 {
|
if abs > Self::MAX_NATURAL_FLOAT_FOR_DISPLAY.into()
|
||||||
|
|| abs < Self::MIN_NATURAL_FLOAT_FOR_DISPLAY.into()
|
||||||
|
{
|
||||||
write!(f, "{:e}", self.0)
|
write!(f, "{:e}", self.0)
|
||||||
} else {
|
} else {
|
||||||
self.0.fmt(f)
|
fmt::Display::fmt(&self.0, f)?;
|
||||||
|
if abs.fract().is_zero() {
|
||||||
|
f.write_str(".0")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
impl From<FLOAT> for FloatWrapper {
|
impl<F: Float> From<F> for FloatWrapper<F> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(value: FLOAT) -> Self {
|
fn from(value: F) -> Self {
|
||||||
Self::new(value)
|
Self::new(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
impl FromStr for FloatWrapper {
|
impl<F: Float + FromStr> FromStr for FloatWrapper<F> {
|
||||||
type Err = <FLOAT as FromStr>::Err;
|
type Err = <F as FromStr>::Err;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
FLOAT::from_str(s).map(Into::<Self>::into)
|
F::from_str(s).map(Into::<Self>::into)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
impl FloatWrapper {
|
impl<F: Float> FloatWrapper<F> {
|
||||||
|
/// Maximum floating-point number for natural display before switching to scientific notation.
|
||||||
|
pub const MAX_NATURAL_FLOAT_FOR_DISPLAY: f32 = 10000000000000.0;
|
||||||
|
|
||||||
|
/// Minimum floating-point number for natural display before switching to scientific notation.
|
||||||
|
pub const MIN_NATURAL_FLOAT_FOR_DISPLAY: f32 = 0.0000000000001;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub const fn new(value: FLOAT) -> Self {
|
pub fn new(value: F) -> Self {
|
||||||
|
Self(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FloatWrapper<FLOAT> {
|
||||||
|
#[inline(always)]
|
||||||
|
pub(crate) const fn const_new(value: FLOAT) -> Self {
|
||||||
Self(value)
|
Self(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1544,7 +1562,7 @@ impl FloatWrapper {
|
|||||||
/// # Volatile Data Structure
|
/// # Volatile Data Structure
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Debug, Clone, Hash)]
|
#[derive(Clone, Hash)]
|
||||||
pub enum Expr {
|
pub enum Expr {
|
||||||
/// Dynamic constant.
|
/// Dynamic constant.
|
||||||
/// Used to hold either an [`Array`] or [`Map`][crate::Map] literal for quick cloning.
|
/// Used to hold either an [`Array`] or [`Map`][crate::Map] literal for quick cloning.
|
||||||
@ -1556,7 +1574,7 @@ pub enum Expr {
|
|||||||
IntegerConstant(INT, Position),
|
IntegerConstant(INT, Position),
|
||||||
/// Floating-point constant.
|
/// Floating-point constant.
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
FloatConstant(FloatWrapper, Position),
|
FloatConstant(FloatWrapper<FLOAT>, Position),
|
||||||
/// Character constant.
|
/// Character constant.
|
||||||
CharConstant(char, Position),
|
CharConstant(char, Position),
|
||||||
/// [String][ImmutableString] constant.
|
/// [String][ImmutableString] constant.
|
||||||
@ -1613,6 +1631,80 @@ impl Default for Expr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Expr {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::DynamicConstant(value, pos) => write!(f, "{:?} @ {:?}", value, pos),
|
||||||
|
Self::BoolConstant(value, pos) => write!(f, "{} @ {:?}", value, pos),
|
||||||
|
Self::IntegerConstant(value, pos) => write!(f, "{} @ {:?}", value, pos),
|
||||||
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
Self::FloatConstant(value, pos) => write!(f, "{} @ {:?}", value, pos),
|
||||||
|
Self::CharConstant(value, pos) => write!(f, "{:?} @ {:?}", value, pos),
|
||||||
|
Self::StringConstant(value, pos) => write!(f, "{:?} @ {:?}", value, pos),
|
||||||
|
Self::FnPointer(value, pos) => write!(f, "Fn({:?}) @ {:?}", value, pos),
|
||||||
|
Self::Unit(pos) => write!(f, "() @ {:?}", pos),
|
||||||
|
Self::InterpolatedString(x) => {
|
||||||
|
f.write_str("InterpolatedString")?;
|
||||||
|
f.debug_list().entries(x.iter()).finish()
|
||||||
|
}
|
||||||
|
Self::Array(x, pos) => {
|
||||||
|
f.write_str("Array")?;
|
||||||
|
f.debug_list().entries(x.iter()).finish()?;
|
||||||
|
write!(f, " @ {:?}", pos)
|
||||||
|
}
|
||||||
|
Self::Map(x, pos) => {
|
||||||
|
f.write_str("Map")?;
|
||||||
|
f.debug_map()
|
||||||
|
.entries(x.0.iter().map(|(k, v)| (k, v)))
|
||||||
|
.finish()?;
|
||||||
|
write!(f, " @ {:?}", pos)
|
||||||
|
}
|
||||||
|
Self::Variable(i, pos, x) => {
|
||||||
|
f.write_str("Variable(")?;
|
||||||
|
match x.1 {
|
||||||
|
Some((_, ref namespace)) => write!(f, "{}::", namespace)?,
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
write!(f, "{}", x.2)?;
|
||||||
|
match i.map_or_else(|| x.0, |n| NonZeroUsize::new(n.get() as usize)) {
|
||||||
|
Some(n) => write!(f, " [{}]", n)?,
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
write!(f, ") @ {:?}", pos)
|
||||||
|
}
|
||||||
|
Self::Property(x) => write!(f, "Property({:?} @ {:?})", x.2.name, x.2.pos),
|
||||||
|
Self::Stmt(x) => {
|
||||||
|
f.write_str("Stmt")?;
|
||||||
|
f.debug_list().entries(x.statements.iter()).finish()?;
|
||||||
|
write!(f, " @ {:?}", x.pos)
|
||||||
|
}
|
||||||
|
Self::FnCall(x, pos) => {
|
||||||
|
f.debug_tuple("FnCall").field(x).finish()?;
|
||||||
|
write!(f, " @ {:?}", pos)
|
||||||
|
}
|
||||||
|
Self::Dot(x, pos) | Self::Index(x, pos) | Self::And(x, pos) | Self::Or(x, pos) => {
|
||||||
|
let op = match self {
|
||||||
|
Self::Dot(_, _) => "Dot",
|
||||||
|
Self::Index(_, _) => "Index",
|
||||||
|
Self::And(_, _) => "And",
|
||||||
|
Self::Or(_, _) => "Or",
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
f.debug_struct(op)
|
||||||
|
.field("lhs", &x.lhs)
|
||||||
|
.field("rhs", &x.rhs)
|
||||||
|
.finish()?;
|
||||||
|
write!(f, " @ {:?}", pos)
|
||||||
|
}
|
||||||
|
Self::Custom(x, pos) => {
|
||||||
|
f.debug_tuple("Custom").field(x).finish()?;
|
||||||
|
write!(f, " @ {:?}", pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Expr {
|
impl Expr {
|
||||||
/// Get the [`Dynamic`] value of a constant expression.
|
/// Get the [`Dynamic`] value of a constant expression.
|
||||||
///
|
///
|
||||||
@ -1914,7 +2006,7 @@ mod tests {
|
|||||||
assert_eq!(size_of::<Option<ast::Expr>>(), 16);
|
assert_eq!(size_of::<Option<ast::Expr>>(), 16);
|
||||||
assert_eq!(size_of::<ast::Stmt>(), 32);
|
assert_eq!(size_of::<ast::Stmt>(), 32);
|
||||||
assert_eq!(size_of::<Option<ast::Stmt>>(), 32);
|
assert_eq!(size_of::<Option<ast::Stmt>>(), 32);
|
||||||
assert_eq!(size_of::<FnPtr>(), 80);
|
assert_eq!(size_of::<FnPtr>(), 96);
|
||||||
assert_eq!(size_of::<Scope>(), 288);
|
assert_eq!(size_of::<Scope>(), 288);
|
||||||
assert_eq!(size_of::<LexError>(), 56);
|
assert_eq!(size_of::<LexError>(), 56);
|
||||||
assert_eq!(size_of::<ParseError>(), 16);
|
assert_eq!(size_of::<ParseError>(), 16);
|
||||||
|
@ -159,7 +159,7 @@ pub enum Union {
|
|||||||
Int(INT, AccessMode),
|
Int(INT, AccessMode),
|
||||||
/// A floating-point value.
|
/// A floating-point value.
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
Float(FloatWrapper, AccessMode),
|
Float(FloatWrapper<FLOAT>, AccessMode),
|
||||||
/// A fixed-precision decimal value.
|
/// A fixed-precision decimal value.
|
||||||
#[cfg(feature = "decimal")]
|
#[cfg(feature = "decimal")]
|
||||||
Decimal(Box<Decimal>, AccessMode),
|
Decimal(Box<Decimal>, AccessMode),
|
||||||
@ -682,16 +682,22 @@ impl Dynamic {
|
|||||||
pub const NEGATIVE_ONE: Dynamic = Self(Union::Int(-1, AccessMode::ReadWrite));
|
pub const NEGATIVE_ONE: Dynamic = Self(Union::Int(-1, AccessMode::ReadWrite));
|
||||||
/// A [`Dynamic`] containing the floating-point zero.
|
/// A [`Dynamic`] containing the floating-point zero.
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
pub const FLOAT_ZERO: Dynamic =
|
pub const FLOAT_ZERO: Dynamic = Self(Union::Float(
|
||||||
Self(Union::Float(FloatWrapper::new(0.0), AccessMode::ReadWrite));
|
FloatWrapper::const_new(0.0),
|
||||||
|
AccessMode::ReadWrite,
|
||||||
|
));
|
||||||
/// A [`Dynamic`] containing the floating-point one.
|
/// A [`Dynamic`] containing the floating-point one.
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
pub const FLOAT_ONE: Dynamic =
|
pub const FLOAT_ONE: Dynamic = Self(Union::Float(
|
||||||
Self(Union::Float(FloatWrapper::new(1.0), AccessMode::ReadWrite));
|
FloatWrapper::const_new(1.0),
|
||||||
|
AccessMode::ReadWrite,
|
||||||
|
));
|
||||||
/// A [`Dynamic`] containing the floating-point negative one.
|
/// A [`Dynamic`] containing the floating-point negative one.
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
pub const FLOAT_NEGATIVE_ONE: Dynamic =
|
pub const FLOAT_NEGATIVE_ONE: Dynamic = Self(Union::Float(
|
||||||
Self(Union::Float(FloatWrapper::new(-1.0), AccessMode::ReadWrite));
|
FloatWrapper::const_new(-1.0),
|
||||||
|
AccessMode::ReadWrite,
|
||||||
|
));
|
||||||
|
|
||||||
/// Get the [`AccessMode`] for this [`Dynamic`].
|
/// Get the [`AccessMode`] for this [`Dynamic`].
|
||||||
pub(crate) fn access_mode(&self) -> AccessMode {
|
pub(crate) fn access_mode(&self) -> AccessMode {
|
||||||
@ -1670,9 +1676,9 @@ impl From<FLOAT> for Dynamic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
impl From<FloatWrapper> for Dynamic {
|
impl From<FloatWrapper<FLOAT>> for Dynamic {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(value: FloatWrapper) -> Self {
|
fn from(value: FloatWrapper<FLOAT>) -> Self {
|
||||||
Self(Union::Float(value, AccessMode::ReadWrite))
|
Self(Union::Float(value, AccessMode::ReadWrite))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ pub type Precedence = NonZeroU8;
|
|||||||
// We cannot use Cow<str> here because `eval` may load a [module][Module] and
|
// We cannot use Cow<str> here because `eval` may load a [module][Module] and
|
||||||
// the module name will live beyond the AST of the eval script text.
|
// the module name will live beyond the AST of the eval script text.
|
||||||
// The best we can do is a shared reference.
|
// The best we can do is a shared reference.
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct Imports(StaticVec<Identifier>, StaticVec<Shared<Module>>);
|
pub struct Imports(StaticVec<Identifier>, StaticVec<Shared<Module>>);
|
||||||
|
|
||||||
impl Imports {
|
impl Imports {
|
||||||
@ -147,6 +147,20 @@ impl Imports {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Imports {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.write_str("Imports")?;
|
||||||
|
|
||||||
|
if self.is_empty() {
|
||||||
|
f.debug_map().finish()
|
||||||
|
} else {
|
||||||
|
f.debug_map()
|
||||||
|
.entries(self.0.iter().zip(self.1.iter()))
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
|
@ -7,8 +7,8 @@ use crate::fn_register::RegisterNativeFunction;
|
|||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
any::TypeId,
|
any::TypeId,
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
collections::BTreeMap,
|
collections::{BTreeMap, BTreeSet},
|
||||||
fmt, format,
|
fmt,
|
||||||
iter::empty,
|
iter::empty,
|
||||||
num::NonZeroUsize,
|
num::NonZeroUsize,
|
||||||
ops::{Add, AddAssign, Deref, DerefMut},
|
ops::{Add, AddAssign, Deref, DerefMut},
|
||||||
@ -173,50 +173,36 @@ impl Default for Module {
|
|||||||
|
|
||||||
impl fmt::Debug for Module {
|
impl fmt::Debug for Module {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(
|
let mut d = f.debug_struct("Module");
|
||||||
f,
|
|
||||||
"Module({}\n{}{}{})",
|
if let Some(ref id) = self.id {
|
||||||
self.id
|
d.field("id", id);
|
||||||
.as_ref()
|
}
|
||||||
.map(|id| format!("id: {:?},", id))
|
|
||||||
.unwrap_or_default(),
|
if !self.modules.is_empty() {
|
||||||
if !self.modules.is_empty() {
|
d.field(
|
||||||
format!(
|
"modules",
|
||||||
" modules: {}\n",
|
&self
|
||||||
self.modules
|
.modules
|
||||||
.keys()
|
.keys()
|
||||||
.map(|m| m.as_str())
|
.map(|m| m.as_str())
|
||||||
.collect::<Vec<_>>()
|
.collect::<BTreeSet<_>>(),
|
||||||
.join(", ")
|
);
|
||||||
)
|
}
|
||||||
} else {
|
if !self.variables.is_empty() {
|
||||||
Default::default()
|
d.field("vars", &self.variables);
|
||||||
},
|
}
|
||||||
if !self.variables.is_empty() {
|
if !self.functions.is_empty() {
|
||||||
format!(
|
d.field(
|
||||||
" vars: {}\n",
|
"functions",
|
||||||
self.variables
|
&self
|
||||||
.iter()
|
.functions
|
||||||
.map(|(k, v)| format!("{}={:?}", k, v))
|
.values()
|
||||||
.collect::<Vec<_>>()
|
.map(|f| crate::stdlib::string::ToString::to_string(&f.func))
|
||||||
.join(", ")
|
.collect::<BTreeSet<_>>(),
|
||||||
)
|
);
|
||||||
} else {
|
}
|
||||||
Default::default()
|
d.finish()
|
||||||
},
|
|
||||||
if !self.functions.is_empty() {
|
|
||||||
format!(
|
|
||||||
" functions: {}\n",
|
|
||||||
self.functions
|
|
||||||
.values()
|
|
||||||
.map(|f| crate::stdlib::string::ToString::to_string(&f.func))
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(", ")
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Default::default()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,8 +17,8 @@ use crate::stdlib::{
|
|||||||
};
|
};
|
||||||
use crate::utils::get_hasher;
|
use crate::utils::get_hasher;
|
||||||
use crate::{
|
use crate::{
|
||||||
calc_fn_hash, calc_fn_params_hash, combine_hashes, Dynamic, Engine, Module, Position, Scope,
|
calc_fn_hash, calc_fn_params_hash, combine_hashes, Dynamic, Engine, ImmutableString, Module,
|
||||||
StaticVec, AST,
|
Position, Scope, StaticVec, AST,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Level of optimization performed.
|
/// Level of optimization performed.
|
||||||
@ -799,15 +799,12 @@ fn optimize_expr(expr: &mut Expr, state: &mut State) {
|
|||||||
if x.namespace.is_none() // Non-qualified
|
if x.namespace.is_none() // Non-qualified
|
||||||
&& state.optimization_level == OptimizationLevel::Simple // simple optimizations
|
&& state.optimization_level == OptimizationLevel::Simple // simple optimizations
|
||||||
&& x.num_args() == 1
|
&& x.num_args() == 1
|
||||||
&& matches!(x.args[0], Expr::StringConstant(_, _))
|
&& x.constant_args.len() == 1
|
||||||
|
&& x.constant_args[0].0.is::<ImmutableString>()
|
||||||
&& x.name == KEYWORD_FN_PTR
|
&& x.name == KEYWORD_FN_PTR
|
||||||
=> {
|
=> {
|
||||||
if let Expr::StringConstant(s, _) = mem::take(&mut x.args[0]) {
|
state.set_dirty();
|
||||||
state.set_dirty();
|
*expr = Expr::FnPointer(mem::take(&mut x.constant_args[0].0).take_immutable_string().unwrap(), *pos);
|
||||||
*expr = Expr::FnPointer(s, *pos);
|
|
||||||
} else {
|
|
||||||
unreachable!();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not call some special keywords
|
// Do not call some special keywords
|
||||||
|
@ -9,7 +9,7 @@ def_package!(crate:BasicFnPackage:"Basic Fn functions.", lib, {
|
|||||||
mod fn_ptr_functions {
|
mod fn_ptr_functions {
|
||||||
#[rhai_fn(name = "name", get = "name", pure)]
|
#[rhai_fn(name = "name", get = "name", pure)]
|
||||||
pub fn name(f: &mut FnPtr) -> ImmutableString {
|
pub fn name(f: &mut FnPtr) -> ImmutableString {
|
||||||
f.get_fn_name().clone()
|
f.get_fn_name().as_str().into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
|
@ -73,31 +73,23 @@ mod print_debug_functions {
|
|||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
use num_traits::Float;
|
use num_traits::Float;
|
||||||
|
|
||||||
|
use crate::ast::FloatWrapper;
|
||||||
|
|
||||||
#[rhai_fn(name = "print", name = "to_string")]
|
#[rhai_fn(name = "print", name = "to_string")]
|
||||||
pub fn print_f64(number: f64) -> ImmutableString {
|
pub fn print_f64(number: f64) -> ImmutableString {
|
||||||
let abs = number.abs();
|
FloatWrapper::new(number).to_string().into()
|
||||||
if abs > 10000000000000.0 || abs < 0.0000000000001 {
|
|
||||||
format!("{:e}", number).into()
|
|
||||||
} else {
|
|
||||||
number.to_string().into()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "print", name = "to_string")]
|
#[rhai_fn(name = "print", name = "to_string")]
|
||||||
pub fn print_f32(number: f32) -> ImmutableString {
|
pub fn print_f32(number: f32) -> ImmutableString {
|
||||||
let abs = number.abs();
|
FloatWrapper::new(number).to_string().into()
|
||||||
if abs > 10000000000000.0 || abs < 0.0000000000001 {
|
|
||||||
format!("{:e}", number).into()
|
|
||||||
} else {
|
|
||||||
number.to_string().into()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "debug", name = "to_debug")]
|
#[rhai_fn(name = "debug", name = "to_debug")]
|
||||||
pub fn debug_f64(number: f64) -> ImmutableString {
|
pub fn debug_f64(number: f64) -> ImmutableString {
|
||||||
number.to_string().into()
|
format!("{:?}", FloatWrapper::new(number)).into()
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "debug", name = "to_debug")]
|
#[rhai_fn(name = "debug", name = "to_debug")]
|
||||||
pub fn debug_f32(number: f32) -> ImmutableString {
|
pub fn debug_f32(number: f32) -> ImmutableString {
|
||||||
number.to_string().into()
|
format!("{:?}", FloatWrapper::new(number)).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1271,16 +1271,16 @@ fn parse_primary(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cache the hash key for namespace-qualified variables
|
// Cache the hash key for namespace-qualified variables
|
||||||
match &mut root_expr {
|
match root_expr {
|
||||||
Expr::Variable(_, _, x) if x.1.is_some() => Some(x),
|
Expr::Variable(_, _, ref mut x) if x.1.is_some() => Some(x),
|
||||||
Expr::Index(x, _) | Expr::Dot(x, _) => match &mut x.lhs {
|
Expr::Index(ref mut x, _) | Expr::Dot(ref mut x, _) => match &mut x.lhs {
|
||||||
Expr::Variable(_, _, x) if x.1.is_some() => Some(x),
|
Expr::Variable(_, _, x) if x.1.is_some() => Some(x),
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
.map(|x| match x.as_mut() {
|
.map(|x| match x.as_mut() {
|
||||||
(_, Some((ref mut hash, ref mut namespace)), name) => {
|
(_, Some((hash, namespace)), name) => {
|
||||||
*hash = calc_fn_hash(namespace.iter().map(|v| v.name.as_str()), name, 0);
|
*hash = calc_fn_hash(namespace.iter().map(|v| v.name.as_str()), name, 0);
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
|
@ -18,7 +18,7 @@ use crate::stdlib::{
|
|||||||
use crate::{Engine, LexError, StaticVec, INT};
|
use crate::{Engine, LexError, StaticVec, INT};
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
use crate::ast::FloatWrapper;
|
use crate::{ast::FloatWrapper, FLOAT};
|
||||||
|
|
||||||
#[cfg(feature = "decimal")]
|
#[cfg(feature = "decimal")]
|
||||||
use rust_decimal::Decimal;
|
use rust_decimal::Decimal;
|
||||||
@ -210,7 +210,7 @@ pub enum Token {
|
|||||||
///
|
///
|
||||||
/// Reserved under the `no_float` feature.
|
/// Reserved under the `no_float` feature.
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
FloatConstant(FloatWrapper),
|
FloatConstant(FloatWrapper<FLOAT>),
|
||||||
/// A [`Decimal`] constant.
|
/// A [`Decimal`] constant.
|
||||||
///
|
///
|
||||||
/// Requires the `decimal` feature.
|
/// Requires the `decimal` feature.
|
||||||
|
@ -55,24 +55,33 @@ fn test_optimizer_parse() -> Result<(), Box<EvalAltResult>> {
|
|||||||
|
|
||||||
let ast = engine.compile("{ const DECISION = false; if DECISION { 42 } else { 123 } }")?;
|
let ast = engine.compile("{ const DECISION = false; if DECISION { 42 } else { 123 } }")?;
|
||||||
|
|
||||||
assert!(format!("{:?}", ast).starts_with(
|
assert_eq!(
|
||||||
r#"AST { source: None, body: [Expr(IntegerConstant(123, 1:53))], functions: Module("#
|
format!("{:?}", ast),
|
||||||
));
|
"AST { source: None, body: [Expr(123 @ 1:53)], functions: Module, resolver: None }"
|
||||||
|
);
|
||||||
|
|
||||||
let ast = engine.compile("const DECISION = false; if DECISION { 42 } else { 123 }")?;
|
let ast = engine.compile("const DECISION = false; if DECISION { 42 } else { 123 }")?;
|
||||||
|
|
||||||
assert!(format!("{:?}", ast).starts_with(r#"AST { source: None, body: [Const(BoolConstant(false, 1:18), Ident("DECISION" @ 1:7), false, 1:1), Expr(IntegerConstant(123, 1:51))], functions: Module("#));
|
assert_eq!(
|
||||||
|
format!("{:?}", ast),
|
||||||
|
r#"AST { source: None, body: [Const(false @ 1:18, "DECISION" @ 1:7, false, 1:1), Expr(123 @ 1:51)], functions: Module, resolver: None }"#
|
||||||
|
);
|
||||||
|
|
||||||
let ast = engine.compile("if 1 == 2 { 42 }")?;
|
let ast = engine.compile("if 1 == 2 { 42 }")?;
|
||||||
|
|
||||||
assert!(format!("{:?}", ast).starts_with("AST { source: None, body: [], functions: Module("));
|
assert_eq!(
|
||||||
|
format!("{:?}", ast),
|
||||||
|
"AST { source: None, body: [], functions: Module, resolver: None }"
|
||||||
|
);
|
||||||
|
|
||||||
engine.set_optimization_level(OptimizationLevel::Full);
|
engine.set_optimization_level(OptimizationLevel::Full);
|
||||||
|
|
||||||
let ast = engine.compile("abs(-42)")?;
|
let ast = engine.compile("abs(-42)")?;
|
||||||
|
|
||||||
assert!(format!("{:?}", ast)
|
assert_eq!(
|
||||||
.starts_with(r"AST { source: None, body: [Expr(IntegerConstant(42, 1:1))]"));
|
format!("{:?}", ast),
|
||||||
|
"AST { source: None, body: [Expr(42 @ 1:1)], functions: Module, resolver: None }"
|
||||||
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user