// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using Mono.Cecil; namespace ICSharpCode.Decompiler.ILAst { public static class PatternMatching { public static bool Match(this ILNode node, ILCode code) { ILExpression expr = node as ILExpression; return expr != null && expr.Prefixes == null && expr.Code == code; } public static bool Match(this ILNode node, ILCode code, out T operand) { ILExpression expr = node as ILExpression; if (expr != null && expr.Prefixes == null && expr.Code == code && expr.Arguments.Count == 0) { operand = (T)expr.Operand; return true; } operand = default(T); return false; } public static bool Match(this ILNode node, ILCode code, T operand) { ILExpression expr = node as ILExpression; if (expr != null && expr.Prefixes == null && expr.Code == code) { Debug.Assert(expr.Arguments.Count == 0); return operand.Equals(expr.Operand); } return false; } public static bool Match(this ILNode node, ILCode code, out List args) { ILExpression expr = node as ILExpression; if (expr != null && expr.Prefixes == null && expr.Code == code) { Debug.Assert(expr.Operand == null); args = expr.Arguments; return true; } args = null; return false; } public static bool Match(this ILNode node, ILCode code, out ILExpression arg) { List args; if (node.Match(code, out args) && args.Count == 1) { arg = args[0]; return true; } arg = null; return false; } public static bool Match(this ILNode node, ILCode code, out T operand, out List args) { ILExpression expr = node as ILExpression; if (expr != null && expr.Prefixes == null && expr.Code == code) { operand = (T)expr.Operand; args = expr.Arguments; return true; } operand = default(T); args = null; return false; } public static bool Match(this ILNode node, ILCode code, out T operand, out ILExpression arg) { List args; if (node.Match(code, out operand, out args) && args.Count == 1) { arg = args[0]; return true; } arg = null; return false; } public static bool Match(this ILNode node, ILCode code, out T operand, out ILExpression arg1, out ILExpression arg2) { List args; if (node.Match(code, out operand, out args) && args.Count == 2) { arg1 = args[0]; arg2 = args[1]; return true; } arg1 = null; arg2 = null; return false; } public static bool MatchSingle(this ILBasicBlock bb, ILCode code, out T operand, out ILExpression arg, out ILLabel fallLabel) { if (bb.Body.Count == 1) { if (bb.Body[0].Match(code, out operand, out arg)) { fallLabel = bb.FallthoughGoto != null ? (ILLabel)bb.FallthoughGoto.Operand : null; return true; } } operand = default(T); arg = null; fallLabel = null; return false; } public static bool MatchLast(this ILBasicBlock bb, ILCode code, out T operand, out ILExpression arg, out ILLabel fallLabel) { if (bb.Body.LastOrDefault().Match(code, out operand, out arg)) { fallLabel = bb.FallthoughGoto != null ? (ILLabel)bb.FallthoughGoto.Operand : null; return true; } operand = default(T); arg = null; fallLabel = null; return false; } public static bool MatchThis(this ILNode node) { ILVariable v; return node.Match(ILCode.Ldloc, out v) && v.IsParameter && v.OriginalParameter.Index == -1; } public static bool MatchLdloc(this ILNode node, ILVariable expectedVar) { ILVariable v; return node.Match(ILCode.Ldloc, out v) && v == expectedVar; } } }