Beispiel #1
0
        public void VisitNode(JSLabelGroupStatement lgs)
        {
            CheckForFallthrough(lgs);

            var data = new LabelGroupData();

            LabelGroupStack.Push(data);

            foreach (var key in lgs.Labels.Keys)
            {
                data.Add(key.Value, new LabelGroupLabelData());
            }

            VisitChildren(lgs);

            // Scan all the labels to determine their direct exit label, if any
            foreach (var kvp in data)
            {
                var targetLabels = kvp.Value.ExitTargetLabels.Distinct().ToArray();

                if (
                    (targetLabels.Length == 1) &&
                    (kvp.Value.UntargettedExitCount == 0)
                    )
                {
                    kvp.Value.DirectExitLabel = targetLabels[0];
                }
                else
                {
                    kvp.Value.DirectExitLabel = null;
                }
            }

            // Scan all the labels again to determine their recursive exit label
            foreach (var kvp in data)
            {
                var rel = kvp.Value.RecursiveExitLabel = ComputeRecursiveExitLabel(data, kvp.Key);

                if (rel != null)
                {
                    data[rel].TimesUsedAsRecursiveExitTarget += 1;
                }
            }

            // If we have one label that is the recursive exit target for all other labels, we can turn it into the exit label
            var recursiveExitTargets = data.Where(
                (kvp) => kvp.Value.TimesUsedAsRecursiveExitTarget > 0
                ).ToArray();

            if (recursiveExitTargets.Length == 1)
            {
                var onlyRecursiveExitTarget = recursiveExitTargets[0].Key;
                var exitLabel        = lgs.ExitLabel;
                var newExitLabel     = lgs.Labels[onlyRecursiveExitTarget];
                var newExitLabelData = data[newExitLabel.Label];

                if (
                    (newExitLabelData.ExitTargetLabels.Count == 0) &&
                    (newExitLabelData.UntargettedExitCount == 0) &&
                    (newExitLabel != lgs.Labels.LastOrDefault().Value)
                    )
                {
                    if (TraceLevel >= 1)
                    {
                        Console.WriteLine("// Cannot mark label '{0}' as exit label because it falls through and is not the last label", onlyRecursiveExitTarget);
                    }
                }
                else if (exitLabel != null)
                {
                    if (exitLabel != newExitLabel)
                    {
                        if (TraceLevel >= 1)
                        {
                            Console.WriteLine("// Cannot mark label '{0}' as exit label because this labelgroup already has one", onlyRecursiveExitTarget);
                        }
                    }
                }
                else
                {
                    if (TraceLevel >= 1)
                    {
                        Console.WriteLine("// Marking label '{0}' as exit label", onlyRecursiveExitTarget);
                    }

                    lgs.ExitLabel = newExitLabel;
                    MadeChanges   = true;
                }
            }

            if ((lgs.ExitLabel != null) && (lgs.Labels.Count > 1))
            {
                ExtractExitLabel(lgs);
            }

            LabelGroupStack.Pop();
        }