public override void CleanupNodes() { base.CleanupNodes(); if (Parser.Settings.EvalLiteralExpressions && Parser.Settings.IsModificationAllowed(TreeModifications.EvaluateNumericExpressions)) { // if the if-condition is a constant, we can eliminate one of the two branches ConstantWrapper constantCondition = Condition as ConstantWrapper; if (constantCondition != null) { // instead, replace the condition with a 1 if it's always true or a 0 if it's always false if (constantCondition.IsNotOneOrPositiveZero) { try { Condition = new ConstantWrapper(constantCondition.ToBoolean() ? 1 : 0, PrimitiveType.Number, null, Parser); } catch (InvalidCastException) { // ignore any invalid cast exceptions } } } } }
public override void CleanupNodes() { base.CleanupNodes(); if (Parser.Settings.EvalLiteralExpressions && Parser.Settings.IsModificationAllowed(TreeModifications.EvaluateNumericExpressions)) { ConstantWrapper constantCondition = Condition as ConstantWrapper; if (constantCondition != null) { try { // if condition is always false, change it to a zero (only one byte) // and if it is always true, remove it (default behavior) if (constantCondition.ToBoolean()) { // always true -- don't need a condition at all Condition = null; } else if (constantCondition.IsNotOneOrPositiveZero) { // always false and it's not already a zero. Make it so (only one byte) Condition = new ConstantWrapper(0, PrimitiveType.Number, null, Parser); } } catch (InvalidCastException) { // ignore any invalid cast exceptions } } } }
public override void CleanupNodes() { base.CleanupNodes(); if (Parser.Settings.EvalLiteralExpressions && Parser.Settings.IsModificationAllowed(TreeModifications.EvaluateNumericExpressions)) { // if the condition is a literal, evaluating the condition doesn't do anything, AND // we know now whether it's true or not. ConstantWrapper literalCondition = m_condition as ConstantWrapper; if (literalCondition != null) { try { // if the boolean represenation of the literal is true, we can replace the condition operator // with the true expression; otherwise we can replace it with the false expression Parent.ReplaceChild(this, literalCondition.ToBoolean() ? m_trueExpression : m_falseExpression); } catch (InvalidCastException) { // ignore any invalid cast errors } } } }
public override void Visit(ConstantWrapper node) { if (node != null) { // no children, so don't bother calling the base. if (node.PrimitiveType == PrimitiveType.Boolean && m_parser.Settings.IsModificationAllowed(TreeModifications.BooleanLiteralsToNotOperators)) { node.Parent.ReplaceChild(node, new NumericUnary( node.Context, m_parser, new ConstantWrapper(node.ToBoolean() ? 0 : 1, PrimitiveType.Number, node.Context, m_parser), JSToken.LogicalNot)); } } }
public override void CleanupNodes() { base.CleanupNodes(); if (Parser.Settings.EvalLiteralExpressions && Parser.Settings.IsModificationAllowed(TreeModifications.EvaluateNumericExpressions)) { // if the condition is a constant, we can simplify things ConstantWrapper constantCondition = Condition as ConstantWrapper; if (constantCondition != null && constantCondition.IsNotOneOrPositiveZero) { try { // the condition is a constant, so it is always either true or false // we can replace the condition with a one or a zero -- only one byte Condition = new ConstantWrapper(constantCondition.ToBoolean() ? 1 : 0, PrimitiveType.Number, null, Parser); } catch (InvalidCastException) { // ignore any invalid cast errors } } } }
public override void CleanupNodes() { base.CleanupNodes(); // see if the condition is a constant if (Parser.Settings.EvalLiteralExpressions && Parser.Settings.IsModificationAllowed(TreeModifications.EvaluateNumericExpressions)) { ConstantWrapper constantCondition = Condition as ConstantWrapper; if (constantCondition != null) { // TODO: we'd RATHER eliminate the statement altogether if the condition is always false, // but we'd need to make sure var'd variables and declared functions are properly handled. try { bool isTrue = constantCondition.ToBoolean(); if (isTrue) { // the condition is always true; we should change it to a for(;;) statement. // less bytes than while(1) // check to see if we want to combine a preceding var with a for-statement AstNode initializer = null; if (Parser.Settings.IsModificationAllowed(TreeModifications.MoveVarIntoFor)) { // if the previous statement is a var, we can move it to the initializer // and save even more bytes. The parent should always be a block. If not, // then assume there is no previous. Block parentBlock = Parent as Block; if (parentBlock != null) { int whileIndex = parentBlock.StatementIndex(this); if (whileIndex > 0) { Var previousVar = parentBlock[whileIndex - 1] as Var; if (previousVar != null) { initializer = previousVar; parentBlock.ReplaceChild(previousVar, null); } } } } // create the for using our body and replace ourselves with it ForNode forNode = new ForNode(Context, Parser, initializer, null, null, Body); Parent.ReplaceChild(this, forNode); } else if (constantCondition.IsNotOneOrPositiveZero) { // the condition is always false, so we can replace the condition // with a zero -- only one byte Condition = new ConstantWrapper(0, PrimitiveType.Number, null, Parser); } } catch (InvalidCastException) { // ignore any invalid cast exceptions } } } }
public override void CleanupNodes() { base.CleanupNodes(); if (Parser.Settings.EvalLiteralExpressions && Parser.Settings.IsModificationAllowed(TreeModifications.EvaluateNumericExpressions)) { // see if our operand is a ConstantWrapper ConstantWrapper literalOperand = Operand as ConstantWrapper; if (literalOperand != null) { // must be number, boolean, string, or null switch (OperatorToken) { case JSToken.Plus: try { // replace with a constant representing operand.ToNumber, Parent.ReplaceChild(this, new ConstantWrapper(literalOperand.ToNumber(), PrimitiveType.Number, Context, Parser)); } catch (InvalidCastException) { // some kind of casting in ToNumber caused a situation where we don't want // to perform the combination on these operands } break; case JSToken.Minus: try { // replace with a constant representing the negative of operand.ToNumber Parent.ReplaceChild(this, new ConstantWrapper(-literalOperand.ToNumber(), PrimitiveType.Number, Context, Parser)); } catch (InvalidCastException) { // some kind of casting in ToNumber caused a situation where we don't want // to perform the combination on these operands } break; case JSToken.BitwiseNot: try { // replace with a constant representing the bitwise-not of operant.ToInt32 Parent.ReplaceChild(this, new ConstantWrapper(Convert.ToDouble(~literalOperand.ToInt32()), PrimitiveType.Number, Context, Parser)); } catch (InvalidCastException) { // some kind of casting in ToNumber caused a situation where we don't want // to perform the combination on these operands } break; case JSToken.LogicalNot: // replace with a constant representing the opposite of operand.ToBoolean try { Parent.ReplaceChild(this, new ConstantWrapper(!literalOperand.ToBoolean(), PrimitiveType.Boolean, Context, Parser)); } catch (InvalidCastException) { // ignore any invalid cast exceptions } break; } } } }
private ConstantWrapper Equal(ConstantWrapper left, ConstantWrapper right) { ConstantWrapper newLiteral = null; if (m_parser.Settings.IsModificationAllowed(TreeModifications.EvaluateNumericExpressions)) { PrimitiveType leftType = left.PrimitiveType; if (leftType == right.PrimitiveType) { // the values are the same type switch (leftType) { case PrimitiveType.Null: // null == null is true newLiteral = new ConstantWrapper(true, PrimitiveType.Boolean, null, m_parser); break; case PrimitiveType.Boolean: // compare boolean values newLiteral = new ConstantWrapper(left.ToBoolean() == right.ToBoolean(), PrimitiveType.Boolean, null, m_parser); break; case PrimitiveType.String: // compare string ordinally newLiteral = new ConstantWrapper(string.CompareOrdinal(left.ToString(), right.ToString()) == 0, PrimitiveType.Boolean, null, m_parser); break; case PrimitiveType.Number: try { // compare the values // +0 and -0 are treated as "equal" in C#, so we don't need to test them separately. // and NaN is always unequal to everything else, including itself. if (left.IsOkayToCombine && right.IsOkayToCombine) { newLiteral = new ConstantWrapper(left.ToNumber() == right.ToNumber(), PrimitiveType.Boolean, null, m_parser); } } catch (InvalidCastException) { // some kind of casting in ToNumber caused a situation where we don't want // to perform the combination on these operands } break; } } else if (left.IsOkayToCombine && right.IsOkayToCombine) { try { // numeric comparison // +0 and -0 are treated as "equal" in C#, so we don't need to test them separately. // and NaN is always unequal to everything else, including itself. newLiteral = new ConstantWrapper(left.ToNumber() == right.ToNumber(), PrimitiveType.Boolean, null, m_parser); } catch (InvalidCastException) { // some kind of casting in ToNumber caused a situation where we don't want // to perform the combination on these operands } } } return newLiteral; }
private ConstantWrapper LogicalOr(ConstantWrapper left, ConstantWrapper right) { ConstantWrapper newLiteral = null; if (m_parser.Settings.IsModificationAllowed(TreeModifications.EvaluateNumericExpressions)) { try { // if the left-hand side evaluates to true, return the left-hand side. // if the left-hand side is false, return the right-hand side. newLiteral = left.ToBoolean() ? left : right; } catch (InvalidCastException) { // if we couldn't cast to bool, ignore } } return newLiteral; }
public override void Visit(ConstantWrapper node) { if (node != null) { // measure if (node.PrimitiveType == PrimitiveType.Boolean) { if (m_measure) { // if we are converting true/false literals to !0/!1, then // a logical-not doesn't add or subtract anything. But if we aren't, // we need to add/subtract the difference in the length between the // "true" and "false" strings if (!m_parser.Settings.MinifyCode || !m_parser.Settings.IsModificationAllowed(TreeModifications.BooleanLiteralsToNotOperators)) { // converting true to false adds a character, false to true subtracts m_delta += node.ToBoolean() ? 1 : -1; } } else { // convert - just flip the boolean value node.Value = !node.ToBoolean(); } } else { // just the same typical operation as most other nodes for other types TypicalHandler(node); } } }