Add Expr::DynamicConstant.
This commit is contained in:
parent
c104afbdce
commit
28de155f08
12
src/ast.rs
12
src/ast.rs
@ -860,6 +860,8 @@ pub struct FnCallExpr {
|
|||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Expr {
|
pub enum Expr {
|
||||||
|
/// Dynamic constant.
|
||||||
|
DynamicConstant(Box<Dynamic>, Position),
|
||||||
/// Integer constant.
|
/// Integer constant.
|
||||||
IntegerConstant(INT, Position),
|
IntegerConstant(INT, Position),
|
||||||
/// Floating-point constant.
|
/// Floating-point constant.
|
||||||
@ -929,6 +931,7 @@ impl Expr {
|
|||||||
Some(match self {
|
Some(match self {
|
||||||
Self::Expr(x) => return x.get_type_id(),
|
Self::Expr(x) => return x.get_type_id(),
|
||||||
|
|
||||||
|
Self::DynamicConstant(x, _) => x.type_id(),
|
||||||
Self::IntegerConstant(_, _) => TypeId::of::<INT>(),
|
Self::IntegerConstant(_, _) => TypeId::of::<INT>(),
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
Self::FloatConstant(_, _) => TypeId::of::<FLOAT>(),
|
Self::FloatConstant(_, _) => TypeId::of::<FLOAT>(),
|
||||||
@ -957,6 +960,7 @@ impl Expr {
|
|||||||
Some(match self {
|
Some(match self {
|
||||||
Self::Expr(x) => return x.get_constant_value(),
|
Self::Expr(x) => return x.get_constant_value(),
|
||||||
|
|
||||||
|
Self::DynamicConstant(x, _) => x.as_ref().clone(),
|
||||||
Self::IntegerConstant(x, _) => (*x).into(),
|
Self::IntegerConstant(x, _) => (*x).into(),
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
Self::FloatConstant(x, _) => (*x).into(),
|
Self::FloatConstant(x, _) => (*x).into(),
|
||||||
@ -1004,6 +1008,7 @@ impl Expr {
|
|||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
Self::FloatConstant(_, pos) => *pos,
|
Self::FloatConstant(_, pos) => *pos,
|
||||||
|
|
||||||
|
Self::DynamicConstant(_, pos) => *pos,
|
||||||
Self::IntegerConstant(_, pos) => *pos,
|
Self::IntegerConstant(_, pos) => *pos,
|
||||||
Self::CharConstant(_, pos) => *pos,
|
Self::CharConstant(_, pos) => *pos,
|
||||||
Self::StringConstant(_, pos) => *pos,
|
Self::StringConstant(_, pos) => *pos,
|
||||||
@ -1036,6 +1041,7 @@ impl Expr {
|
|||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
Self::FloatConstant(_, pos) => *pos = new_pos,
|
Self::FloatConstant(_, pos) => *pos = new_pos,
|
||||||
|
|
||||||
|
Self::DynamicConstant(_, pos) => *pos = new_pos,
|
||||||
Self::IntegerConstant(_, pos) => *pos = new_pos,
|
Self::IntegerConstant(_, pos) => *pos = new_pos,
|
||||||
Self::CharConstant(_, pos) => *pos = new_pos,
|
Self::CharConstant(_, pos) => *pos = new_pos,
|
||||||
Self::StringConstant(_, pos) => *pos = new_pos,
|
Self::StringConstant(_, pos) => *pos = new_pos,
|
||||||
@ -1096,7 +1102,8 @@ impl Expr {
|
|||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
Self::FloatConstant(_, _) => true,
|
Self::FloatConstant(_, _) => true,
|
||||||
|
|
||||||
Self::IntegerConstant(_, _)
|
Self::DynamicConstant(_, _)
|
||||||
|
| Self::IntegerConstant(_, _)
|
||||||
| Self::CharConstant(_, _)
|
| Self::CharConstant(_, _)
|
||||||
| Self::StringConstant(_, _)
|
| Self::StringConstant(_, _)
|
||||||
| Self::FnPointer(_, _)
|
| Self::FnPointer(_, _)
|
||||||
@ -1129,7 +1136,8 @@ impl Expr {
|
|||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
Self::FloatConstant(_, _) => false,
|
Self::FloatConstant(_, _) => false,
|
||||||
|
|
||||||
Self::IntegerConstant(_, _)
|
Self::DynamicConstant(_, _)
|
||||||
|
| Self::IntegerConstant(_, _)
|
||||||
| Self::CharConstant(_, _)
|
| Self::CharConstant(_, _)
|
||||||
| Self::FnPointer(_, _)
|
| Self::FnPointer(_, _)
|
||||||
| Self::In(_, _)
|
| Self::In(_, _)
|
||||||
|
@ -1677,6 +1677,7 @@ impl Engine {
|
|||||||
let result = match expr {
|
let result = match expr {
|
||||||
Expr::Expr(x) => self.eval_expr(scope, mods, state, lib, this_ptr, x, level),
|
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()),
|
Expr::IntegerConstant(x, _) => Ok((*x).into()),
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
Expr::FloatConstant(x, _) => Ok((*x).into()),
|
Expr::FloatConstant(x, _) => Ok((*x).into()),
|
||||||
|
@ -17,6 +17,12 @@ use crate::{calc_native_fn_hash, StaticVec};
|
|||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
use crate::ast::ReturnType;
|
use crate::ast::ReturnType;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_index"))]
|
||||||
|
use crate::Array;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
use crate::Map;
|
||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
@ -523,9 +529,25 @@ fn optimize_expr(expr: &mut Expr, state: &mut State) {
|
|||||||
// lhs[rhs]
|
// lhs[rhs]
|
||||||
(lhs, rhs) => { optimize_expr(lhs, state); optimize_expr(rhs, state); }
|
(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 .. ]
|
// [ items .. ]
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Expr::Array(a, _) => a.iter_mut().for_each(|expr| optimize_expr(expr, state)),
|
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, .. }
|
// #{ key:value, .. }
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Expr::Map(m, _) => m.iter_mut().for_each(|(_, expr)| optimize_expr(expr, state)),
|
Expr::Map(m, _) => m.iter_mut().for_each(|(_, expr)| optimize_expr(expr, state)),
|
||||||
|
Loading…
Reference in New Issue
Block a user