public DekiScriptLiteral Visit(DekiScriptSequence expr, DekiScriptEnv env)
        {
            if (expr.Kind != DekiScriptSequence.ScopeKind.None)
            {
                env = env.NewLocalScope();
            }
            bool safe = env.IsSafeMode;
            DekiScriptEvaluationAccumulator accumulator = new DekiScriptEvaluationAccumulator();

            foreach (DekiScriptExpression expression in expr.List)
            {
                try {
                    accumulator.Add(expression.VisitWith(this, env), safe);
                } catch (DekiScriptAbort.Exception e) {
                    // flow control exception occurred (e.g. break/continue)
                    accumulator.Add(e.AccumulatedState, safe);
                    switch (expr.Kind)
                    {
                    case DekiScriptSequence.ScopeKind.ScopeCatchContinue:
                        if (e.FlowControl == DekiScriptAbort.Kind.Continue)
                        {
                            return(accumulator.Value);
                        }
                        break;

                    case DekiScriptSequence.ScopeKind.ScopeCatchBreakAndContinue:
                        return(accumulator.Value);
                    }
                    throw new DekiScriptAbort.Exception(e.FlowControl, accumulator.Value);
                }
            }
            return(accumulator.Value);
        }
        public DekiScriptOutputBuffer.Range Visit(DekiScriptSequence expr, DekiScriptExpressionEvaluationState state)
        {
            int marker = state.Buffer.Marker;

            foreach (DekiScriptExpression expression in expr.List)
            {
                expression.VisitWith(this, state);
            }
            return(state.Buffer.Since(marker));
        }
        public DekiScriptExpression Visit(DekiScriptSequence expr, DekiScriptExpressionEvaluationState state)
        {
            return(expr);

#if false
            var mode = state.Mode;
            var env  = state.Env;
            if (expr.Kind != DekiScriptSequence.ScopeKind.None)
            {
                env = env.NewLocalScope();
            }
            bool safe = env.IsSafeMode;

            // loop over all expressions and accumulate as many as possible
            var accumulator = new DekiScriptOutputBuffer();
            List <DekiScriptExpression> list = new List <DekiScriptExpression>(expr.List.Length);
            foreach (DekiScriptExpression expression in expr.List)
            {
                DekiScriptExpression value = expression.VisitWith(this, new DekiScriptExpressionEvaluationState(mode, env));

                // check if we can continue to accumulate the values
                if ((accumulator != null) && value is DekiScriptLiteral)
                {
                    accumulator.Append((DekiScriptLiteral)value);
                }
                else
                {
                    // check if the accumulator contains a value to add to the list
                    if (accumulator != null)
                    {
                        list.Add(accumulator.GetResult(safe));
                        accumulator = null;
                    }

                    // check if value is worthile keeping
                    if (!(value is DekiScriptNil))
                    {
                        list.Add(value);
                    }
                }
            }
            if (accumulator != null)
            {
                return(accumulator.GetResult(safe));
            }
            return(DekiScriptSequence.New(expr.Kind, list.ToArray()));
#endif
        }
        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));
        }