mirror of https://github.com/icsharpcode/ILSpy.git
4 changed files with 1 additions and 537 deletions
@ -1,519 +0,0 @@
@@ -1,519 +0,0 @@
|
||||
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
// software and associated documentation files (the "Software"), to deal in the Software
|
||||
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||
// to whom the Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or
|
||||
// substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using ICSharpCode.Decompiler.CSharp.Resolver; |
||||
using ICSharpCode.Decompiler.CSharp.Syntax; |
||||
using ICSharpCode.Decompiler.Semantics; |
||||
using ICSharpCode.Decompiler.TypeSystem; |
||||
using ICSharpCode.Decompiler.Util; |
||||
|
||||
namespace ICSharpCode.Decompiler.CSharp.TypeSystem |
||||
{ |
||||
// Contains representations for constant C# expressions.
|
||||
// We use these instead of storing the full AST to reduce the memory usage.
|
||||
|
||||
[Serializable] |
||||
public abstract class ConstantExpression : IConstantValue |
||||
{ |
||||
public abstract ResolveResult Resolve(CSharpResolver resolver); |
||||
|
||||
public ResolveResult Resolve(ITypeResolveContext context) |
||||
{ |
||||
var csContext = (CSharpTypeResolveContext)context; |
||||
if (context.CurrentAssembly != context.Compilation.MainAssembly) { |
||||
// The constant needs to be resolved in a different compilation.
|
||||
IProjectContent pc = context.CurrentAssembly as IProjectContent; |
||||
if (pc != null) { |
||||
ICompilation nestedCompilation = context.Compilation.SolutionSnapshot.GetCompilation(pc); |
||||
if (nestedCompilation != null) { |
||||
var nestedContext = MapToNestedCompilation(csContext, nestedCompilation); |
||||
ResolveResult rr = Resolve(new CSharpResolver(nestedContext)); |
||||
return MapToNewContext(rr, context); |
||||
} |
||||
} |
||||
} |
||||
// Resolve in current context.
|
||||
return Resolve(new CSharpResolver(csContext)); |
||||
} |
||||
|
||||
CSharpTypeResolveContext MapToNestedCompilation(CSharpTypeResolveContext context, ICompilation nestedCompilation) |
||||
{ |
||||
var nestedContext = new CSharpTypeResolveContext(nestedCompilation.MainAssembly); |
||||
if (context.CurrentUsingScope != null) { |
||||
nestedContext = nestedContext.WithUsingScope(context.CurrentUsingScope.UnresolvedUsingScope.Resolve(nestedCompilation)); |
||||
} |
||||
if (context.CurrentTypeDefinition != null) { |
||||
nestedContext = nestedContext.WithCurrentTypeDefinition(nestedCompilation.Import(context.CurrentTypeDefinition)); |
||||
} |
||||
return nestedContext; |
||||
} |
||||
|
||||
static ResolveResult MapToNewContext(ResolveResult rr, ITypeResolveContext newContext) |
||||
{ |
||||
if (rr is TypeOfResolveResult) { |
||||
return new TypeOfResolveResult( |
||||
rr.Type.ToTypeReference().Resolve(newContext), |
||||
((TypeOfResolveResult)rr).ReferencedType.ToTypeReference().Resolve(newContext)); |
||||
} else if (rr is ArrayCreateResolveResult) { |
||||
ArrayCreateResolveResult acrr = (ArrayCreateResolveResult)rr; |
||||
return new ArrayCreateResolveResult( |
||||
acrr.Type.ToTypeReference().Resolve(newContext), |
||||
MapToNewContext(acrr.SizeArguments, newContext), |
||||
MapToNewContext(acrr.InitializerElements, newContext)); |
||||
} else if (rr.IsCompileTimeConstant) { |
||||
return new ConstantResolveResult( |
||||
rr.Type.ToTypeReference().Resolve(newContext), |
||||
rr.ConstantValue |
||||
); |
||||
} else { |
||||
return new ErrorResolveResult(rr.Type.ToTypeReference().Resolve(newContext)); |
||||
} |
||||
} |
||||
|
||||
static ResolveResult[] MapToNewContext(IList<ResolveResult> input, ITypeResolveContext newContext) |
||||
{ |
||||
if (input == null) |
||||
return null; |
||||
ResolveResult[] output = new ResolveResult[input.Count]; |
||||
for (int i = 0; i < output.Length; i++) { |
||||
output[i] = MapToNewContext(input[i], newContext); |
||||
} |
||||
return output; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Used for constants that could not be converted to IConstantValue.
|
||||
/// </summary>
|
||||
[Serializable] |
||||
public sealed class ErrorConstantValue : IConstantValue |
||||
{ |
||||
readonly ITypeReference type; |
||||
|
||||
public ErrorConstantValue(ITypeReference type) |
||||
{ |
||||
if (type == null) |
||||
throw new ArgumentNullException("type"); |
||||
this.type = type; |
||||
} |
||||
|
||||
public ResolveResult Resolve(ITypeResolveContext context) |
||||
{ |
||||
return new ErrorResolveResult(type.Resolve(context)); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Increments an integer <see cref="IConstantValue"/> by a fixed amount without changing the type.
|
||||
/// </summary>
|
||||
[Serializable] |
||||
public sealed class IncrementConstantValue : IConstantValue, ISupportsInterning |
||||
{ |
||||
readonly IConstantValue baseValue; |
||||
readonly int incrementAmount; |
||||
|
||||
public IncrementConstantValue(IConstantValue baseValue, int incrementAmount = 1) |
||||
{ |
||||
if (baseValue == null) |
||||
throw new ArgumentNullException("baseValue"); |
||||
IncrementConstantValue icv = baseValue as IncrementConstantValue; |
||||
if (icv != null) { |
||||
this.baseValue = icv.baseValue; |
||||
this.incrementAmount = icv.incrementAmount + incrementAmount; |
||||
} else { |
||||
this.baseValue = baseValue; |
||||
this.incrementAmount = incrementAmount; |
||||
} |
||||
} |
||||
|
||||
public ResolveResult Resolve(ITypeResolveContext context) |
||||
{ |
||||
ResolveResult rr = baseValue.Resolve(context); |
||||
if (rr.IsCompileTimeConstant && rr.ConstantValue != null) { |
||||
object val = rr.ConstantValue; |
||||
TypeCode typeCode = Type.GetTypeCode(val.GetType()); |
||||
if (typeCode >= TypeCode.SByte && typeCode <= TypeCode.UInt64) { |
||||
long intVal = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, val, false); |
||||
object newVal = CSharpPrimitiveCast.Cast(typeCode, unchecked(intVal + incrementAmount), false); |
||||
return new ConstantResolveResult(rr.Type, newVal); |
||||
} |
||||
} |
||||
return new ErrorResolveResult(rr.Type); |
||||
} |
||||
|
||||
int ISupportsInterning.GetHashCodeForInterning() |
||||
{ |
||||
unchecked { |
||||
return baseValue.GetHashCode() * 33 ^ incrementAmount; |
||||
} |
||||
} |
||||
|
||||
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) |
||||
{ |
||||
IncrementConstantValue o = other as IncrementConstantValue; |
||||
return o != null && baseValue == o.baseValue && incrementAmount == o.incrementAmount; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// C#'s equivalent to the SimpleConstantValue.
|
||||
/// </summary>
|
||||
[Serializable] |
||||
public sealed class PrimitiveConstantExpression : ConstantExpression, ISupportsInterning |
||||
{ |
||||
readonly ITypeReference type; |
||||
readonly object value; |
||||
|
||||
public ITypeReference Type { |
||||
get { return type; } |
||||
} |
||||
|
||||
public object Value { |
||||
get { return value; } |
||||
} |
||||
|
||||
public PrimitiveConstantExpression(ITypeReference type, object value) |
||||
{ |
||||
if (type == null) |
||||
throw new ArgumentNullException("type"); |
||||
this.type = type; |
||||
this.value = value; |
||||
} |
||||
|
||||
public override ResolveResult Resolve(CSharpResolver resolver) |
||||
{ |
||||
return new ConstantResolveResult(type.Resolve(resolver.CurrentTypeResolveContext), value); |
||||
} |
||||
|
||||
int ISupportsInterning.GetHashCodeForInterning() |
||||
{ |
||||
return type.GetHashCode() ^ (value != null ? value.GetHashCode() : 0); |
||||
} |
||||
|
||||
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) |
||||
{ |
||||
PrimitiveConstantExpression scv = other as PrimitiveConstantExpression; |
||||
return scv != null && type == scv.type && value == scv.value; |
||||
} |
||||
} |
||||
|
||||
[Serializable] |
||||
public sealed class TypeOfConstantExpression : ConstantExpression |
||||
{ |
||||
readonly ITypeReference type; |
||||
|
||||
public ITypeReference Type { |
||||
get { return type; } |
||||
} |
||||
|
||||
public TypeOfConstantExpression(ITypeReference type) |
||||
{ |
||||
this.type = type; |
||||
} |
||||
|
||||
public override ResolveResult Resolve(CSharpResolver resolver) |
||||
{ |
||||
return resolver.ResolveTypeOf(type.Resolve(resolver.CurrentTypeResolveContext)); |
||||
} |
||||
} |
||||
|
||||
[Serializable] |
||||
public sealed class ConstantCast : ConstantExpression, ISupportsInterning |
||||
{ |
||||
readonly ITypeReference targetType; |
||||
readonly ConstantExpression expression; |
||||
readonly bool allowNullableConstants; |
||||
|
||||
public ConstantCast(ITypeReference targetType, ConstantExpression expression, bool allowNullableConstants) |
||||
{ |
||||
if (targetType == null) |
||||
throw new ArgumentNullException("targetType"); |
||||
if (expression == null) |
||||
throw new ArgumentNullException("expression"); |
||||
this.targetType = targetType; |
||||
this.expression = expression; |
||||
this.allowNullableConstants = allowNullableConstants; |
||||
} |
||||
|
||||
public override ResolveResult Resolve(CSharpResolver resolver) |
||||
{ |
||||
var type = targetType.Resolve(resolver.CurrentTypeResolveContext); |
||||
var resolveResult = expression.Resolve(resolver); |
||||
if (allowNullableConstants && NullableType.IsNullable(type)) { |
||||
resolveResult = resolver.ResolveCast(NullableType.GetUnderlyingType(type), resolveResult); |
||||
if (resolveResult.IsCompileTimeConstant) |
||||
return new ConstantResolveResult(type, resolveResult.ConstantValue); |
||||
} |
||||
return resolver.ResolveCast(type, resolveResult); |
||||
} |
||||
|
||||
int ISupportsInterning.GetHashCodeForInterning() |
||||
{ |
||||
unchecked { |
||||
return targetType.GetHashCode() + expression.GetHashCode() * 1018829; |
||||
} |
||||
} |
||||
|
||||
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) |
||||
{ |
||||
ConstantCast cast = other as ConstantCast; |
||||
return cast != null |
||||
&& this.targetType == cast.targetType && this.expression == cast.expression && this.allowNullableConstants == cast.allowNullableConstants; |
||||
} |
||||
} |
||||
|
||||
[Serializable] |
||||
public sealed class ConstantIdentifierReference : ConstantExpression |
||||
{ |
||||
readonly string identifier; |
||||
readonly IList<ITypeReference> typeArguments; |
||||
|
||||
public ConstantIdentifierReference(string identifier, IList<ITypeReference> typeArguments = null) |
||||
{ |
||||
if (identifier == null) |
||||
throw new ArgumentNullException("identifier"); |
||||
this.identifier = identifier; |
||||
this.typeArguments = typeArguments ?? EmptyList<ITypeReference>.Instance; |
||||
} |
||||
|
||||
public override ResolveResult Resolve(CSharpResolver resolver) |
||||
{ |
||||
return resolver.ResolveSimpleName(identifier, typeArguments.Resolve(resolver.CurrentTypeResolveContext)); |
||||
} |
||||
} |
||||
|
||||
[Serializable] |
||||
public sealed class ConstantMemberReference : ConstantExpression |
||||
{ |
||||
readonly ITypeReference targetType; |
||||
readonly ConstantExpression targetExpression; |
||||
readonly string memberName; |
||||
readonly IList<ITypeReference> typeArguments; |
||||
|
||||
public ConstantMemberReference(ITypeReference targetType, string memberName, IList<ITypeReference> typeArguments = null) |
||||
{ |
||||
if (targetType == null) |
||||
throw new ArgumentNullException("targetType"); |
||||
if (memberName == null) |
||||
throw new ArgumentNullException("memberName"); |
||||
this.targetType = targetType; |
||||
this.memberName = memberName; |
||||
this.typeArguments = typeArguments ?? EmptyList<ITypeReference>.Instance; |
||||
} |
||||
|
||||
public ConstantMemberReference(ConstantExpression targetExpression, string memberName, IList<ITypeReference> typeArguments = null) |
||||
{ |
||||
if (targetExpression == null) |
||||
throw new ArgumentNullException("targetExpression"); |
||||
if (memberName == null) |
||||
throw new ArgumentNullException("memberName"); |
||||
this.targetExpression = targetExpression; |
||||
this.memberName = memberName; |
||||
this.typeArguments = typeArguments ?? EmptyList<ITypeReference>.Instance; |
||||
} |
||||
|
||||
public override ResolveResult Resolve(CSharpResolver resolver) |
||||
{ |
||||
ResolveResult rr; |
||||
if (targetType != null) |
||||
rr = new TypeResolveResult(targetType.Resolve(resolver.CurrentTypeResolveContext)); |
||||
else |
||||
rr = targetExpression.Resolve(resolver); |
||||
return resolver.ResolveMemberAccess(rr, memberName, typeArguments.Resolve(resolver.CurrentTypeResolveContext)); |
||||
} |
||||
} |
||||
|
||||
[Serializable] |
||||
public sealed class ConstantCheckedExpression : ConstantExpression |
||||
{ |
||||
readonly bool checkForOverflow; |
||||
readonly ConstantExpression expression; |
||||
|
||||
public ConstantCheckedExpression(bool checkForOverflow, ConstantExpression expression) |
||||
{ |
||||
if (expression == null) |
||||
throw new ArgumentNullException("expression"); |
||||
this.checkForOverflow = checkForOverflow; |
||||
this.expression = expression; |
||||
} |
||||
|
||||
public override ResolveResult Resolve(CSharpResolver resolver) |
||||
{ |
||||
return expression.Resolve(resolver.WithCheckForOverflow(checkForOverflow)); |
||||
} |
||||
} |
||||
|
||||
[Serializable] |
||||
public sealed class ConstantDefaultValue : ConstantExpression, ISupportsInterning |
||||
{ |
||||
readonly ITypeReference type; |
||||
|
||||
public ConstantDefaultValue(ITypeReference type) |
||||
{ |
||||
if (type == null) |
||||
throw new ArgumentNullException("type"); |
||||
this.type = type; |
||||
} |
||||
|
||||
public override ResolveResult Resolve(CSharpResolver resolver) |
||||
{ |
||||
return resolver.ResolveDefaultValue(type.Resolve(resolver.CurrentTypeResolveContext)); |
||||
} |
||||
|
||||
int ISupportsInterning.GetHashCodeForInterning() |
||||
{ |
||||
return type.GetHashCode(); |
||||
} |
||||
|
||||
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) |
||||
{ |
||||
ConstantDefaultValue o = other as ConstantDefaultValue; |
||||
return o != null && this.type == o.type; |
||||
} |
||||
} |
||||
|
||||
[Serializable] |
||||
public sealed class ConstantUnaryOperator : ConstantExpression |
||||
{ |
||||
readonly UnaryOperatorType operatorType; |
||||
readonly ConstantExpression expression; |
||||
|
||||
public ConstantUnaryOperator(UnaryOperatorType operatorType, ConstantExpression expression) |
||||
{ |
||||
if (expression == null) |
||||
throw new ArgumentNullException("expression"); |
||||
this.operatorType = operatorType; |
||||
this.expression = expression; |
||||
} |
||||
|
||||
public override ResolveResult Resolve(CSharpResolver resolver) |
||||
{ |
||||
return resolver.ResolveUnaryOperator(operatorType, expression.Resolve(resolver)); |
||||
} |
||||
} |
||||
|
||||
[Serializable] |
||||
public sealed class ConstantBinaryOperator : ConstantExpression |
||||
{ |
||||
readonly ConstantExpression left; |
||||
readonly BinaryOperatorType operatorType; |
||||
readonly ConstantExpression right; |
||||
|
||||
public ConstantBinaryOperator(ConstantExpression left, BinaryOperatorType operatorType, ConstantExpression right) |
||||
{ |
||||
if (left == null) |
||||
throw new ArgumentNullException("left"); |
||||
if (right == null) |
||||
throw new ArgumentNullException("right"); |
||||
this.left = left; |
||||
this.operatorType = operatorType; |
||||
this.right = right; |
||||
} |
||||
|
||||
public override ResolveResult Resolve(CSharpResolver resolver) |
||||
{ |
||||
ResolveResult lhs = left.Resolve(resolver); |
||||
ResolveResult rhs = right.Resolve(resolver); |
||||
return resolver.ResolveBinaryOperator(operatorType, lhs, rhs); |
||||
} |
||||
} |
||||
|
||||
[Serializable] |
||||
public sealed class ConstantConditionalOperator : ConstantExpression |
||||
{ |
||||
readonly ConstantExpression condition, trueExpr, falseExpr; |
||||
|
||||
public ConstantConditionalOperator(ConstantExpression condition, ConstantExpression trueExpr, ConstantExpression falseExpr) |
||||
{ |
||||
if (condition == null) |
||||
throw new ArgumentNullException("condition"); |
||||
if (trueExpr == null) |
||||
throw new ArgumentNullException("trueExpr"); |
||||
if (falseExpr == null) |
||||
throw new ArgumentNullException("falseExpr"); |
||||
this.condition = condition; |
||||
this.trueExpr = trueExpr; |
||||
this.falseExpr = falseExpr; |
||||
} |
||||
|
||||
public override ResolveResult Resolve(CSharpResolver resolver) |
||||
{ |
||||
return resolver.ResolveConditional( |
||||
condition.Resolve(resolver), |
||||
trueExpr.Resolve(resolver), |
||||
falseExpr.Resolve(resolver) |
||||
); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents an array creation (as used within an attribute argument)
|
||||
/// </summary>
|
||||
[Serializable] |
||||
public sealed class ConstantArrayCreation : ConstantExpression |
||||
{ |
||||
// type may be null when the element is being inferred
|
||||
readonly ITypeReference elementType; |
||||
readonly IList<ConstantExpression> arrayElements; |
||||
|
||||
public ConstantArrayCreation(ITypeReference type, IList<ConstantExpression> arrayElements) |
||||
{ |
||||
if (arrayElements == null) |
||||
throw new ArgumentNullException("arrayElements"); |
||||
this.elementType = type; |
||||
this.arrayElements = arrayElements; |
||||
} |
||||
|
||||
public override ResolveResult Resolve(CSharpResolver resolver) |
||||
{ |
||||
ResolveResult[] elements = new ResolveResult[arrayElements.Count]; |
||||
for (int i = 0; i < elements.Length; i++) { |
||||
elements[i] = arrayElements[i].Resolve(resolver); |
||||
} |
||||
int[] sizeArguments = { elements.Length }; |
||||
if (elementType != null) { |
||||
return resolver.ResolveArrayCreation(elementType.Resolve(resolver.CurrentTypeResolveContext), sizeArguments, elements); |
||||
} else { |
||||
return resolver.ResolveArrayCreation(null, sizeArguments, elements); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Used for sizeof() expressions in constants.
|
||||
/// </summary>
|
||||
[Serializable] |
||||
public sealed class SizeOfConstantValue : ConstantExpression |
||||
{ |
||||
readonly ITypeReference type; |
||||
|
||||
public SizeOfConstantValue(ITypeReference type) |
||||
{ |
||||
if (type == null) |
||||
throw new ArgumentNullException("type"); |
||||
this.type = type; |
||||
} |
||||
|
||||
public override ResolveResult Resolve(CSharpResolver resolver) |
||||
{ |
||||
return resolver.ResolveSizeOf(type.Resolve(resolver.CurrentTypeResolveContext)); |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue