コード例 #1
0
ファイル: ModuleWeaver.cs プロジェクト: songhejia/NameOf
        private static void ProcessNameOfCallInstruction(Instruction instruction, ILProcessor ilProcessor)
        {
            var     instructions  = instruction.AsReverseEnumerable().Take(patterns.Value.First().Length).ToArray();        // Take an instruction set with a maximum size of the longest pattern.
            Boolean possibleMatch = false;

            PatternInstruction[] patternMatched = null;
            Func <String>        terminal       = null;

            foreach (var pattern in patterns.Value)
            {
                possibleMatch = true;
                terminal      = null;
                for (Int32 i = 0, j = 0; i < pattern.Length && j < instructions.Length; ++i, ++j)
                {
                    while (pattern[i] is OptionalPatternInstruction && !pattern[i].EligibleOpCodes.Contains(instructions[j].OpCode))
                    {
                        ++i;
                    }
                    var patternInstruction = pattern[i];
                    var currentInstruction = instructions[j];
                    if (patternInstruction.EligibleOpCodes.Contains(currentInstruction.OpCode) && patternInstruction.IsPredicated(currentInstruction, ilProcessor))
                    {
                        if (patternInstruction.Terminal != null && terminal == null)
                        {
                            terminal = () => patternInstruction.Terminal(currentInstruction, ilProcessor);
                        }
                        if (patternInstruction.Action != null)
                        {
                            patternInstruction.Action(currentInstruction);
                        }
                    }
                    else
                    {
                        possibleMatch = false;
                        break;
                    }
                }
                if (possibleMatch && pattern.Count(x => !(x is OptionalPatternInstruction)) <= instructions.Length)
                {
                    patternMatched = pattern;
                    break;
                }
            }
            if (!possibleMatch)
            {
                throw GetNotSupportedException(instruction);                 // The usage of Name.Of is not supported
            }
            if (terminal == null)
            {
                throw new NotImplementedException("There is no terminal expression implemented for the matched pattern.");
            }
            String name;

            try {
                name = terminal();
                if (IsNullOrWhiteSpace(name))
                {
                    throw new Exception("Name not found.");
                }
            }
            catch {
                throw GetNotSupportedException(instruction);
            }
            // TODO: Remove the anonymous methods generated by lamdba expressions in some uses of Name.Of...
            ilProcessor.InsertAfter(instruction, Instruction.Create(OpCodes.Ldstr, name));
            for (Int32 i = 0, j = 0; i < patternMatched.Length && j < instructions.Length; ++i, ++j)
            {
                while (patternMatched[i] is OptionalPatternInstruction && !patternMatched[i].EligibleOpCodes.Contains(instructions[j].OpCode))
                {
                    ++i;
                }
                ilProcessor.Remove(instructions[j]);
            }
        }