Browse Source

Add some improvements to pattern matching.

pull/37/head
Daniel Grunwald 15 years ago
parent
commit
8dadc50191
  1. 2
      ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
  2. 2
      ICSharpCode.Decompiler/Ast/Transforms/PushNegation.cs
  3. 38
      ICSharpCode.Decompiler/Ast/Transforms/UsingStatementTransform.cs
  4. 2
      NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Backreference.cs
  5. 18
      NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Choice.cs
  6. 28
      NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Match.cs
  7. 5
      NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Pattern.cs
  8. 52
      NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Placeholder.cs

2
ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -278,7 +278,7 @@ namespace Decompiler @@ -278,7 +278,7 @@ namespace Decompiler
}
}
string FormatByteCodeOperand(object operand)
static string FormatByteCodeOperand(object operand)
{
if (operand == null) {
return string.Empty;

2
ICSharpCode.Decompiler/Ast/Transforms/PushNegation.cs

@ -114,7 +114,7 @@ namespace Decompiler.Transforms @@ -114,7 +114,7 @@ namespace Decompiler.Transforms
negate = true;
}
if (m != null) {
Expression expr = ((Expression)m["expr"].Single()).Detach().IsType((AstType)m["type"].Single().Detach());
Expression expr = m.Get<Expression>("expr").Single().Detach().IsType(m.Get<AstType>("type").Single().Detach());
if (negate)
expr = new UnaryOperatorExpression(UnaryOperatorType.Not, expr);
binaryOperatorExpression.ReplaceWith(expr);

38
ICSharpCode.Decompiler/Ast/Transforms/UsingStatementTransform.cs

@ -6,6 +6,7 @@ using System.Linq; @@ -6,6 +6,7 @@ using System.Linq;
using Decompiler.Transforms;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.PatternMatching;
using Mono.Cecil;
namespace Decompiler.Transforms
{
@ -29,18 +30,25 @@ namespace Decompiler.Transforms @@ -29,18 +30,25 @@ namespace Decompiler.Transforms
TryBlock = new AnyNode("body").ToBlock(),
FinallyBlock = new BlockStatement {
Statements = {
new IfElseStatement {
Condition = new BinaryOperatorExpression(
new NamedNode("ident", new IdentifierExpression()).ToExpression(),
BinaryOperatorType.InEquality,
new NullReferenceExpression()
),
TrueStatement = new BlockStatement {
Statements = {
new ExpressionStatement(new Backreference("ident").ToExpression().Invoke("Dispose"))
new Choice {
{ "valueType",
new ExpressionStatement(new NamedNode("ident", new IdentifierExpression()).ToExpression().Invoke("Dispose"))
},
{ "referenceType",
new IfElseStatement {
Condition = new BinaryOperatorExpression(
new NamedNode("ident", new IdentifierExpression()).ToExpression(),
BinaryOperatorType.InEquality,
new NullReferenceExpression()
),
TrueStatement = new BlockStatement {
Statements = {
new ExpressionStatement(new Backreference("ident").ToExpression().Invoke("Dispose"))
}
}
}
}
}
}.ToStatement()
}
}
};
@ -52,8 +60,14 @@ namespace Decompiler.Transforms @@ -52,8 +60,14 @@ namespace Decompiler.Transforms
if (m1 == null) continue;
Match m2 = usingTryCatchPattern.Match(node.NextSibling);
if (m2 == null) continue;
if (((VariableInitializer)m1["variable"].Single()).Name == ((IdentifierExpression)m2["ident"].Single()).Identifier) {
BlockStatement body = (BlockStatement)m2["body"].Single();
if (m1.Get<VariableInitializer>("variable").Single().Name == m2.Get<IdentifierExpression>("ident").Single().Identifier) {
if (m2.Has("valueType")) {
// if there's no if(x!=null), then it must be a value type
TypeReference tr = m1.Get<AstType>("type").Single().Annotation<TypeReference>();
if (tr == null || !tr.IsValueType)
continue;
}
BlockStatement body = m2.Get<BlockStatement>("body").Single();
body.Remove();
node.NextSibling.Remove();
node.ReplaceWith(

2
NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Backreference.cs

@ -22,7 +22,7 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching @@ -22,7 +22,7 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching
protected internal override bool DoMatch(AstNode other, Match match)
{
return match[referencedGroupName].Last().Match(other) != null;
return match.Get(referencedGroupName).Last().Match(other) != null;
}
}
}

18
NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Choice.cs

@ -2,20 +2,25 @@ @@ -2,20 +2,25 @@
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
using System;
using System.Collections;
namespace ICSharpCode.NRefactory.CSharp.PatternMatching
{
/// <summary>
/// Matches one of several alternatives.
/// </summary>
public class Choice : Pattern
public class Choice : Pattern, IEnumerable
{
public static readonly Role<AstNode> AlternativeRole = new Role<AstNode>("Alternative", AstNode.Null);
public Choice(params AstNode[] alternatives)
public void Add(string name, AstNode alternative)
{
foreach (AstNode node in alternatives)
AddChild(node, AlternativeRole);
AddChild(new NamedNode(name, alternative), AlternativeRole);
}
public void Add(AstNode alternative)
{
AddChild(alternative, AlternativeRole);
}
protected internal override bool DoMatch(AstNode other, Match match)
@ -29,5 +34,10 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching @@ -29,5 +34,10 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching
}
return false;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetChildrenByRole(AlternativeRole).GetEnumerator();
}
}
}

28
NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Match.cs

@ -24,13 +24,29 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching @@ -24,13 +24,29 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching
results.RemoveRange(checkPoint, results.Count - checkPoint);
}
public IEnumerable<AstNode> this[string groupName] {
get {
foreach (var pair in results) {
if (pair.Key == groupName)
yield return pair.Value;
}
public IEnumerable<AstNode> Get(string groupName)
{
foreach (var pair in results) {
if (pair.Key == groupName)
yield return pair.Value;
}
}
public IEnumerable<T> Get<T>(string groupName) where T : AstNode
{
foreach (var pair in results) {
if (pair.Key == groupName)
yield return (T)pair.Value;
}
}
public bool Has(string groupName)
{
foreach (var pair in results) {
if (pair.Key == groupName)
return true;
}
return false;
}
public void Add(string groupName, AstNode node)

5
NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Pattern.cs

@ -29,6 +29,11 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching @@ -29,6 +29,11 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching
return new ExpressionPlaceholder(this);
}
public Statement ToStatement()
{
return new StatementPlaceholder(this);
}
public BlockStatement ToBlock()
{
return new BlockStatementPlaceholder(this);

52
NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Placeholder.cs

@ -7,113 +7,113 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching @@ -7,113 +7,113 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching
{
sealed class TypePlaceholder : AstType
{
public static readonly Role<Pattern> PatternRole = new Role<Pattern>("Pattern");
public static readonly Role<AstNode> ChildRole = new Role<AstNode>("Child", AstNode.Null);
public TypePlaceholder(Pattern pattern)
public TypePlaceholder(AstNode child)
{
AddChild(pattern, TypePlaceholder.PatternRole);
AddChild(child, TypePlaceholder.ChildRole);
}
public override NodeType NodeType {
get { return NodeType.Pattern; }
get { return GetChildByRole(TypePlaceholder.ChildRole).NodeType; }
}
public override S AcceptVisitor<T, S>(IAstVisitor<T, S> visitor, T data)
{
return default(S);
return GetChildByRole(TypePlaceholder.ChildRole).AcceptVisitor(visitor, data);
}
protected internal override bool DoMatch(AstNode other, Match match)
{
return GetChildByRole(TypePlaceholder.PatternRole).DoMatch(other, match);
return GetChildByRole(TypePlaceholder.ChildRole).DoMatch(other, match);
}
}
sealed class ExpressionPlaceholder : Expression
{
public ExpressionPlaceholder(Pattern pattern)
public ExpressionPlaceholder(AstNode child)
{
AddChild(pattern, TypePlaceholder.PatternRole);
AddChild(child, TypePlaceholder.ChildRole);
}
public override NodeType NodeType {
get { return NodeType.Pattern; }
get { return GetChildByRole(TypePlaceholder.ChildRole).NodeType; }
}
public override S AcceptVisitor<T, S>(IAstVisitor<T, S> visitor, T data)
{
return default(S);
return GetChildByRole(TypePlaceholder.ChildRole).AcceptVisitor(visitor, data);
}
protected internal override bool DoMatch(AstNode other, Match match)
{
return GetChildByRole(TypePlaceholder.PatternRole).DoMatch(other, match);
return GetChildByRole(TypePlaceholder.ChildRole).DoMatch(other, match);
}
}
sealed class StatementPlaceholder : Statement
{
public StatementPlaceholder(Pattern pattern)
public StatementPlaceholder(AstNode child)
{
AddChild(pattern, TypePlaceholder.PatternRole);
AddChild(child, TypePlaceholder.ChildRole);
}
public override NodeType NodeType {
get { return NodeType.Pattern; }
get { return GetChildByRole(TypePlaceholder.ChildRole).NodeType; }
}
public override S AcceptVisitor<T, S>(IAstVisitor<T, S> visitor, T data)
{
return default(S);
return GetChildByRole(TypePlaceholder.ChildRole).AcceptVisitor(visitor, data);
}
protected internal override bool DoMatch(AstNode other, Match match)
{
return GetChildByRole(TypePlaceholder.PatternRole).DoMatch(other, match);
return GetChildByRole(TypePlaceholder.ChildRole).DoMatch(other, match);
}
}
sealed class BlockStatementPlaceholder : BlockStatement
{
public BlockStatementPlaceholder(Pattern pattern)
public BlockStatementPlaceholder(AstNode child)
{
AddChild(pattern, TypePlaceholder.PatternRole);
AddChild(child, TypePlaceholder.ChildRole);
}
public override NodeType NodeType {
get { return NodeType.Pattern; }
get { return GetChildByRole(TypePlaceholder.ChildRole).NodeType; }
}
public override S AcceptVisitor<T, S>(IAstVisitor<T, S> visitor, T data)
{
return default(S);
return GetChildByRole(TypePlaceholder.ChildRole).AcceptVisitor(visitor, data);
}
protected internal override bool DoMatch(AstNode other, Match match)
{
return GetChildByRole(TypePlaceholder.PatternRole).DoMatch(other, match);
return GetChildByRole(TypePlaceholder.ChildRole).DoMatch(other, match);
}
}
sealed class VariablePlaceholder : VariableInitializer
{
public VariablePlaceholder(Pattern pattern)
public VariablePlaceholder(AstNode child)
{
AddChild(pattern, TypePlaceholder.PatternRole);
AddChild(child, TypePlaceholder.ChildRole);
}
public override NodeType NodeType {
get { return NodeType.Pattern; }
get { return GetChildByRole(TypePlaceholder.ChildRole).NodeType; }
}
public override S AcceptVisitor<T, S>(IAstVisitor<T, S> visitor, T data)
{
return default(S);
return GetChildByRole(TypePlaceholder.ChildRole).AcceptVisitor(visitor, data);
}
protected internal override bool DoMatch(AstNode other, Match match)
{
return GetChildByRole(TypePlaceholder.PatternRole).DoMatch(other, match);
return GetChildByRole(TypePlaceholder.ChildRole).DoMatch(other, match);
}
}
}

Loading…
Cancel
Save