コード例 #1
0
        public static IReadOnlyList <Int32> GrabLabels(SwitchStmt stmt)
        {
            CaseLabelsGrabber grabber = new CaseLabelsGrabber();

            stmt.Stmt.Accept(grabber);
            return(grabber.Labels);
        }
コード例 #2
0
        public override void CGenStmt(Env env, CGenState state)
        {
            // Inside a switch statement, the initializations are ignored,
            // but the stack size should be changed.
            List <Tuple <Env, Decln> > declns;
            List <Tuple <Env, Stmt> >  stmts;

            var compoundStmt = this.Stmt as CompoundStmt;

            if (compoundStmt == null)
            {
                throw new NotImplementedException();
            }

            declns = compoundStmt.Declns;
            stmts  = compoundStmt.Stmts;

            // Track all case values.
            IReadOnlyList <Int32> values = CaseLabelsGrabber.GrabLabels(this);

            // Make sure there are no duplicates.
            if (values.Distinct().Count() != values.Count)
            {
                throw new InvalidOperationException("case labels not unique.");
            }
            // Request labels for these values.
            Dictionary <Int32, Int32> value_to_label = values.ToDictionary(value => value, value => state.RequestLabel());

            Int32 label_finish = state.RequestLabel();

            Int32 num_default_stmts = stmts.Count(_ => _.Item2 is DefaultStmt);

            if (num_default_stmts > 1)
            {
                throw new InvalidOperationException("duplicate defaults.");
            }
            Int32 label_default =
                num_default_stmts == 1 ?
                state.RequestLabel() :
                label_finish;

            Int32 saved_stack_size = state.StackSize;
            Int32 stack_size       =
                declns.Any() ?
                declns.Last().Item1.StackSize :
                saved_stack_size;

            // 1. Evaluate Expr.
            CGenExprStmt(env, this.Expr, state);

            // 2. Expand stack.
            state.CGenForceStackSizeTo(stack_size);

            // 3. Make the Jump list.
            foreach (KeyValuePair <Int32, Int32> value_label_pair in value_to_label)
            {
                state.CMPL(value_label_pair.Key, Reg.EAX);
                state.JZ(value_label_pair.Value);
            }
            state.JMP(label_default);

            // 4. List all the statements.
            state.InSwitch(label_finish, label_default, value_to_label);
            foreach (Tuple <Env, Stmt> env_stmt_pair in stmts)
            {
                env_stmt_pair.Item2.CGenStmt(env_stmt_pair.Item1, state);
            }
            state.OutLabels();

            // 5. finish:
            state.CGenLabel(label_finish);

            // 6. Restore stack size.
            state.CGenForceStackSizeTo(saved_stack_size);
        }
コード例 #3
0
ファイル: StmtVisitor.cs プロジェクト: phisiart/C-Compiler
 public static IReadOnlyList<Int32> GrabLabels(SwitchStmt stmt) {
     CaseLabelsGrabber grabber = new CaseLabelsGrabber();
     stmt.Stmt.Accept(grabber);
     return grabber.Labels;
 }