示例#1
0
        /// <summary>
        /// 生成指定类型的 Switch 代码块,使用差异位匹配算法。
        /// </summary>
        /// <typeparam name="T">指定类型</typeparam>
        /// <param name="ilGen">ILGenerator IL 指令生成器</param>
        /// <param name="emitLoadValue">生成加载 Switch 参数的指令的委托</param>
        /// <param name="comparer">差异位比较器</param>
        /// <param name="cases">case 标签块集合</param>
        /// <param name="defaultLabel">默认标签块</param>
        /// <param name="emitLoadItem">生成加载指定 Case 块值的指定的委托</param>
        public static void DifferenceSwitch <T>(ILGenerator ilGen,
                                                Action <ILGenerator> emitLoadValue,
                                                Action <ILGenerator, T> emitLoadItem,
                                                IDifferenceComparer <T> comparer,
                                                CaseInfo <T>[] cases,
                                                Label defaultLabel)
        {
            var lengthGroup = new LengthGroup <T>(cases, comparer);

            if (lengthGroup.GetDepth() > DifferenceSwitchMaxDepth)
            {
                throw new ArgumentException("Groups too deep.");
            }

            var lengthCases = new CaseInfo <int> [lengthGroup.Groups.Count];

            for (int i = 0; i < lengthCases.Length; i++)
            {
                lengthCases[i] = new CaseInfo <int>(lengthGroup.Groups[i].length, ilGen.DefineLabel())
                {
                    Tag = lengthGroup.Groups[i].group
                };
            }

            Switch(ilGen, (ilGen2) =>
            {
                emitLoadValue(ilGen2);
                comparer.EmitGetLength(ilGen2);
            }, lengthCases, defaultLabel);

            DifferenceCasesProcess(ilGen, emitLoadValue, emitLoadItem, comparer, defaultLabel, lengthCases);
        }
示例#2
0
        private static void DifferenceCasesProcess <TString>(
            ILGenerator iLGen,
            Action <ILGenerator> emitLoadValue,
            Action <ILGenerator, TString> emitLoadItem,
            IDifferenceComparer <TString> comparer,
            Label defaultLabel,
            CaseInfo <int>[] differenceCases)
        {
            foreach (var item in differenceCases)
            {
                iLGen.MarkLabel(item.Label);

                if (item.Tag is SingleGroup <TString> singleGroup)
                {
                    if (SwitchDoNotVerify)
                    {
                        iLGen.Branch(singleGroup.Value.Label);
                    }
                    else
                    {
                        emitLoadValue(iLGen);
                        emitLoadItem(iLGen, singleGroup.Value.Value);
                        comparer.EmitEquals(iLGen);
                        iLGen.BranchTrue(singleGroup.Value.Label);

                        iLGen.Branch(defaultLabel);
                    }
                }
                else if (item.Tag is DifferenceGroup <TString> differenceGroup)
                {
                    var charCases = new CaseInfo <int> [differenceGroup.Groups.Count];

                    for (int i = 0; i < charCases.Length; i++)
                    {
                        charCases[i] = new CaseInfo <int>(differenceGroup.Groups[i].chr, iLGen.DefineLabel())
                        {
                            Tag = differenceGroup.Groups[i].group
                        };
                    }

                    Switch(iLGen, (ilGen2) =>
                    {
                        emitLoadValue(ilGen2);
                        ilGen2.LoadConstant(differenceGroup.Index);
                        comparer.EmitElementAt(iLGen);
                    }, charCases, defaultLabel);

                    DifferenceCasesProcess(iLGen, emitLoadValue, emitLoadItem, comparer, defaultLabel, charCases);
                }
                else
                {
                    throw new NotSupportedException();
                }
            }
        }
示例#3
0
 public BaseGroup(IDifferenceComparer <T> comparer, int sortToken)
 {
     Comparer  = comparer;
     SortToken = sortToken;
 }
示例#4
0
 public SingleGroup(CaseInfo <T> value, IDifferenceComparer <T> comparer) : base(comparer, 1)
 {
     Value = value;
 }