public DekiScriptExpression Visit(DekiScriptBinary expr, DekiScriptOptimizerState state)
        {
            DekiScriptExpression left   = expr.Left.VisitWith(this, state);
            DekiScriptExpression right  = expr.Right.VisitWith(this, state);
            DekiScriptExpression result = new DekiScriptBinary(expr.Line, expr.Column, expr.OpCode, left, right);

            if ((left is DekiScriptLiteral) && (right is DekiScriptLiteral))
            {
                result = result.Evaluate(state.Env);
            }
            return(result);
        }
        private object Optimize(DekiScriptCaseBlock expr, DekiScriptExpression value, DekiScriptEvalMode mode, DekiScriptEnv env, out bool isDefaultCase)
        {
            List <DekiScriptExpression> conditions = new List <DekiScriptExpression>();

            isDefaultCase = false;
            for (int i = 0; i < expr.Conditions.Length; i++)
            {
                if (expr.Conditions[i] != null)
                {
                    DekiScriptExpression condition = expr.Conditions[i].VisitWith(this, new DekiScriptOptimizerState(mode, env));

                    // check if condition always succeeds or always fails
                    if ((value is DekiScriptLiteral) && (condition is DekiScriptLiteral))
                    {
                        DekiScriptBinary test = new DekiScriptBinary(0, 0, DekiScriptBinary.Op.Equal, value, condition);
                        if (!test.Evaluate(env).IsNilFalseZero)
                        {
                            // NOTE (steveb): we wrap the outcome into a sequence to ensure proper handling of break/continue statements

                            // condition succeeded, return it
                            return(DekiScriptSequence.New(DekiScriptSequence.ScopeKind.ScopeCatchBreakAndContinue, expr.Body.VisitWith(this, new DekiScriptOptimizerState(mode, env))));
                        }
                    }
                    else
                    {
                        conditions.Add(condition);
                    }
                }
                else
                {
                    isDefaultCase = true;
                    conditions.Add(null);
                }
            }

            // check if any conditions were true or unknown
            if (conditions.Count == 0)
            {
                return(null);
            }
            DekiScriptExpression body = expr.Body.VisitWith(this, new DekiScriptOptimizerState(mode, env));

            return(new DekiScriptCaseBlock(conditions.ToArray(), body, expr.IsBlock));
        }