@ -96,11 +96,6 @@ namespace ICSharpCode.Decompiler.ILAst
@@ -96,11 +96,6 @@ namespace ICSharpCode.Decompiler.ILAst
{
return e . Code = = this . code ;
}
public override ILExpression BuildNew ( ref PatternMatcher pm , ILExpression [ ] args )
{
return new ILExpression ( this . code , null , args ) ;
}
}
sealed class MethodPattern : Pattern
@ -144,10 +139,17 @@ namespace ICSharpCode.Decompiler.ILAst
@@ -144,10 +139,17 @@ namespace ICSharpCode.Decompiler.ILAst
case ILCode . Ceq :
if ( ! equals . GetValueOrDefault ( ) | | custom . GetValueOrDefault ( ) ) return false ;
break ;
case ILCode . Cne :
if ( equals . GetValueOrDefault ( true ) | | custom . GetValueOrDefault ( ) ) return false ;
break ;
case ILCode . Cgt :
case ILCode . Cgt_Un :
case ILCode . Cge :
case ILCode . Cge_Un :
case ILCode . Clt :
case ILCode . Clt_Un :
case ILCode . Cle :
case ILCode . Cle_Un :
if ( equals ! = null | | custom . GetValueOrDefault ( ) ) return false ;
break ;
case ILCode . Call :
@ -219,37 +221,17 @@ namespace ICSharpCode.Decompiler.ILAst
@@ -219,37 +221,17 @@ namespace ICSharpCode.Decompiler.ILAst
}
}
sealed class PrimitivePattern : Pattern
{
readonly ILCode code ;
readonly object operand ;
public PrimitivePattern ( ILCode code , object operand , params Pattern [ ] arguments )
: base ( arguments )
{
this . code = code ;
this . operand = operand ;
}
public override bool Match ( ref PatternMatcher pm , ILExpression e )
{
return e . Code = = code & & object . Equals ( e . Operand , this . operand ) ;
}
}
static readonly Tuple < string , string , string > GetValueOrDefault = new Tuple < string , string , string > ( "GetValueOrDefault" , "Nullable`1" , "System" ) ;
static readonly Tuple < string , string , string > get_HasValue = new Tuple < string , string , string > ( "get_HasValue" , "Nullable`1" , "System" ) ;
static readonly Pattern VariableRefA = new VariablePattern ( ILCode . Ldloca , false ) , VariableRefB = new VariablePattern ( ILCode . Ldloca , true ) ;
static readonly Pattern VariableA = new VariablePattern ( ILCode . Ldloc , false ) , VariableB = new VariablePattern ( ILCode . Ldloc , true ) ;
static readonly Pattern VariableAHasValue = new MethodPattern ( ILCode . CallGetter , get_HasValue , VariableRefA ) ;
static readonly Pattern VariableAGetValueOrDefault = new MethodPattern ( ILCode . Call , GetValueOrDefault , VariableRefA ) ;
static readonly Pattern NotVariableAHasValue = new ILPattern ( ILCode . Ceq , VariableAHasValue , new PrimitivePattern ( ILCode . Ldc_I4 , 0 ) ) ;
static readonly Pattern VariableBHasValue = new MethodPattern ( ILCode . CallGetter , get_HasValue , VariableRefB ) ;
static readonly Pattern VariableBGetValueOrDefault = new MethodPattern ( ILCode . Call , GetValueOrDefault , VariableRefB ) ;
static readonly Pattern NotVariableBHasValue = new ILPattern ( ILCode . Ceq , VariableBHasValue , new PrimitivePattern ( ILCode . Ldc_I4 , 0 ) ) ;
static readonly Pattern CeqHasValue = new ILPattern ( ILCode . Ceq , VariableAHasValue , VariableBHasValue ) ;
static readonly Pattern CneHasValue = new ILPattern ( ILCode . Cne , VariableAHasValue , VariableBHasValue ) ;
static readonly Pattern AndHasValue = new ILPattern ( ILCode . And , VariableAHasValue , VariableBHasValue ) ;
static readonly Pattern NotCeqHasValue = new ILPattern ( ILCode . Ceq , CeqHasValue , new PrimitivePattern ( ILCode . Ldc_I4 , 0 ) ) ;
static readonly Pattern [ ] LoadValuesNN = new [ ] { VariableAGetValueOrDefault , VariableBGetValueOrDefault } ;
static OperatorPattern OperatorNN ( bool? equals = null , bool? custom = null )
@ -272,55 +254,43 @@ namespace ICSharpCode.Decompiler.ILAst
@@ -272,55 +254,43 @@ namespace ICSharpCode.Decompiler.ILAst
static readonly Pattern [ ] Comparisons = new Pattern [ ] {
/* both operands nullable */
// == (Primitive, Decimal)
! ! OperatorNN ( equals : true ) & CeqHasValue ,
OperatorNN ( equals : true ) & CeqHasValue ,
// == (Struct)
! ! CeqHasValue & ( ! VariableAHasValue | OperatorNN ( equals : true , custom : true ) ) ,
// != (Primitive)
! OperatorNN ( equals : true , custom : false ) | NotCeqHasValue ,
// != (Decimal)
OperatorNN ( equals : false , custom : true ) | NotCeqHasValue ,
CeqHasValue & ( ! VariableAHasValue | OperatorNN ( equals : true , custom : true ) ) ,
// != (Primitive, Decimal)
OperatorNN ( equals : false ) | CneHasValue ,
// != (Struct)
! CeqHasValue | ( ! ! VariableAHasValue & OperatorNN ( equals : false , custom : true ) ) ,
// > , < (Primitive, Decimal), >= , <= (Decimal)
! ! OperatorNN ( ) & AndHasValue ,
// >= , <= (Primitive)
! OperatorNN ( custom : false ) & AndHasValue ,
CneHasValue | ( VariableAHasValue & OperatorNN ( equals : false , custom : true ) ) ,
// > , < , >= , <= (Primitive, Decimal)
OperatorNN ( ) & AndHasValue ,
// > , < , >= , <= (Struct)
AndHasValue & OperatorNN ( custom : true ) ,
/* only first operand nullable */
// == (Primitive, Decimal)
! ! OperatorNV ( equals : true ) & VariableAHasValue ,
OperatorNV ( equals : true ) & VariableAHasValue ,
// == (Struct)
! ! VariableAHasValue & OperatorNV ( equals : true , custom : true ) ,
// != (Primitive)
! OperatorNV ( equals : true , custom : false ) | NotVariableAHasValue ,
// != (Decimal)
OperatorNV ( equals : false , custom : true ) | NotVariableAHasValue ,
VariableAHasValue & OperatorNV ( equals : true , custom : true ) ,
// != (Primitive, Decimal)
OperatorNV ( equals : false ) | ! VariableAHasValue ,
// != (Struct)
! VariableAHasValue | OperatorNV ( equals : false , custom : true ) ,
// > , < (Primitive, Decimal), >= , <= (Decimal)
! ! OperatorNV ( ) & VariableAHasValue ,
// >= , <= (Primitive)
! OperatorNV ( custom : false ) & VariableAHasValue ,
// > , <, >= , <= (Primitive, Decimal)
OperatorNV ( ) & VariableAHasValue ,
// > , < , >= , <= (Struct)
VariableAHasValue & OperatorNV ( custom : true ) ,
/* only second operand nullable */
// == (Primitive, Decimal)
! ! OperatorVN ( equals : true ) & VariableBHasValue ,
OperatorVN ( equals : true ) & VariableBHasValue ,
// == (Struct)
! ! VariableBHasValue & OperatorVN ( equals : true , custom : true ) ,
// != (Primitive)
! OperatorVN ( equals : true , custom : false ) | NotVariableBHasValue ,
// != (Decimal)
OperatorVN ( equals : false , custom : true ) | NotVariableBHasValue ,
VariableBHasValue & OperatorVN ( equals : true , custom : true ) ,
// != (Primitive, Decimal)
OperatorVN ( equals : false ) | ! VariableBHasValue ,
// != (Struct)
! VariableBHasValue | OperatorVN ( equals : false , custom : true ) ,
// > , < (Primitive, Decimal), >= , <= (Decimal)
! ! OperatorVN ( ) & VariableBHasValue ,
// >= , <= (Primitive)
! OperatorVN ( custom : false ) & VariableBHasValue ,
// > , <, >= , <= (Primitive, Decimal)
OperatorVN ( ) & VariableBHasValue ,
// > , < , >= , <= (Struct)
VariableBHasValue & OperatorVN ( custom : true ) ,
} ;
@ -345,7 +315,6 @@ namespace ICSharpCode.Decompiler.ILAst
@@ -345,7 +315,6 @@ namespace ICSharpCode.Decompiler.ILAst
}
static readonly Pattern OperatorVariableAB = new OperatorPattern ( VariableA , VariableB ) ;
static readonly Pattern NotOperatorVariableAB = ! OperatorVariableAB ;
public static bool Simplify ( ILExpression expr )
{
@ -355,12 +324,12 @@ namespace ICSharpCode.Decompiler.ILAst
@@ -355,12 +324,12 @@ namespace ICSharpCode.Decompiler.ILAst
for ( int i = 0 ; i < ps . Length ; i + + ) {
var pm = new PatternMatcher ( ) ;
if ( ! pm . Match ( ps [ i ] , expr ) ) continue ;
var pi = i % 8 ;
var n = pm . BuildNew ( pi ! = 2 & & pi ! = 6 ? OperatorVariableAB : NotOperatorVariableAB , expr ) ;
var n = pm . BuildNew ( OperatorVariableAB , expr ) ;
expr . Code = n . Code ;
expr . Operand = n . Operand ;
expr . Arguments = n . Arguments ;
expr . ILRanges = n . ILRanges ;
expr . InferredType = n . InferredType ;
return true ;
}
return false ;