diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index 7929ef775817..0faef69f9dd5 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -2360,14 +2360,6 @@ namespace Microsoft.FSharp.Core then p <- p + 1; -1L else 1L - let parseOctalUInt64 (s:string) p l = - let rec parse n acc = if n < l then parse (n+1) (acc *.. 8UL +.. (let c = s.Chars(n) in if c >=... '0' && c <=... '7' then Convert.ToUInt64(c) -.. Convert.ToUInt64('0') else formatError())) else acc in - parse p 0UL - - let parseBinaryUInt64 (s:string) p l = - let rec parse n acc = if n < l then parse (n+1) (acc *.. 2UL +.. (match s.Chars(n) with '0' -> 0UL | '1' -> 1UL | _ -> formatError())) else acc in - parse p 0UL - let inline removeUnderscores (s:string) = match s with | null -> null @@ -2383,8 +2375,8 @@ namespace Microsoft.FSharp.Core if p >= l then formatError() else match specifier with | 'x' -> UInt32.Parse( s.Substring(p), NumberStyles.AllowHexSpecifier,CultureInfo.InvariantCulture) - | 'b' -> Convert.ToUInt32(parseBinaryUInt64 s p l) - | 'o' -> Convert.ToUInt32(parseOctalUInt64 s p l) + | 'b' -> Convert.ToUInt32(s.Substring(p), 2) + | 'o' -> Convert.ToUInt32(s.Substring(p), 8) | _ -> UInt32.Parse(s.Substring(p), NumberStyles.Integer, CultureInfo.InvariantCulture) in let inline int32OfUInt32 (x:uint32) = (# "" x : int32 #) @@ -2401,8 +2393,8 @@ namespace Microsoft.FSharp.Core if p >= l then formatError() else match Char.ToLowerInvariant(specifier) with | 'x' -> sign * (int32OfUInt32 (Convert.ToUInt32(UInt64.Parse(s.Substring(p), NumberStyles.AllowHexSpecifier,CultureInfo.InvariantCulture)))) - | 'b' -> sign * (int32OfUInt32 (Convert.ToUInt32(parseBinaryUInt64 s p l))) - | 'o' -> sign * (int32OfUInt32 (Convert.ToUInt32(parseOctalUInt64 s p l))) + | 'b' -> sign * (int32OfUInt32 (Convert.ToUInt32(s.Substring(p), 2))) + | 'o' -> sign * (int32OfUInt32 (Convert.ToUInt32(s.Substring(p), 8))) | _ -> Int32.Parse(s, NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture) let ParseInt64 (s:string) = @@ -2416,8 +2408,8 @@ namespace Microsoft.FSharp.Core if p >= l then formatError() else match Char.ToLowerInvariant(specifier) with | 'x' -> sign *. Int64.Parse(s.Substring(p), NumberStyles.AllowHexSpecifier,CultureInfo.InvariantCulture) - | 'b' -> sign *. (int64OfUInt64 (parseBinaryUInt64 s p l)) - | 'o' -> sign *. (int64OfUInt64 (parseOctalUInt64 s p l)) + | 'b' -> sign *. (int64OfUInt64 (Convert.ToUInt64(s.Substring(p), 2))) + | 'o' -> sign *. (int64OfUInt64 (Convert.ToUInt64(s.Substring(p), 8))) | _ -> Int64.Parse(s, NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture) let ParseUInt64 (s:string) : uint64 = @@ -2430,8 +2422,8 @@ namespace Microsoft.FSharp.Core if p >= l then formatError() else match specifier with | 'x' -> UInt64.Parse(s.Substring(p), NumberStyles.AllowHexSpecifier,CultureInfo.InvariantCulture) - | 'b' -> parseBinaryUInt64 s p l - | 'o' -> parseOctalUInt64 s p l + | 'b' -> Convert.ToUInt64(s.Substring(p), 2) + | 'o' -> Convert.ToUInt64(s.Substring(p), 8) | _ -> UInt64.Parse(s.Substring(p), NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture) diff --git a/src/fsharp/lex.fsl b/src/fsharp/lex.fsl index 0af96d71c9a6..b118a9dac9df 100644 --- a/src/fsharp/lex.fsl +++ b/src/fsharp/lex.fsl @@ -66,14 +66,6 @@ let get0OXB (s:string) (p:byref) l = let formatError() = raise (new System.FormatException(SR.GetString("bad format string"))) -let parseBinaryUInt64 (s:string) p l = - let rec parse n acc = if n < l then parse (n+1) (acc * 2UL + (match s.[n] with '0' -> 0UL | '1' -> 1UL | _ -> formatError())) else acc - parse p 0UL - -let parseOctalUInt64 (s:string) p l = - let rec parse n acc = if n < l then parse (n+1) (acc * 8UL + (let c = s.[n] in if c >= '0' && c <= '7' then Convert.ToUInt64 c - Convert.ToUInt64 '0' else formatError())) else acc - parse p 0UL - let removeUnderscores (s:string) = match s with | null -> null @@ -91,8 +83,8 @@ let parseInt32 (s:string) = match Char.ToLower(specifier,CultureInfo.InvariantCulture) with #endif | 'x' -> sign * (int32 (Convert.ToUInt32(UInt64.Parse(s.Substring(p), NumberStyles.AllowHexSpecifier,CultureInfo.InvariantCulture)))) - | 'b' -> sign * (int32 (Convert.ToUInt32(parseBinaryUInt64 s p l))) - | 'o' -> sign * (int32 (Convert.ToUInt32(parseOctalUInt64 s p l))) + | 'b' -> sign * (int32 (Convert.ToUInt32(s.Substring(p), 2))) + | 'o' -> sign * (int32 (Convert.ToUInt32(s.Substring(p), 8))) | _ -> Int32.Parse(s, NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture) let lexemeTrimRightToInt32 args lexbuf n = diff --git a/tests/fsharpqa/Source/Conformance/LexicalAnalysis/NumericLiterals/E_MaxLiterals04.fs b/tests/fsharpqa/Source/Conformance/LexicalAnalysis/NumericLiterals/E_MaxLiterals04.fs new file mode 100644 index 000000000000..c68477767c4b --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/LexicalAnalysis/NumericLiterals/E_MaxLiterals04.fs @@ -0,0 +1,28 @@ +// #Regression #Conformance #LexicalAnalysis #Constants + + +// Verify compile error for signed literals which are MaxSize + 1, MaxSize - 1 +// All of these should cause compiler errors + +//This number is outside the allowable range for 8-bit signed integers +//This number is outside the allowable range for 16-bit signed integers +//This number is outside the allowable range for 32-bit signed integers +//This number is outside the allowable range for 64-bit signed integers + +//This number is outside the allowable range for 8-bit signed integers +//This number is outside the allowable range for 16-bit signed integers +//This number is outside the allowable range for 32-bit signed integers +//This number is outside the allowable range for 64-bit signed integers + + +let minByteBin = -0b10000001y +let maxByteBin = 0b10000000y + +let minInt16Bin = -0b1000_0000_0000_0001s +let maxInt16Bin = 0b1000_0000_0000_0000s + +let minInt32Bin = -0b1000_0000_0000_0000_0000_0000_0000_0001 +let maxInt32Bin = 0b1000_0000_0000_0000_0000_0000_0000_0000 + +let minInt64Bin = -0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0001L +let maxInt64Bin = 0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000L diff --git a/tests/fsharpqa/Source/Conformance/LexicalAnalysis/NumericLiterals/E_MaxLiterals05.fs b/tests/fsharpqa/Source/Conformance/LexicalAnalysis/NumericLiterals/E_MaxLiterals05.fs new file mode 100644 index 000000000000..d7ecb4496641 --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/LexicalAnalysis/NumericLiterals/E_MaxLiterals05.fs @@ -0,0 +1,28 @@ +// #Regression #Conformance #LexicalAnalysis #Constants + + +// Verify compile error for signed literals which are MaxSize + 1, MaxSize - 1 +// All of these should cause compiler errors + +//This number is outside the allowable range for 8-bit signed integers +//This number is outside the allowable range for 16-bit signed integers +//This number is outside the allowable range for 32-bit signed integers +//This number is outside the allowable range for 64-bit signed integers + +//This number is outside the allowable range for 8-bit signed integers +//This number is outside the allowable range for 16-bit signed integers +//This number is outside the allowable range for 32-bit signed integers +//This number is outside the allowable range for 64-bit signed integers + + +let minByteHex = -0x81y +let maxByteHex = 0x80y + +let minInt16Hex = -0x8001s +let maxInt16Hex = 0x8000s + +let minInt32Hex = -0x8000_0001 +let maxInt32Hex = 0x8000_0000 + +let minInt64Hex = -0x8000_0000_0000_0001L +let maxInt64Hex = 0x8000_0000_0000_0000L diff --git a/tests/fsharpqa/Source/Conformance/LexicalAnalysis/NumericLiterals/E_MaxLiterals06.fs b/tests/fsharpqa/Source/Conformance/LexicalAnalysis/NumericLiterals/E_MaxLiterals06.fs new file mode 100644 index 000000000000..1c9c2946155d --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/LexicalAnalysis/NumericLiterals/E_MaxLiterals06.fs @@ -0,0 +1,28 @@ +// #Regression #Conformance #LexicalAnalysis #Constants + + +// Verify compile error for signed literals which are MaxSize + 1, MaxSize - 1 +// All of these should cause compiler errors + +//This number is outside the allowable range for 8-bit signed integers +//This number is outside the allowable range for 16-bit signed integers +//This number is outside the allowable range for 32-bit signed integers +//This number is outside the allowable range for 64-bit signed integers + +//This number is outside the allowable range for 8-bit signed integers +//This number is outside the allowable range for 16-bit signed integers +//This number is outside the allowable range for 32-bit signed integers +//This number is outside the allowable range for 64-bit signed integers + + +let minByteOct = -0o201y +let maxByteOct = 0o200y + +let minInt16Oct = -0o100_001s +let maxInt16Oct = 0o100_000s + +let minInt32Oct = -0o20_000_000_001 +let maxInt32Oct = 0o20_000_000_000 + +let minInt64Oct = -0o1_000_000_000_000_000_000_001L +let maxInt64Oct = 0o1_000_000_000_000_000_000_000L diff --git a/tests/fsharpqa/Source/Conformance/LexicalAnalysis/NumericLiterals/env.lst b/tests/fsharpqa/Source/Conformance/LexicalAnalysis/NumericLiterals/env.lst index 47fdc9891d62..163bbafe0186 100644 --- a/tests/fsharpqa/Source/Conformance/LexicalAnalysis/NumericLiterals/env.lst +++ b/tests/fsharpqa/Source/Conformance/LexicalAnalysis/NumericLiterals/env.lst @@ -23,6 +23,9 @@ SOURCE=E_MaxLiterals01.fs # E_MaxLiterals01.fs SOURCE=E_MaxLiterals02.fs # E_MaxLiterals02.fs SOURCE=E_MaxLiterals03.fs # E_MaxLiterals03.fs + SOURCE=E_MaxLiterals04.fs # E_MaxLiterals04.fs + SOURCE=E_MaxLiterals05.fs # E_MaxLiterals05.fs + SOURCE=E_MaxLiterals06.fs # E_MaxLiterals06.fs SOURCE=BigNums01.fs # BigNums01.fs