|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
namespace Microsoft.CodeAnalysis.CSharp
{
using static BinaryOperatorKind;
internal static partial class ValueSetFactory
{
private sealed class BoolValueSet : IValueSet<bool>
{
private readonly bool _hasFalse, _hasTrue;
internal static readonly BoolValueSet AllValues = new BoolValueSet(hasFalse: true, hasTrue: true);
internal static readonly BoolValueSet None = new BoolValueSet(hasFalse: false, hasTrue: false);
internal static readonly BoolValueSet OnlyTrue = new BoolValueSet(hasFalse: false, hasTrue: true);
internal static readonly BoolValueSet OnlyFalse = new BoolValueSet(hasFalse: true, hasTrue: false);
private BoolValueSet(bool hasFalse, bool hasTrue) => (_hasFalse, _hasTrue) = (hasFalse, hasTrue);
public static BoolValueSet Create(bool hasFalse, bool hasTrue)
{
switch (hasFalse, hasTrue)
{
case (false, false):
return None;
case (false, true):
return OnlyTrue;
case (true, false):
return OnlyFalse;
case (true, true):
return AllValues;
}
}
bool IValueSet.IsEmpty => !_hasFalse && !_hasTrue;
ConstantValue IValueSet.Sample => ConstantValue.Create(_hasTrue ? true : _hasFalse ? false : throw new ArgumentException());
public bool Any(BinaryOperatorKind relation, bool value)
{
switch (relation, value)
{
case (Equal, true):
return _hasTrue;
case (Equal, false):
return _hasFalse;
default:
return true;
}
}
bool IValueSet.Any(BinaryOperatorKind relation, ConstantValue value) => value.IsBad || Any(relation, value.BooleanValue);
public bool All(BinaryOperatorKind relation, bool value)
{
switch (relation, value)
{
case (Equal, true):
return !_hasFalse;
case (Equal, false):
return !_hasTrue;
default:
return true;
}
}
bool IValueSet.All(BinaryOperatorKind relation, ConstantValue value) => !value.IsBad && All(relation, value.BooleanValue);
public IValueSet<bool> Complement() => Create(!_hasFalse, !_hasTrue);
IValueSet IValueSet.Complement() => this.Complement();
public IValueSet<bool> Intersect(IValueSet<bool> other)
{
if (this == other)
return this;
BoolValueSet o = (BoolValueSet)other;
return Create(hasFalse: this._hasFalse & o._hasFalse, hasTrue: this._hasTrue & o._hasTrue);
}
public IValueSet Intersect(IValueSet other) => this.Intersect((IValueSet<bool>)other);
public IValueSet<bool> Union(IValueSet<bool> other)
{
if (this == other)
return this;
BoolValueSet o = (BoolValueSet)other;
return Create(hasFalse: this._hasFalse | o._hasFalse, hasTrue: this._hasTrue | o._hasTrue);
}
IValueSet IValueSet.Union(IValueSet other) => this.Union((IValueSet<bool>)other);
// Since we cache all distinct boolean value sets, we can use reference equality.
public override bool Equals(object? obj) => this == obj;
public override int GetHashCode() => System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(this);
public override string ToString() => (_hasFalse, _hasTrue) switch
{
(false, false) => "{}",
(true, false) => "{false}",
(false, true) => "{true}",
(true, true) => "{false,true}",
};
}
}
}
|