public static void TestThatAllPossibleOperandTypesAreSupported(Dictionary <DataType, HashSet <DataType> > supportedOperandTypes, Func <InternalDataTypeBase, InternalDataTypeBase, InternalDataTypeBase> operation, string operationDescription) { var allTypePairs = (new[] { EnumExtensions.GetEnumCollection <DataType>(), EnumExtensions.GetEnumCollection <DataType>() }) .CartesianProduct() .Select(r => new DataTypePair <DataType>(r.First(), r.Last())) .Distinct(); var supportedTypes = allTypePairs .Where(p => supportedOperandTypes.ContainsKey(p.Left) && supportedOperandTypes[p.Left].Contains(p.Right)) .ToList(); foreach (var pair in allTypePairs) { var valuePair = new DataTypeValuePair <DataType>(MakeDataType(pair.Left), MakeDataType(pair.Right)); var act = new Action(() => _ = operation(valuePair.Left as InternalDataTypeBase, valuePair.Right as InternalDataTypeBase)); if (supportedTypes.Contains(pair)) { act.Should().NotThrow($"a {pair.Left} and {pair.Right} should be able to be {operationDescription}"); } else { act.Should().Throw <Exception>($"a {pair.Left} and {pair.Right} should not be able to be {operationDescription}"); } } }
// List of operand types, grouped by operations, that are supported as input operand types static Dictionary <OperatorType, Dictionary <DataType, HashSet <DataType> > > BuildOperandTypeMaps(bool inputTypes = false) { var dict = new Dictionary <OperatorType, Dictionary <DataType, HashSet <DataType> > >(); foreach (var opType in EnumExtensions.GetEnumCollection <OperatorType>()) { if (!dict.ContainsKey(opType)) { dict.Add(opType, new Dictionary <DataType, HashSet <DataType> >()); } var subDict = dict[opType]; var opTypesByOperator = DataMapper.OperandTypeCastMap[opType] .Where(kv => kv.Value.OperationSupported) .Select(kv => new Tuple <OperatorType, DataType, DataType>( opType, inputTypes ? kv.Key.Left : kv.Value.Left, inputTypes ? kv.Key.Right : kv.Value.Right)) .Distinct(); foreach (var entry in opTypesByOperator) { if (!subDict.ContainsKey(entry.Item2)) { subDict.Add(entry.Item2, new HashSet <DataType>()); } if (!subDict[entry.Item2].Contains(entry.Item3)) { subDict[entry.Item2].Add(entry.Item3); } } } return(dict); }
public void MakeDataTypeCoversAllDataTypes() { foreach (var dataType in EnumExtensions.GetEnumCollection <DataType>()) { Action act = () => TestCommon.MakeDataType(dataType); act.Should().NotThrow <TestOperationException>(); } }
public void MakeLiteralTokenCoversAllLiteralTokenTypes() { foreach (var tokenType in EnumExtensions.GetEnumCollection <LiteralTokenType>()) { Action act = () => TestCommon.MakeLiteralToken(tokenType); act.Should().NotThrow <TestOperationException>(); } }
public void AllUnaryOperatorsMapped() { var unaryDataTypes = EnumExtensions.GetEnumCollection <OperatorType>(e => e.IsUnaryOperator()) .OrderBy(e => e) .ToArray(); var allMappings = DataMapper.OperandTypeCastMap .Select(map => map.Key) .OrderBy(e => e) .ToArray(); unaryDataTypes.Should().BeSubsetOf(allMappings); }
public static LimitedIntegerType CreateLimitedIntegerType(BigInteger value, IConfiguration configuration) { var isSigned = value < 0; var bitWidth = EnumExtensions .GetEnumCollection <IntegerBitWidth>() .FirstOrDefault(bw => isSigned ? MinAndMaxMap.Instance[new BitWidthAndSignPair(bw, isSigned)].Min <= value : MinAndMaxMap.Instance[new BitWidthAndSignPair(bw, isSigned)].Max >= value); if (bitWidth == 0) { throw new TypeConversionException($"{value} is out of range of a {nameof(LimitedIntegerType)}."); } return(new LimitedIntegerType(value, new BitWidthAndSignPair(bitWidth, isSigned), configuration)); }
public void AllBitWidthsHaveAMinAndMax() { foreach (var signAndBitwidth in EnumExtensions.GetEnumCollection <IntegerBitWidth>() .SelectMany(bw => new[] { false, true }.Select(s => new BitWidthAndSignPair(bw, s)))) { var isSigned = signAndBitwidth.IsSigned; var bitWidth = signAndBitwidth.BitWidth; var expectedMin = isSigned ? BigInteger.Pow(new BigInteger(2), (int)bitWidth - 1) * -1 : 0; var expectedMax = isSigned ? BigInteger.Pow(new BigInteger(2), (int)bitWidth - 1) - 1 : BigInteger.Pow(new BigInteger(2), (int)bitWidth) - 1; MinAndMaxMap.Instance.ContainsKey(signAndBitwidth).Should().BeTrue(); var minMax = MinAndMaxMap.Instance[signAndBitwidth]; minMax.Min.Should().Be(expectedMin, $"a {(isSigned ? "signed" : "unsigned")} {(int)bitWidth}-bit integer should have a minimum of {expectedMin}"); minMax.Max.Should().Be(expectedMax, $"a {(isSigned ? "signed" : "unsigned")} {(int)bitWidth}-bit integer should have a maximum of {expectedMax}"); } }
public void AllUnaryOperatorsMappingsShouldHaveTheSameTypeLeftAndRight() { var unaryDataTypes = EnumExtensions.GetEnumCollection <OperatorType>(e => e.IsUnaryOperator()).ToHashSet(); var unaryMappings = DataMapper.OperandTypeCastMap .Where(map => unaryDataTypes.Contains(map.Key)) .OrderBy(map => map.Key) .ToDictionary(kv => kv.Key, kv => kv.Value); foreach (var opType in unaryMappings.Keys) { var mapping = unaryMappings[opType]; foreach (var dataMapping in mapping) { dataMapping.Key.Left.Should().Be(dataMapping.Key.Right, $"unary mappings should be the same for data type {dataMapping.Key.Left} for operator {opType}."); dataMapping.Value.Left.Should().Be(dataMapping.Value.Right, $"unary mappings should be the same for data type {dataMapping.Value.Left} for operator {opType}."); } } }