Merge Expr::True/False into BoolConstant.

This commit is contained in:
Stephen Chung 2020-11-19 22:29:50 +08:00
parent b87fa87a75
commit 15afd83da5
4 changed files with 37 additions and 56 deletions

View File

@ -862,6 +862,8 @@ pub enum Expr {
/// Used to hold either an Array or Map literal for quick cloning. /// Used to hold either an Array or Map literal for quick cloning.
/// All other primitive data types should use the appropriate variants for better speed. /// All other primitive data types should use the appropriate variants for better speed.
DynamicConstant(Box<Dynamic>, Position), DynamicConstant(Box<Dynamic>, Position),
/// Boolean constant.
BoolConstant(bool, Position),
/// Integer constant. /// Integer constant.
IntegerConstant(INT, Position), IntegerConstant(INT, Position),
/// Floating-point constant. /// Floating-point constant.
@ -877,10 +879,6 @@ pub enum Expr {
Array(Box<StaticVec<Expr>>, Position), Array(Box<StaticVec<Expr>>, Position),
/// #{ name:expr, ... } /// #{ name:expr, ... }
Map(Box<StaticVec<(IdentX, Expr)>>, Position), Map(Box<StaticVec<(IdentX, Expr)>>, Position),
/// true
True(Position),
/// false
False(Position),
/// () /// ()
Unit(Position), Unit(Position),
/// Variable access - (optional index, optional modules, hash, variable name) /// Variable access - (optional index, optional modules, hash, variable name)
@ -932,8 +930,7 @@ impl Expr {
x.clone(), x.clone(),
Default::default(), Default::default(),
)))), )))),
Self::True(_) => true.into(), Self::BoolConstant(x, _) => (*x).into(),
Self::False(_) => false.into(),
Self::Unit(_) => ().into(), Self::Unit(_) => ().into(),
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
@ -978,6 +975,7 @@ impl Expr {
Self::FloatConstant(_, pos) => *pos, Self::FloatConstant(_, pos) => *pos,
Self::DynamicConstant(_, pos) => *pos, Self::DynamicConstant(_, pos) => *pos,
Self::BoolConstant(_, 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,
@ -991,7 +989,7 @@ impl Expr {
Self::And(x, _) | Self::Or(x, _) | Self::In(x, _) => x.lhs.position(), Self::And(x, _) | Self::Or(x, _) | Self::In(x, _) => x.lhs.position(),
Self::True(pos) | Self::False(pos) | Self::Unit(pos) => *pos, Self::Unit(pos) => *pos,
Self::Dot(x, _) | Self::Index(x, _) => x.lhs.position(), Self::Dot(x, _) | Self::Index(x, _) => x.lhs.position(),
@ -1009,6 +1007,7 @@ impl Expr {
Self::FloatConstant(_, pos) => *pos = new_pos, Self::FloatConstant(_, pos) => *pos = new_pos,
Self::DynamicConstant(_, pos) => *pos = new_pos, Self::DynamicConstant(_, pos) => *pos = new_pos,
Self::BoolConstant(_, 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,
@ -1020,7 +1019,7 @@ impl Expr {
Self::Stmt(_, pos) => *pos = new_pos, Self::Stmt(_, pos) => *pos = new_pos,
Self::FnCall(_, pos) => *pos = new_pos, Self::FnCall(_, pos) => *pos = new_pos,
Self::And(_, pos) | Self::Or(_, pos) | Self::In(_, pos) => *pos = new_pos, Self::And(_, pos) | Self::Or(_, pos) | Self::In(_, pos) => *pos = new_pos,
Self::True(pos) | Self::False(pos) | Self::Unit(pos) => *pos = new_pos, Self::Unit(pos) => *pos = new_pos,
Self::Dot(_, pos) | Self::Index(_, pos) => *pos = new_pos, Self::Dot(_, pos) | Self::Index(_, pos) => *pos = new_pos,
Self::Custom(_, pos) => *pos = new_pos, Self::Custom(_, pos) => *pos = new_pos,
} }
@ -1066,12 +1065,11 @@ impl Expr {
Self::FloatConstant(_, _) => true, Self::FloatConstant(_, _) => true,
Self::DynamicConstant(_, _) Self::DynamicConstant(_, _)
| Self::BoolConstant(_, _)
| Self::IntegerConstant(_, _) | Self::IntegerConstant(_, _)
| Self::CharConstant(_, _) | Self::CharConstant(_, _)
| Self::StringConstant(_, _) | Self::StringConstant(_, _)
| Self::FnPointer(_, _) | Self::FnPointer(_, _)
| Self::True(_)
| Self::False(_)
| Self::Unit(_) => true, | Self::Unit(_) => true,
// An array literal is constant if all items are constant // An array literal is constant if all items are constant
@ -1099,14 +1097,13 @@ impl Expr {
Self::FloatConstant(_, _) => false, Self::FloatConstant(_, _) => false,
Self::DynamicConstant(_, _) Self::DynamicConstant(_, _)
| Self::BoolConstant(_, _)
| Self::IntegerConstant(_, _) | Self::IntegerConstant(_, _)
| Self::CharConstant(_, _) | Self::CharConstant(_, _)
| Self::FnPointer(_, _) | Self::FnPointer(_, _)
| Self::In(_, _) | Self::In(_, _)
| Self::And(_, _) | Self::And(_, _)
| Self::Or(_, _) | Self::Or(_, _)
| Self::True(_)
| Self::False(_)
| Self::Unit(_) => false, | Self::Unit(_) => false,
Self::StringConstant(_, _) Self::StringConstant(_, _)

View File

@ -1815,8 +1815,7 @@ impl Engine {
.into()) .into())
} }
Expr::True(_) => Ok(true.into()), Expr::BoolConstant(x, _) => Ok((*x).into()),
Expr::False(_) => Ok(false.into()),
Expr::Unit(_) => Ok(Dynamic::UNIT), Expr::Unit(_) => Ok(Dynamic::UNIT),
Expr::Custom(custom, _) => { Expr::Custom(custom, _) => {

View File

@ -282,12 +282,12 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut State, preserve_result: bool) {
}, },
// if false { if_block } -> Noop // if false { if_block } -> Noop
Stmt::If(Expr::False(pos), x, _) if x.1.is_none() => { Stmt::If(Expr::BoolConstant(false, pos), x, _) if x.1.is_none() => {
state.set_dirty(); state.set_dirty();
*stmt = Stmt::Noop(*pos); *stmt = Stmt::Noop(*pos);
} }
// if true { if_block } -> if_block // if true { if_block } -> if_block
Stmt::If(Expr::True(_), x, _) if x.1.is_none() => { Stmt::If(Expr::BoolConstant(true, _), x, _) if x.1.is_none() => {
*stmt = mem::take(&mut x.0); *stmt = mem::take(&mut x.0);
optimize_stmt(stmt, state, true); optimize_stmt(stmt, state, true);
} }
@ -316,12 +316,12 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut State, preserve_result: bool) {
optimize_stmt(&mut x.0, state, true); optimize_stmt(&mut x.0, state, true);
} }
// if false { if_block } else { else_block } -> else_block // if false { if_block } else { else_block } -> else_block
Stmt::If(Expr::False(_), x, _) if x.1.is_some() => { Stmt::If(Expr::BoolConstant(false, _), x, _) if x.1.is_some() => {
*stmt = mem::take(x.1.as_mut().unwrap()); *stmt = mem::take(x.1.as_mut().unwrap());
optimize_stmt(stmt, state, true); optimize_stmt(stmt, state, true);
} }
// if true { if_block } else { else_block } -> if_block // if true { if_block } else { else_block } -> if_block
Stmt::If(Expr::True(_), x, _) => { Stmt::If(Expr::BoolConstant(true, _), x, _) => {
*stmt = mem::take(&mut x.0); *stmt = mem::take(&mut x.0);
optimize_stmt(stmt, state, true); optimize_stmt(stmt, state, true);
} }
@ -375,12 +375,12 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut State, preserve_result: bool) {
} }
// while false { block } -> Noop // while false { block } -> Noop
Stmt::While(Expr::False(pos), _, _) => { Stmt::While(Expr::BoolConstant(false, pos), _, _) => {
state.set_dirty(); state.set_dirty();
*stmt = Stmt::Noop(*pos) *stmt = Stmt::Noop(*pos)
} }
// while true { block } -> loop { block } // while true { block } -> loop { block }
Stmt::While(Expr::True(_), block, pos) => { Stmt::While(Expr::BoolConstant(true, _), block, pos) => {
optimize_stmt(block, state, false); optimize_stmt(block, state, false);
*stmt = Stmt::Loop(Box::new(mem::take(block)), *pos) *stmt = Stmt::Loop(Box::new(mem::take(block)), *pos)
} }
@ -576,32 +576,23 @@ fn optimize_expr(expr: &mut Expr, state: &mut State) {
// "xxx" in "xxxxx" // "xxx" in "xxxxx"
(Expr::StringConstant(a, pos), Expr::StringConstant(b, _)) => { (Expr::StringConstant(a, pos), Expr::StringConstant(b, _)) => {
state.set_dirty(); state.set_dirty();
*expr = if b.contains(a.as_str()) { Expr::True(*pos) } else { Expr::False(*pos) }; *expr = Expr::BoolConstant( b.contains(a.as_str()), *pos);
} }
// 'x' in "xxxxx" // 'x' in "xxxxx"
(Expr::CharConstant(a, pos), Expr::StringConstant(b, _)) => { (Expr::CharConstant(a, pos), Expr::StringConstant(b, _)) => {
state.set_dirty(); state.set_dirty();
*expr = if b.contains(*a) { Expr::True(*pos) } else { Expr::False(*pos) }; *expr = Expr::BoolConstant(b.contains(*a), *pos);
} }
// "xxx" in #{...} // "xxx" in #{...}
(Expr::StringConstant(a, pos), Expr::Map(b, _)) => { (Expr::StringConstant(a, pos), Expr::Map(b, _)) => {
state.set_dirty(); state.set_dirty();
*expr = if b.iter().find(|(x, _)| x.name == *a).is_some() { *expr = Expr::BoolConstant(b.iter().find(|(x, _)| x.name == *a).is_some(), *pos);
Expr::True(*pos)
} else {
Expr::False(*pos)
};
} }
// 'x' in #{...} // 'x' in #{...}
(Expr::CharConstant(a, pos), Expr::Map(b, _)) => { (Expr::CharConstant(a, pos), Expr::Map(b, _)) => {
state.set_dirty(); state.set_dirty();
let ch = a.to_string(); let ch = a.to_string();
*expr = Expr::BoolConstant(b.iter().find(|(x, _)| x.name == &ch).is_some(), *pos);
*expr = if b.iter().find(|(x, _)| x.name == &ch).is_some() {
Expr::True(*pos)
} else {
Expr::False(*pos)
};
} }
// lhs in rhs // lhs in rhs
(lhs, rhs) => { optimize_expr(lhs, state); optimize_expr(rhs, state); } (lhs, rhs) => { optimize_expr(lhs, state); optimize_expr(rhs, state); }
@ -609,18 +600,18 @@ fn optimize_expr(expr: &mut Expr, state: &mut State) {
// lhs && rhs // lhs && rhs
Expr::And(x, _) => match (&mut x.lhs, &mut x.rhs) { Expr::And(x, _) => match (&mut x.lhs, &mut x.rhs) {
// true && rhs -> rhs // true && rhs -> rhs
(Expr::True(_), rhs) => { (Expr::BoolConstant(true, _), rhs) => {
state.set_dirty(); state.set_dirty();
optimize_expr(rhs, state); optimize_expr(rhs, state);
*expr = mem::take(rhs); *expr = mem::take(rhs);
} }
// false && rhs -> false // false && rhs -> false
(Expr::False(pos), _) => { (Expr::BoolConstant(false, pos), _) => {
state.set_dirty(); state.set_dirty();
*expr = Expr::False(*pos); *expr = Expr::BoolConstant(false, *pos);
} }
// lhs && true -> lhs // lhs && true -> lhs
(lhs, Expr::True(_)) => { (lhs, Expr::BoolConstant(true, _)) => {
state.set_dirty(); state.set_dirty();
optimize_expr(lhs, state); optimize_expr(lhs, state);
*expr = mem::take(lhs); *expr = mem::take(lhs);
@ -631,18 +622,18 @@ fn optimize_expr(expr: &mut Expr, state: &mut State) {
// lhs || rhs // lhs || rhs
Expr::Or(ref mut x, _) => match (&mut x.lhs, &mut x.rhs) { Expr::Or(ref mut x, _) => match (&mut x.lhs, &mut x.rhs) {
// false || rhs -> rhs // false || rhs -> rhs
(Expr::False(_), rhs) => { (Expr::BoolConstant(false, _), rhs) => {
state.set_dirty(); state.set_dirty();
optimize_expr(rhs, state); optimize_expr(rhs, state);
*expr = mem::take(rhs); *expr = mem::take(rhs);
} }
// true || rhs -> true // true || rhs -> true
(Expr::True(pos), _) => { (Expr::BoolConstant(true, pos), _) => {
state.set_dirty(); state.set_dirty();
*expr = Expr::True(*pos); *expr = Expr::BoolConstant(true, *pos);
} }
// lhs || false // lhs || false
(lhs, Expr::False(_)) => { (lhs, Expr::BoolConstant(false, _)) => {
state.set_dirty(); state.set_dirty();
optimize_expr(lhs, state); optimize_expr(lhs, state);
*expr = mem::take(lhs); *expr = mem::take(lhs);

View File

@ -464,8 +464,7 @@ fn parse_index_chain(
| Expr::And(_, _) | Expr::And(_, _)
| Expr::Or(_, _) | Expr::Or(_, _)
| Expr::In(_, _) | Expr::In(_, _)
| Expr::True(_) | Expr::BoolConstant(_, _)
| Expr::False(_)
| Expr::Unit(_) => { | Expr::Unit(_) => {
return Err(PERR::MalformedIndexExpr( return Err(PERR::MalformedIndexExpr(
"Only arrays, object maps and strings can be indexed".into(), "Only arrays, object maps and strings can be indexed".into(),
@ -499,8 +498,7 @@ fn parse_index_chain(
| Expr::And(_, _) | Expr::And(_, _)
| Expr::Or(_, _) | Expr::Or(_, _)
| Expr::In(_, _) | Expr::In(_, _)
| Expr::True(_) | Expr::BoolConstant(_, _)
| Expr::False(_)
| Expr::Unit(_) => { | Expr::Unit(_) => {
return Err(PERR::MalformedIndexExpr( return Err(PERR::MalformedIndexExpr(
"Only arrays, object maps and strings can be indexed".into(), "Only arrays, object maps and strings can be indexed".into(),
@ -541,7 +539,7 @@ fn parse_index_chain(
.into_err(x.position())) .into_err(x.position()))
} }
// lhs[true], lhs[false] // lhs[true], lhs[false]
x @ Expr::True(_) | x @ Expr::False(_) => { x @ Expr::BoolConstant(_, _) => {
return Err(PERR::MalformedIndexExpr( return Err(PERR::MalformedIndexExpr(
"Array access expects integer index, not a boolean".into(), "Array access expects integer index, not a boolean".into(),
) )
@ -999,8 +997,8 @@ fn parse_primary(
Token::LeftBracket => parse_array_literal(input, state, lib, settings.level_up())?, Token::LeftBracket => parse_array_literal(input, state, lib, settings.level_up())?,
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
Token::MapStart => parse_map_literal(input, state, lib, settings.level_up())?, Token::MapStart => parse_map_literal(input, state, lib, settings.level_up())?,
Token::True => Expr::True(settings.pos), Token::True => Expr::BoolConstant(true, settings.pos),
Token::False => Expr::False(settings.pos), Token::False => Expr::BoolConstant(false, settings.pos),
Token::LexError(err) => return Err(err.into_err(settings.pos)), Token::LexError(err) => return Err(err.into_err(settings.pos)),
_ => { _ => {
@ -1451,8 +1449,7 @@ fn make_in_expr(lhs: Expr, rhs: Expr, op_pos: Position) -> Result<Expr, ParseErr
| (_, x @ Expr::And(_, _)) | (_, x @ Expr::And(_, _))
| (_, x @ Expr::Or(_, _)) | (_, x @ Expr::Or(_, _))
| (_, x @ Expr::In(_, _)) | (_, x @ Expr::In(_, _))
| (_, x @ Expr::True(_)) | (_, x @ Expr::BoolConstant(_, _))
| (_, x @ Expr::False(_))
| (_, x @ Expr::Unit(_)) => { | (_, x @ Expr::Unit(_)) => {
return Err(PERR::MalformedInExpr( return Err(PERR::MalformedInExpr(
"'in' expression expects a string, array or object map".into(), "'in' expression expects a string, array or object map".into(),
@ -1492,8 +1489,7 @@ fn make_in_expr(lhs: Expr, rhs: Expr, op_pos: Position) -> Result<Expr, ParseErr
(x @ Expr::And(_, _), Expr::StringConstant(_, _)) (x @ Expr::And(_, _), Expr::StringConstant(_, _))
| (x @ Expr::Or(_, _), Expr::StringConstant(_, _)) | (x @ Expr::Or(_, _), Expr::StringConstant(_, _))
| (x @ Expr::In(_, _), Expr::StringConstant(_, _)) | (x @ Expr::In(_, _), Expr::StringConstant(_, _))
| (x @ Expr::True(_), Expr::StringConstant(_, _)) | (x @ Expr::BoolConstant(_, _), Expr::StringConstant(_, _)) => {
| (x @ Expr::False(_), Expr::StringConstant(_, _)) => {
return Err(PERR::MalformedInExpr( return Err(PERR::MalformedInExpr(
"'in' expression for a string expects a string, not a boolean".into(), "'in' expression for a string expects a string, not a boolean".into(),
) )
@ -1545,8 +1541,7 @@ fn make_in_expr(lhs: Expr, rhs: Expr, op_pos: Position) -> Result<Expr, ParseErr
(x @ Expr::And(_, _), Expr::Map(_, _)) (x @ Expr::And(_, _), Expr::Map(_, _))
| (x @ Expr::Or(_, _), Expr::Map(_, _)) | (x @ Expr::Or(_, _), Expr::Map(_, _))
| (x @ Expr::In(_, _), Expr::Map(_, _)) | (x @ Expr::In(_, _), Expr::Map(_, _))
| (x @ Expr::True(_), Expr::Map(_, _)) | (x @ Expr::BoolConstant(_, _), Expr::Map(_, _)) => {
| (x @ Expr::False(_), Expr::Map(_, _)) => {
return Err(PERR::MalformedInExpr( return Err(PERR::MalformedInExpr(
"'in' expression for an object map expects a string, not a boolean".into(), "'in' expression for an object map expects a string, not a boolean".into(),
) )
@ -2961,8 +2956,7 @@ pub fn map_dynamic_to_expr(value: Dynamic, pos: Position) -> Option<Expr> {
Union::Int(value) => Some(Expr::IntegerConstant(value, pos)), Union::Int(value) => Some(Expr::IntegerConstant(value, pos)),
Union::Char(value) => Some(Expr::CharConstant(value, pos)), Union::Char(value) => Some(Expr::CharConstant(value, pos)),
Union::Str(value) => Some(Expr::StringConstant(value, pos)), Union::Str(value) => Some(Expr::StringConstant(value, pos)),
Union::Bool(true) => Some(Expr::True(pos)), Union::Bool(value) => Some(Expr::BoolConstant(value, pos)),
Union::Bool(false) => Some(Expr::False(pos)),
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
Union::Array(array) => { Union::Array(array) => {
let items: Vec<_> = array let items: Vec<_> = array