Add Expr::DynamicConstant.

This commit is contained in:
Stephen Chung 2020-11-14 19:04:49 +08:00
parent c104afbdce
commit 28de155f08
3 changed files with 33 additions and 2 deletions

View File

@ -860,6 +860,8 @@ pub struct FnCallExpr {
/// This type is volatile and may change.
#[derive(Debug, Clone)]
pub enum Expr {
/// Dynamic constant.
DynamicConstant(Box<Dynamic>, 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::<INT>(),
#[cfg(not(feature = "no_float"))]
Self::FloatConstant(_, _) => TypeId::of::<FLOAT>(),
@ -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(_, _)

View File

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

View File

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