From 28de155f086f037c988032aea7425e04bc2333ce Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sat, 14 Nov 2020 19:04:49 +0800 Subject: [PATCH] Add Expr::DynamicConstant. --- src/ast.rs | 12 ++++++++++-- src/engine.rs | 1 + src/optimize.rs | 22 ++++++++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/ast.rs b/src/ast.rs index b0a4ac00..44847ac7 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -860,6 +860,8 @@ pub struct FnCallExpr { /// This type is volatile and may change. #[derive(Debug, Clone)] pub enum Expr { + /// Dynamic constant. + DynamicConstant(Box, Position), /// Integer constant. IntegerConstant(INT, Position), /// Floating-point constant. @@ -929,6 +931,7 @@ impl Expr { Some(match self { Self::Expr(x) => return x.get_type_id(), + Self::DynamicConstant(x, _) => x.type_id(), Self::IntegerConstant(_, _) => TypeId::of::(), #[cfg(not(feature = "no_float"))] Self::FloatConstant(_, _) => TypeId::of::(), @@ -957,6 +960,7 @@ impl Expr { Some(match self { Self::Expr(x) => return x.get_constant_value(), + Self::DynamicConstant(x, _) => x.as_ref().clone(), Self::IntegerConstant(x, _) => (*x).into(), #[cfg(not(feature = "no_float"))] Self::FloatConstant(x, _) => (*x).into(), @@ -1004,6 +1008,7 @@ impl Expr { #[cfg(not(feature = "no_float"))] Self::FloatConstant(_, pos) => *pos, + Self::DynamicConstant(_, pos) => *pos, Self::IntegerConstant(_, pos) => *pos, Self::CharConstant(_, pos) => *pos, Self::StringConstant(_, pos) => *pos, @@ -1036,6 +1041,7 @@ impl Expr { #[cfg(not(feature = "no_float"))] Self::FloatConstant(_, pos) => *pos = new_pos, + Self::DynamicConstant(_, pos) => *pos = new_pos, Self::IntegerConstant(_, pos) => *pos = new_pos, Self::CharConstant(_, pos) => *pos = new_pos, Self::StringConstant(_, pos) => *pos = new_pos, @@ -1096,7 +1102,8 @@ impl Expr { #[cfg(not(feature = "no_float"))] Self::FloatConstant(_, _) => true, - Self::IntegerConstant(_, _) + Self::DynamicConstant(_, _) + | Self::IntegerConstant(_, _) | Self::CharConstant(_, _) | Self::StringConstant(_, _) | Self::FnPointer(_, _) @@ -1129,7 +1136,8 @@ impl Expr { #[cfg(not(feature = "no_float"))] Self::FloatConstant(_, _) => false, - Self::IntegerConstant(_, _) + Self::DynamicConstant(_, _) + | Self::IntegerConstant(_, _) | Self::CharConstant(_, _) | Self::FnPointer(_, _) | Self::In(_, _) diff --git a/src/engine.rs b/src/engine.rs index a401160e..d2a5d684 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -1677,6 +1677,7 @@ impl Engine { let result = match expr { Expr::Expr(x) => self.eval_expr(scope, mods, state, lib, this_ptr, x, level), + Expr::DynamicConstant(x, _) => Ok(x.as_ref().clone()), Expr::IntegerConstant(x, _) => Ok((*x).into()), #[cfg(not(feature = "no_float"))] Expr::FloatConstant(x, _) => Ok((*x).into()), diff --git a/src/optimize.rs b/src/optimize.rs index 11e4fae3..292d3fc1 100644 --- a/src/optimize.rs +++ b/src/optimize.rs @@ -17,6 +17,12 @@ use crate::{calc_native_fn_hash, StaticVec}; #[cfg(not(feature = "no_function"))] use crate::ast::ReturnType; +#[cfg(not(feature = "no_index"))] +use crate::Array; + +#[cfg(not(feature = "no_object"))] +use crate::Map; + use crate::stdlib::{ boxed::Box, hash::{Hash, Hasher}, @@ -523,9 +529,25 @@ fn optimize_expr(expr: &mut Expr, state: &mut State) { // lhs[rhs] (lhs, rhs) => { optimize_expr(lhs, state); optimize_expr(rhs, state); } }, + // [ constant .. ] + #[cfg(not(feature = "no_index"))] + Expr::Array(a, pos) if a.iter().all(Expr::is_constant) => { + state.set_dirty(); + let mut arr: Array = Default::default(); + arr.extend(mem::take(a).into_iter().map(|expr| expr.get_constant_value().unwrap())); + *expr = Expr::DynamicConstant(Box::new(arr.into()), *pos); + } // [ items .. ] #[cfg(not(feature = "no_index"))] Expr::Array(a, _) => a.iter_mut().for_each(|expr| optimize_expr(expr, state)), + // #{ key:constant, .. } + #[cfg(not(feature = "no_object"))] + Expr::Map(m, pos) if m.iter().all(|(_, expr)| expr.is_constant()) => { + state.set_dirty(); + let mut map: Map = Default::default(); + map.extend(mem::take(m).into_iter().map(|(key, expr)| (key.name, expr.get_constant_value().unwrap()))); + *expr = Expr::DynamicConstant(Box::new(map.into()), *pos); + } // #{ key:value, .. } #[cfg(not(feature = "no_object"))] Expr::Map(m, _) => m.iter_mut().for_each(|(_, expr)| optimize_expr(expr, state)),