Ejemplo n.º 1
0
            public override ControlFlowNode VisitSwitchStatement(SwitchStatement switchStatement, ControlFlowNode data)
            {
                // First, figure out which switch section will get called (if the expression is constant):
                ResolveResult constant                 = builder.EvaluateConstant(switchStatement.Expression);
                SwitchSection defaultSection           = null;
                SwitchSection sectionMatchedByConstant = null;

                foreach (SwitchSection section in switchStatement.SwitchSections)
                {
                    foreach (CaseLabel label in section.CaseLabels)
                    {
                        if (label.Expression.IsNull)
                        {
                            defaultSection = section;
                        }
                        else if (constant != null && constant.IsCompileTimeConstant)
                        {
                            ResolveResult labelConstant = builder.EvaluateConstant(label.Expression);
                            if (builder.AreEqualConstants(constant, labelConstant))
                            {
                                sectionMatchedByConstant = section;
                            }
                        }
                    }
                }
                if (constant != null && constant.IsCompileTimeConstant && sectionMatchedByConstant == null)
                {
                    sectionMatchedByConstant = defaultSection;
                }

                int gotoCaseOrDefaultInOuterScope        = gotoCaseOrDefault.Count;
                List <ControlFlowNode> sectionStartNodes = new List <ControlFlowNode>();

                ControlFlowNode end = builder.CreateEndNode(switchStatement, addToNodeList: false);

                breakTargets.Push(end);
                foreach (SwitchSection section in switchStatement.SwitchSections)
                {
                    int sectionStartNodeID = builder.nodes.Count;
                    if (constant == null || !constant.IsCompileTimeConstant || section == sectionMatchedByConstant)
                    {
                        HandleStatementList(section.Statements, data);
                    }
                    else
                    {
                        // This section is unreachable: pass null to HandleStatementList.
                        HandleStatementList(section.Statements, null);
                    }
                    // Don't bother connecting the ends of the sections: the 'break' statement takes care of that.

                    // Store the section start node for 'goto case' statements.
                    sectionStartNodes.Add(sectionStartNodeID < builder.nodes.Count ? builder.nodes[sectionStartNodeID] : null);
                }
                breakTargets.Pop();
                if (defaultSection == null && sectionMatchedByConstant == null)
                {
                    Connect(data, end);
                }

                if (gotoCaseOrDefault.Count > gotoCaseOrDefaultInOuterScope)
                {
                    // Resolve 'goto case' statements:
                    for (int i = gotoCaseOrDefaultInOuterScope; i < gotoCaseOrDefault.Count; i++)
                    {
                        ControlFlowNode   gotoCaseNode      = gotoCaseOrDefault[i];
                        GotoCaseStatement gotoCaseStatement = gotoCaseNode.NextStatement as GotoCaseStatement;
                        ResolveResult     gotoCaseConstant  = null;
                        if (gotoCaseStatement != null)
                        {
                            gotoCaseConstant = builder.EvaluateConstant(gotoCaseStatement.LabelExpression);
                        }
                        int targetSectionIndex  = -1;
                        int currentSectionIndex = 0;
                        foreach (SwitchSection section in switchStatement.SwitchSections)
                        {
                            foreach (CaseLabel label in section.CaseLabels)
                            {
                                if (gotoCaseStatement != null)
                                {
                                    // goto case
                                    if (!label.Expression.IsNull)
                                    {
                                        ResolveResult labelConstant = builder.EvaluateConstant(label.Expression);
                                        if (builder.AreEqualConstants(gotoCaseConstant, labelConstant))
                                        {
                                            targetSectionIndex = currentSectionIndex;
                                        }
                                    }
                                }
                                else
                                {
                                    // goto default
                                    if (label.Expression.IsNull)
                                    {
                                        targetSectionIndex = currentSectionIndex;
                                    }
                                }
                            }
                            currentSectionIndex++;
                        }
                        if (targetSectionIndex >= 0 && sectionStartNodes[targetSectionIndex] != null)
                        {
                            Connect(gotoCaseNode, sectionStartNodes[targetSectionIndex], ControlFlowEdgeType.Jump);
                        }
                        else
                        {
                            Connect(gotoCaseNode, end, ControlFlowEdgeType.Jump);
                        }
                    }
                    gotoCaseOrDefault.RemoveRange(gotoCaseOrDefaultInOuterScope, gotoCaseOrDefault.Count - gotoCaseOrDefaultInOuterScope);
                }

                builder.nodes.Add(end);
                return(end);
            }
Ejemplo n.º 2
0
            public override ControlFlowNode VisitSwitchStatement(SwitchStatement switchStatement, ControlFlowNode data)
            {
                // First, figure out which switch section will get called (if the expression is constant):
                ConstantResolveResult constant                 = builder.EvaluateConstant(switchStatement.Expression);
                SwitchSection         defaultSection           = null;
                SwitchSection         sectionMatchedByConstant = null;

                foreach (SwitchSection section in switchStatement.SwitchSections)
                {
                    foreach (CaseLabel label in section.CaseLabels)
                    {
                        if (label.Expression.IsNull)
                        {
                            defaultSection = section;
                        }
                        else if (constant != null)
                        {
                            ConstantResolveResult labelConstant = builder.EvaluateConstant(label.Expression);
                            if (builder.AreEqualConstants(constant, labelConstant))
                            {
                                sectionMatchedByConstant = section;
                            }
                        }
                    }
                }
                if (constant != null && sectionMatchedByConstant == null)
                {
                    sectionMatchedByConstant = defaultSection;
                }

                int gotoCaseOrDefaultInOuterScope = gotoCaseOrDefault.Count;

                ControlFlowNode end = builder.CreateEndNode(switchStatement, addToNodeList: false);

                breakTargets.Push(end);
                foreach (SwitchSection section in switchStatement.SwitchSections)
                {
                    if (constant == null || section == sectionMatchedByConstant)
                    {
                        HandleStatementList(section.Statements, data);
                    }
                    else
                    {
                        // This section is unreachable: pass null to HandleStatementList.
                        HandleStatementList(section.Statements, null);
                    }
                    // Don't bother connecting the ends of the sections: the 'break' statement takes care of that.
                }
                breakTargets.Pop();
                if (defaultSection == null && sectionMatchedByConstant == null)
                {
                    Connect(data, end);
                }

                if (gotoCaseOrDefault.Count > gotoCaseOrDefaultInOuterScope)
                {
                    // Resolve 'goto case' statements:
                    throw new NotImplementedException();
                }

                builder.nodes.Add(end);
                return(end);
            }