Skip to content

Commit

Permalink
Implement relational patterns for decimal. (#41912)
Browse files Browse the repository at this point in the history
* Implement relational patterns for decimal.
* Implements and tests null purity checking for the type pattern `object` (e.g. in `is not object`).
* Significantly improves the debug dumper for the decision dag builder.
* Fixed a bug in EnumeratedValueSet and enhanced the fuzz tests to catch it.
* Move to common random-set generation code.
* Rename the typeclass interfaces xTC to IxTC.
* Improve the `ToString` for `char`.
* Add double complement tests.
  • Loading branch information
Neal Gafter authored Feb 28, 2020
1 parent 431cf4c commit 400d27b
Show file tree
Hide file tree
Showing 28 changed files with 696 additions and 278 deletions.
11 changes: 2 additions & 9 deletions Compilers.sln
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29519.87
# Visual Studio 15
VisualStudioVersion = 15.0.27102.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.UnitTests", "src\Compilers\Core\CodeAnalysisTest\Microsoft.CodeAnalysis.UnitTests.csproj", "{A4C99B85-765C-4C65-9C2A-BB609AAB09E6}"
EndProject
Expand Down Expand Up @@ -160,8 +160,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BuildBoss", "src\Tools\Buil
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Net.Compilers.Toolset.Package", "src\NuGet\Microsoft.Net.Compilers.Toolset\Microsoft.Net.Compilers.Toolset.Package.csproj", "{6D407402-CC4A-4125-9B00-C70562A636A5}"
EndProject
Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "vbi", "src\Interactive\vbi\vbi.vbproj", "{706CFC25-B6E0-4DAA-BCC4-F6FAAFEEDF87}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
src\Compilers\Core\AnalyzerDriver\AnalyzerDriver.projitems*{1ee8cad3-55f9-4d91-96b2-084641da9a6c}*SharedItemsImports = 4
Expand Down Expand Up @@ -437,10 +435,6 @@ Global
{6D407402-CC4A-4125-9B00-C70562A636A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6D407402-CC4A-4125-9B00-C70562A636A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6D407402-CC4A-4125-9B00-C70562A636A5}.Release|Any CPU.Build.0 = Release|Any CPU
{706CFC25-B6E0-4DAA-BCC4-F6FAAFEEDF87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{706CFC25-B6E0-4DAA-BCC4-F6FAAFEEDF87}.Debug|Any CPU.Build.0 = Debug|Any CPU
{706CFC25-B6E0-4DAA-BCC4-F6FAAFEEDF87}.Release|Any CPU.ActiveCfg = Release|Any CPU
{706CFC25-B6E0-4DAA-BCC4-F6FAAFEEDF87}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -514,7 +508,6 @@ Global
{B446E771-AB52-41C9-ACFC-FDF8EACAF291} = {FD0FAF5F-1DED-485C-99FA-84B97F3A8EEC}
{8A02AFAF-F622-4E3E-9E1A-8CFDACC7C7E1} = {FD0FAF5F-1DED-485C-99FA-84B97F3A8EEC}
{6D407402-CC4A-4125-9B00-C70562A636A5} = {274B96B7-F815-47E3-9CA4-4024A57A478F}
{706CFC25-B6E0-4DAA-BCC4-F6FAAFEEDF87} = {3FF38FD4-DF16-44B0-924F-0D5AE155495B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6F599E08-A9EA-4FAA-897F-5D824B0210E6}
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1262,6 +1262,7 @@ private BoundPattern BindRelationalPattern(
SpecialType.System_UInt32 => BinaryOperatorKind.UInt,
SpecialType.System_Int64 => BinaryOperatorKind.Long,
SpecialType.System_UInt64 => BinaryOperatorKind.ULong,
SpecialType.System_Decimal => BinaryOperatorKind.Decimal,
_ => BinaryOperatorKind.Error,
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ BoundExpression makeRelationalTest(BoundExpression input, BinaryOperatorKind ope
literal = _factory.Literal(literal.ConstantValue.Int32Value);
}

return _factory.Binary(operatorKind, comparisonType, input, literal);
return this._localRewriter.MakeBinaryOperator(_factory.Syntax, operatorKind, input, literal, comparisonType, method: null);
}

BoundExpression makeEqualityTest(BoundExpression loweredLiteral, BoundExpression input)
Expand Down
6 changes: 3 additions & 3 deletions src/Compilers/CSharp/Portable/Utilities/IValueSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ namespace Microsoft.CodeAnalysis.CSharp
/// <summary>
/// An interface representing a set of values of a specific type. During construction of the state machine
/// for pattern-matching, we track the set of values of each intermediate result that can reach each state.
/// That permits us to determine when tests can be eliminated either because they are impossible (can be
/// That permits us to determine when tests can be eliminated either because they are impossible (and can be
/// replaced by an always-false test) or always true with the set of values that can reach that state (and
/// can be replaced by an always true test).
/// can be replaced by an always-true test).
/// </summary>
internal interface IValueSet
{
Expand All @@ -32,7 +32,7 @@ internal interface IValueSet

/// <summary>
/// Test if the value set contains any values that satisfy the given relation with the given value. Supported values for <paramref name="relation"/>
/// Are <see cref="BinaryOperatorKind.Equal"/> for all supported types, and for numeric types (except decimal) we also support
/// are <see cref="BinaryOperatorKind.Equal"/> for all supported types, and for numeric types we also support
/// <see cref="BinaryOperatorKind.LessThan"/>, <see cref="BinaryOperatorKind.LessThanOrEqual"/>, <see cref="BinaryOperatorKind.GreaterThan"/>, and
/// <see cref="BinaryOperatorKind.GreaterThanOrEqual"/>.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ namespace Microsoft.CodeAnalysis.CSharp

internal static partial class ValueSetFactory
{
private struct ByteTC : NumericTC<byte>
private struct ByteTC : INumericTC<byte>
{
byte NumericTC<byte>.MinValue => byte.MinValue;
byte INumericTC<byte>.MinValue => byte.MinValue;

byte NumericTC<byte>.MaxValue => byte.MaxValue;
byte INumericTC<byte>.MaxValue => byte.MaxValue;

(byte leftMax, byte rightMin) NumericTC<byte>.Partition(byte min, byte max)
(byte leftMax, byte rightMin) INumericTC<byte>.Partition(byte min, byte max)
{
Debug.Assert(min < max);
int half = (max - min) / 2;
Expand All @@ -28,7 +28,7 @@ private struct ByteTC : NumericTC<byte>
return (leftMax, rightMin);
}

bool NumericTC<byte>.Related(BinaryOperatorKind relation, byte left, byte right)
bool INumericTC<byte>.Related(BinaryOperatorKind relation, byte left, byte right)
{
switch (relation)
{
Expand All @@ -47,15 +47,15 @@ bool NumericTC<byte>.Related(BinaryOperatorKind relation, byte left, byte right)
}
}

byte NumericTC<byte>.Next(byte value)
byte INumericTC<byte>.Next(byte value)
{
Debug.Assert(value != byte.MaxValue);
return (byte)(value + 1);
}

byte EqualableValueTC<byte>.FromConstantValue(ConstantValue constantValue) => constantValue.ByteValue;
byte INumericTC<byte>.FromConstantValue(ConstantValue constantValue) => constantValue.ByteValue;

string NumericTC<byte>.ToString(byte value) => value.ToString();
string INumericTC<byte>.ToString(byte value) => value.ToString();
}
}
}
25 changes: 17 additions & 8 deletions src/Compilers/CSharp/Portable/Utilities/ValueSetFactory.CharTC.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

using System;
using System.Diagnostics;
using System.Globalization;
using System.Linq;

#nullable enable

Expand All @@ -13,13 +15,13 @@ namespace Microsoft.CodeAnalysis.CSharp

internal static partial class ValueSetFactory
{
private struct CharTC : NumericTC<char>
private struct CharTC : INumericTC<char>
{
char NumericTC<char>.MinValue => char.MinValue;
char INumericTC<char>.MinValue => char.MinValue;

char NumericTC<char>.MaxValue => char.MaxValue;
char INumericTC<char>.MaxValue => char.MaxValue;

(char leftMax, char rightMin) NumericTC<char>.Partition(char min, char max)
(char leftMax, char rightMin) INumericTC<char>.Partition(char min, char max)
{
Debug.Assert(min < max);
int half = (max - min) / 2;
Expand All @@ -28,7 +30,7 @@ private struct CharTC : NumericTC<char>
return (leftMax, rightMin);
}

bool NumericTC<char>.Related(BinaryOperatorKind relation, char left, char right)
bool INumericTC<char>.Related(BinaryOperatorKind relation, char left, char right)
{
switch (relation)
{
Expand All @@ -47,15 +49,22 @@ bool NumericTC<char>.Related(BinaryOperatorKind relation, char left, char right)
}
}

char NumericTC<char>.Next(char value)
char INumericTC<char>.Next(char value)
{
Debug.Assert(value != char.MaxValue);
return (char)(value + 1);
}

char EqualableValueTC<char>.FromConstantValue(ConstantValue constantValue) => constantValue.CharValue;
char INumericTC<char>.FromConstantValue(ConstantValue constantValue) => constantValue.CharValue;

string NumericTC<char>.ToString(char value) => $"'{value}'";
string INumericTC<char>.ToString(char c)
{
var isPrintable = char.IsWhiteSpace(c) ||
// exclude the Unicode character categories containing non-rendering,
// unknown, or incomplete characters.
char.GetUnicodeCategory(c) switch { UnicodeCategory.Control => false, UnicodeCategory.OtherNotAssigned => false, UnicodeCategory.Surrogate => false, _ => true };
return isPrintable ? $"'{c}'" : $"\\u{(int)c:X4}";
}
}
}
}
Loading

0 comments on commit 400d27b

Please sign in to comment.