Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Commit

Permalink
Merge pull request #3763 from bartdesmet/Issue-3758
Browse files Browse the repository at this point in the history
Fixing expression interpreter for Increment and Decrement nodes
  • Loading branch information
VSadov committed Oct 12, 2015
2 parents 167450b + b76db20 commit 708c8e5
Show file tree
Hide file tree
Showing 6 changed files with 781 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,7 @@ public override string ToString()

internal abstract class IncrementInstruction : Instruction
{
private static Instruction s_int16, s_int32, s_int64, s_UInt16, s_UInt32, s_single, s_double;
private static Instruction s_int16, s_int32, s_int64, s_UInt16, s_UInt32, s_UInt64, s_single, s_double;

public override int ConsumedStack { get { return 1; } }
public override int ProducedStack { get { return 1; } }
Expand Down Expand Up @@ -763,7 +763,7 @@ public override int Run(InterpretedFrame frame)
}
else
{
frame.Push((Int16)unchecked(1 + (Int16)obj));
frame.Push(unchecked((Int16)(1 + (Int16)obj)));
}
return +1;
}
Expand All @@ -780,7 +780,7 @@ public override int Run(InterpretedFrame frame)
}
else
{
frame.Push((Int64)unchecked(1 + (Int64)obj));
frame.Push(unchecked((Int64)(1 + (Int64)obj)));
}
return +1;
}
Expand All @@ -797,7 +797,7 @@ public override int Run(InterpretedFrame frame)
}
else
{
frame.Push((Int16)unchecked(1 + (UInt16)obj));
frame.Push(unchecked((UInt16)(1 + (UInt16)obj)));
}
return +1;
}
Expand All @@ -814,7 +814,24 @@ public override int Run(InterpretedFrame frame)
}
else
{
frame.Push((Int32)unchecked(1 + (UInt32)obj));
frame.Push(unchecked((UInt32)(1 + (UInt32)obj)));
}
return +1;
}
}

internal sealed class IncrementUInt64 : IncrementInstruction
{
public override int Run(InterpretedFrame frame)
{
object obj = frame.Pop();
if (obj == null)
{
frame.Push(null);
}
else
{
frame.Push(unchecked((UInt64)(1 + (UInt64)obj)));
}
return +1;
}
Expand All @@ -831,7 +848,7 @@ public override int Run(InterpretedFrame frame)
}
else
{
frame.Push((Single)unchecked(1 + (Single)obj));
frame.Push(unchecked((Single)(1 + (Single)obj)));
}
return +1;
}
Expand All @@ -848,7 +865,7 @@ public override int Run(InterpretedFrame frame)
}
else
{
frame.Push((Double)unchecked(1 + (Double)obj));
frame.Push(unchecked((Double)(1 + (Double)obj)));
}
return +1;
}
Expand All @@ -857,13 +874,14 @@ public override int Run(InterpretedFrame frame)
public static Instruction Create(Type type)
{
Debug.Assert(!type.GetTypeInfo().IsEnum);
switch (System.Dynamic.Utils.TypeExtensions.GetTypeCode(type))
switch (System.Dynamic.Utils.TypeExtensions.GetTypeCode(TypeUtils.GetNonNullableType(type)))
{
case TypeCode.Int16: return s_int16 ?? (s_int16 = new IncrementInt16());
case TypeCode.Int32: return s_int32 ?? (s_int32 = new IncrementInt32());
case TypeCode.Int64: return s_int64 ?? (s_int64 = new IncrementInt64());
case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new IncrementUInt16());
case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new IncrementUInt32());
case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new IncrementUInt64());
case TypeCode.Single: return s_single ?? (s_single = new IncrementSingle());
case TypeCode.Double: return s_double ?? (s_double = new IncrementDouble());

Expand All @@ -880,7 +898,7 @@ public override string ToString()

internal abstract class DecrementInstruction : Instruction
{
private static Instruction s_int16, s_int32, s_int64, s_UInt16, s_UInt32, s_single, s_double;
private static Instruction s_int16, s_int32, s_int64, s_UInt16, s_UInt32, s_UInt64, s_single, s_double;

public override int ConsumedStack { get { return 1; } }
public override int ProducedStack { get { return 1; } }
Expand Down Expand Up @@ -920,7 +938,7 @@ public override int Run(InterpretedFrame frame)
}
else
{
frame.Push((Int16)unchecked((Int16)obj - 1));
frame.Push(unchecked((Int16)((Int16)obj - 1)));
}
return +1;
}
Expand All @@ -937,7 +955,7 @@ public override int Run(InterpretedFrame frame)
}
else
{
frame.Push((Int64)unchecked((Int64)obj - 1));
frame.Push(unchecked((Int64)((Int64)obj - 1)));
}
return +1;
}
Expand All @@ -954,7 +972,7 @@ public override int Run(InterpretedFrame frame)
}
else
{
frame.Push((Int16)unchecked((UInt16)obj - 1));
frame.Push(unchecked((UInt16)((UInt16)obj - 1)));
}
return +1;
}
Expand All @@ -971,7 +989,24 @@ public override int Run(InterpretedFrame frame)
}
else
{
frame.Push(unchecked((UInt32)obj - 1));
frame.Push(unchecked((UInt32)((UInt32)obj - 1)));
}
return +1;
}
}

internal sealed class DecrementUInt64 : DecrementInstruction
{
public override int Run(InterpretedFrame frame)
{
object obj = frame.Pop();
if (obj == null)
{
frame.Push(null);
}
else
{
frame.Push(unchecked((UInt64)((UInt64)obj - 1)));
}
return +1;
}
Expand All @@ -988,7 +1023,7 @@ public override int Run(InterpretedFrame frame)
}
else
{
frame.Push(unchecked((Single)obj - 1));
frame.Push(unchecked((Single)((Single)obj - 1)));
}
return +1;
}
Expand All @@ -1005,7 +1040,7 @@ public override int Run(InterpretedFrame frame)
}
else
{
frame.Push((Double)unchecked((Double)obj - 1));
frame.Push(unchecked((Double)((Double)obj - 1)));
}
return +1;
}
Expand All @@ -1014,13 +1049,14 @@ public override int Run(InterpretedFrame frame)
public static Instruction Create(Type type)
{
Debug.Assert(!type.GetTypeInfo().IsEnum);
switch (System.Dynamic.Utils.TypeExtensions.GetTypeCode(type))
switch (System.Dynamic.Utils.TypeExtensions.GetTypeCode(TypeUtils.GetNonNullableType(type)))
{
case TypeCode.Int16: return s_int16 ?? (s_int16 = new DecrementInt16());
case TypeCode.Int32: return s_int32 ?? (s_int32 = new DecrementInt32());
case TypeCode.Int64: return s_int64 ?? (s_int64 = new DecrementInt64());
case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new DecrementUInt16());
case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new DecrementUInt32());
case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new DecrementUInt64());
case TypeCode.Single: return s_single ?? (s_single = new DecrementSingle());
case TypeCode.Double: return s_double ?? (s_double = new DecrementDouble());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@
<Compile Include="Unary\UnaryArithmeticNegateCheckedTests.cs" />
<Compile Include="Unary\UnaryArithmeticNegateTests.cs" />
<Compile Include="Unary\UnaryBitwiseNotNullableTests.cs" />
<Compile Include="Unary\UnaryDecrementTests.cs" />
<Compile Include="Unary\UnaryDecrementNullableTests.cs" />
<Compile Include="Unary\UnaryIncrementNullableTests.cs" />
<Compile Include="Unary\UnaryIncrementTests.cs" />
<Compile Include="Unary\UnaryBitwiseNotTests.cs" />
<Compile Include="Unary\UnaryIsFalseNullableTests.cs" />
<Compile Include="Unary\UnaryIsFalseTests.cs" />
Expand All @@ -154,4 +158,4 @@
</ProjectReference>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>
</Project>
181 changes: 181 additions & 0 deletions src/System.Linq.Expressions/tests/Unary/UnaryDecrementNullableTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Linq;
using System.Linq.Expressions;
using Xunit;

namespace Tests.ExpressionCompiler.Unary
{
public static unsafe class UnaryDecrementNullableTests
{
#region Test methods

[Fact]
public static void CheckUnaryDecrementNullableShortTest()
{
short?[] values = new short?[] { null, 0, 1, -1, short.MinValue, short.MaxValue };
for (int i = 0; i < values.Length; i++)
{
VerifyDecrementNullableShort(values[i]);
}
}

[Fact]
public static void CheckUnaryDecrementNullableUShortTest()
{
ushort?[] values = new ushort?[] { null, 0, 1, ushort.MaxValue };
for (int i = 0; i < values.Length; i++)
{
VerifyDecrementNullableUShort(values[i]);
}
}

[Fact]
public static void CheckUnaryDecrementNullableIntTest()
{
int?[] values = new int?[] { null, 0, 1, -1, int.MinValue, int.MaxValue };
for (int i = 0; i < values.Length; i++)
{
VerifyDecrementNullableInt(values[i]);
}
}

[Fact]
public static void CheckUnaryDecrementNullableUIntTest()
{
uint?[] values = new uint?[] { null, 0, 1, uint.MaxValue };
for (int i = 0; i < values.Length; i++)
{
VerifyDecrementNullableUInt(values[i]);
}
}

[Fact]
public static void CheckUnaryDecrementNullableLongTest()
{
long?[] values = new long?[] { null, 0, 1, -1, long.MinValue, long.MaxValue };
for (int i = 0; i < values.Length; i++)
{
VerifyDecrementNullableLong(values[i]);
}
}

[Fact]
public static void CheckUnaryDecrementNullableULongTest()
{
ulong?[] values = new ulong?[] { null, 0, 1, ulong.MaxValue };
for (int i = 0; i < values.Length; i++)
{
VerifyDecrementNullableULong(values[i]);
}
}

[Fact]
public static void CheckDecrementFloatTest()
{
float?[] values = new float?[] { null, 0, 1, -1, float.MinValue, float.MaxValue, float.Epsilon, float.NegativeInfinity, float.PositiveInfinity, float.NaN };
for (int i = 0; i < values.Length; i++)
{
VerifyDecrementNullableFloat(values[i]);
}
}

[Fact]
public static void CheckDecrementDoubleTest()
{
double?[] values = new double?[] { null, 0, 1, -1, double.MinValue, double.MaxValue, double.Epsilon, double.NegativeInfinity, double.PositiveInfinity, double.NaN };
for (int i = 0; i < values.Length; i++)
{
VerifyDecrementNullableDouble(values[i]);
}
}

#endregion

#region Test verifiers

private static void VerifyDecrementNullableShort(short? value)
{
Expression<Func<short?>> e =
Expression.Lambda<Func<short?>>(
Expression.Decrement(Expression.Constant(value, typeof(short?))),
Enumerable.Empty<ParameterExpression>());
Func<short?> f = e.Compile();
Assert.Equal((short?)(--value), f());
}

private static void VerifyDecrementNullableUShort(ushort? value)
{
Expression<Func<ushort?>> e =
Expression.Lambda<Func<ushort?>>(
Expression.Decrement(Expression.Constant(value, typeof(ushort?))),
Enumerable.Empty<ParameterExpression>());
Func<ushort?> f = e.Compile();
Assert.Equal((ushort?)(--value), f());
}

private static void VerifyDecrementNullableInt(int? value)
{
Expression<Func<int?>> e =
Expression.Lambda<Func<int?>>(
Expression.Decrement(Expression.Constant(value, typeof(int?))),
Enumerable.Empty<ParameterExpression>());
Func<int?> f = e.Compile();
Assert.Equal((int?)(--value), f());
}

private static void VerifyDecrementNullableUInt(uint? value)
{
Expression<Func<uint?>> e =
Expression.Lambda<Func<uint?>>(
Expression.Decrement(Expression.Constant(value, typeof(uint?))),
Enumerable.Empty<ParameterExpression>());
Func<uint?> f = e.Compile();
Assert.Equal((uint?)(--value), f());
}

private static void VerifyDecrementNullableLong(long? value)
{
Expression<Func<long?>> e =
Expression.Lambda<Func<long?>>(
Expression.Decrement(Expression.Constant(value, typeof(long?))),
Enumerable.Empty<ParameterExpression>());
Func<long?> f = e.Compile();
Assert.Equal((long?)(--value), f());
}

private static void VerifyDecrementNullableULong(ulong? value)
{
Expression<Func<ulong?>> e =
Expression.Lambda<Func<ulong?>>(
Expression.Decrement(Expression.Constant(value, typeof(ulong?))),
Enumerable.Empty<ParameterExpression>());
Func<ulong?> f = e.Compile();
Assert.Equal((ulong?)(--value), f());
}

private static void VerifyDecrementNullableFloat(float? value)
{
Expression<Func<float?>> e =
Expression.Lambda<Func<float?>>(
Expression.Decrement(Expression.Constant(value, typeof(float?))),
Enumerable.Empty<ParameterExpression>());
Func<float?> f = e.Compile();
Assert.Equal((float?)(--value), f());
}

private static void VerifyDecrementNullableDouble(double? value)
{
Expression<Func<double?>> e =
Expression.Lambda<Func<double?>>(
Expression.Decrement(Expression.Constant(value, typeof(double?))),
Enumerable.Empty<ParameterExpression>());
Func<double?> f = e.Compile();
Assert.Equal((double?)(--value), f());
}

#endregion
}
}
Loading

0 comments on commit 708c8e5

Please sign in to comment.