/// <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); }
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(); } } }
public BaseGroup(IDifferenceComparer <T> comparer, int sortToken) { Comparer = comparer; SortToken = sortToken; }
public SingleGroup(CaseInfo <T> value, IDifferenceComparer <T> comparer) : base(comparer, 1) { Value = value; }