예제 #1
0
        /// <summary>
        /// http://www.ecma-international.org/ecma-262/5.1/#sec-12.11
        /// </summary>
        /// <param name="switchStatement"></param>
        /// <returns></returns>
        public void ExecuteSwitchStatement(RuntimeState state)
        {
            SwitchStatement switchStatement = (SwitchStatement)state.arg;

            if (state.stage == 0)
            {
                if (state.calleeReturned)
                {
                    state.calleeReturned = false;
                    state.stage          = 1;
                    var jsValue = _engine.GetValue(state.calleeReturnValue, true);
                    ExecuteSwitchBlockArgs args = new ExecuteSwitchBlockArgs();
                    args.switchBlock = switchStatement.Cases;
                    args.input       = jsValue;
                    Call(ExecuteSwitchBlock, args);
                    return;
                }
                else
                {
                    Call(_engine.EvaluateExpression, switchStatement.Discriminant);
                    return;
                }
            }

            // Stage 1

            if (state.calleeReturned)
            {
                Completion r = (Completion)state.calleeReturnValue;

                if (r.Type == CompletionType.Break && r.Identifier == switchStatement.LabelSet?.Name)
                {
                    Return(new Completion(CompletionType.Normal, r.Value, null));
                    return;
                }
                Return(r);
                return;
            }
        }
예제 #2
0
        public void ExecuteSwitchBlock(RuntimeState state)
        {
            ExecuteSwitchBlockArgs args        = (ExecuteSwitchBlockArgs)state.arg;
            List <SwitchCase>      switchBlock = args.switchBlock;
            JsValue input = args.input;

            ExecuteSwitchBlockLocal local;

            if (state.local == null)
            {
                state.local            = local = new ExecuteSwitchBlockLocal();
                local.v                = Undefined.Instance;
                local.defaultCase      = null;
                local.hit              = false;
                local.switchBlockCount = switchBlock.Count;
                local.i                = 0;
                local.stage            = 0;
            }
            else
            {
                local = (ExecuteSwitchBlockLocal)state.local;
            }


            if (local.stage == 0) // for loop
            {
                if (local.i < local.switchBlockCount)
                {
                    local.stage = 1;
                }
                else
                {
                    local.stage = 2;
                }
            }
            if (local.stage == 1) // inside for loop
            {
                if (state.calleeReturned && state.stage != 10)
                {
                    Completion r = (Completion)state.calleeReturnValue;
                    if (r.Type != CompletionType.Normal)
                    {
                        Return(r);
                        return;
                    }

                    local.v = r.Value ?? Undefined.Instance;
                }

                var clause = switchBlock[local.i];
                if (clause.Test == null)
                {
                    local.defaultCase = clause;
                }
                else
                {
                    if (state.calleeReturned)
                    {
                        state.calleeReturned = false;
                        state.stage          = 0;
                        var clauseSelector = _engine.GetValue(state.calleeReturnValue, true);
                        if (ExpressionInterpreter.StrictlyEqual(clauseSelector, input))
                        {
                            local.hit = true;
                        }
                    }
                    else
                    {
                        state.stage = 10;
                        Call(_engine.EvaluateExpression, clause.Test);
                        return;
                    }
                }

                if (local.hit && clause.Consequent != null)
                {
                    Call(ExecuteStatementList, clause.Consequent);
                    return;
                }

                local.i++;
                local.stage = 0;
                return;
            }

            if (local.stage == 2)
            {
                if (state.calleeReturned)
                {
                    Completion r = (Completion)state.calleeReturnValue;
                    if (r.Type != CompletionType.Normal)
                    {
                        Return(r);
                        return;
                    }

                    local.v = r.Value ?? Undefined.Instance;
                }

                // do we need to execute the default case ?
                if (local.hit == false && local.defaultCase != null)
                {
                    Call(ExecuteStatementList, local.defaultCase.Consequent);
                    return;
                }

                Return(new Completion(CompletionType.Normal, local.v, null));
                return;
            }
        }