Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC FS-1091] Extend Unsigned Integers to Carry Units of Measure #9978

Merged
merged 42 commits into from
Nov 16, 2020
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
e601c1b
Extend units support to unsigned integers
pblasucci Aug 19, 2020
3dd219a
Merge branch 'master' into feature/unsigned-ints-with-uom
pblasucci Aug 19, 2020
86140ac
more types in more places
pblasucci Aug 20, 2020
d84affa
Merge branch 'master' into feature/unsigned-ints-with-uom
pblasucci Aug 20, 2020
8a352a4
Merge branch 'main' into feature/unsigned-ints-with-uom
pblasucci Aug 20, 2020
bf04398
update error message; fixe failing tests
pblasucci Aug 21, 2020
ae13b6c
one more failing test fixed
pblasucci Aug 21, 2020
954168e
correct typo introduced in last commit
pblasucci Aug 21, 2020
a9b0624
finally learning how the QA suite checks expected failures
pblasucci Aug 21, 2020
75babf2
corrected error range info in failing test
pblasucci Aug 21, 2020
d8ee02d
better error message for unmeasurable types
pblasucci Aug 21, 2020
6f86411
more coverage of mixing uom with literals
pblasucci Aug 21, 2020
f66ff15
Merge branch 'main' into feature/unsigned-ints-with-uom
pblasucci Aug 23, 2020
9c7833f
Add measureables abbrevs; clean-up type checker
pblasucci Aug 24, 2020
4f24ecd
test to show concept of new measure abbrev
pblasucci Aug 24, 2020
751111e
fix failing build (typos)
pblasucci Aug 24, 2020
06d5daa
backout potentially bad test
pblasucci Aug 24, 2020
b2d9451
Handle decimal specially
pblasucci Aug 25, 2020
e42a9b2
Merge branch 'main' into feature/unsigned-ints-with-uom
pblasucci Aug 25, 2020
03b5f44
UoM for native ints
pblasucci Aug 26, 2020
245c075
Fix typo in surface area
pblasucci Aug 26, 2020
ff780c4
Merge branch 'main' into feature/unsigned-ints-with-uom
pblasucci Aug 26, 2020
5ddb8b8
Fix typo in eval test
pblasucci Aug 27, 2020
7e03603
Merge branch 'main' into feature/unsigned-ints-with-uom
pblasucci Aug 27, 2020
39f6a27
trying to satisfy tests
pblasucci Aug 27, 2020
37154bf
trying to address test failures
pblasucci Aug 27, 2020
d728909
still messing about with native ints
pblasucci Aug 27, 2020
c27a62a
more native int stubborness
pblasucci Aug 27, 2020
47e02a3
Temporarily elided difficult test
pblasucci Aug 27, 2020
4ec1928
trying to sort out werid Windows-only test errors
pblasucci Aug 27, 2020
399bf88
add UIntPtr to check for HIGH_PRECEDENCE_BRACK_APP
pblasucci Aug 29, 2020
3768e73
put unsigned,natve ints behind preview flag
pblasucci Aug 29, 2020
30f9a8e
Merge branch 'main' into feature/unsigned-ints-with-uom
pblasucci Aug 29, 2020
4ea5511
fix failing tests
pblasucci Aug 30, 2020
7bc5988
clean up some tests
pblasucci Aug 30, 2020
3e338a2
force the CI suite
pblasucci Aug 30, 2020
0b62498
Merge branch 'main' into feature/unsigned-ints-with-uom
pblasucci Sep 15, 2020
7548faf
fixed bad merge
pblasucci Sep 15, 2020
d2f019f
corrected signatures
pblasucci Sep 15, 2020
76a2c6c
better name for feature gate
pblasucci Oct 20, 2020
1588638
Merge branch 'main' into feature/unsigned-ints-with-uom
pblasucci Oct 24, 2020
123e880
Merge branch 'main' into feature/unsigned-ints-with-uom
pblasucci Nov 16, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/fsharp/FSComp.txt
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ parsSyntaxModuleSigEndDeprecated,"The syntax 'module ... : sig .. end' is not us
634,tcNonZeroConstantCannotHaveGenericUnit,"Non-zero constants cannot have generic units. For generic zero, write 0.0<_>."
635,tcSeqResultsUseYield,"In sequence expressions, results are generated using 'yield'"
tcUnexpectedBigRationalConstant,"Unexpected big rational constant"
636,tcInvalidTypeForUnitsOfMeasure,"Units-of-measure supported only on float, float32, decimal and signed integer types"
636,tcInvalidTypeForUnitsOfMeasure,"Units-of-measure are only supported on float, float32, decimal, and integer types."
tcUnexpectedConstUint16Array,"Unexpected Const_uint16array"
tcUnexpectedConstByteArray,"Unexpected Const_bytearray"
640,tcParameterRequiresName,"A parameter with attributes must also be given a name, e.g. '[<Attribute>] Name : Type'"
Expand Down Expand Up @@ -1226,6 +1226,7 @@ invalidFullNameForProvidedType,"invalid full name for provided type"
3086,tcCustomOperationMayNotBeUsedHere,"A custom operation may not be used in conjunction with 'use', 'try/with', 'try/finally', 'if/then/else' or 'match' operators within this computation expression"
3087,tcCustomOperationMayNotBeOverloaded,"The custom operation '%s' refers to a method which is overloaded. The implementations of custom operations may not be overloaded."
featureOverloadsForCustomOperations,"overloads for custom operations"
featureExpandedMeasurables,"more types support units of measure"
3090,tcIfThenElseMayNotBeUsedWithinQueries,"An if/then/else expression may not be used within queries. Consider using either an if/then expression, or use a sequence expression instead."
3091,ilxgenUnexpectedArgumentToMethodHandleOfDuringCodegen,"Invalid argument to 'methodhandleof' during codegen"
3092,etProvidedTypeReferenceMissingArgument,"A reference to a provided type was missing a value for the static parameter '%s'. You may need to recompile one or more referenced assemblies."
Expand Down
51 changes: 50 additions & 1 deletion src/fsharp/FSharp.Core/prim-types.fs
Original file line number Diff line number Diff line change
Expand Up @@ -369,11 +369,42 @@ namespace Microsoft.FSharp.Core
[<MeasureAnnotatedAbbreviation>] type sbyte<[<Measure>] 'Measure> = sbyte
[<MeasureAnnotatedAbbreviation>] type int16<[<Measure>] 'Measure> = int16
[<MeasureAnnotatedAbbreviation>] type int64<[<Measure>] 'Measure> = int64

[<Experimental(ExperimentalAttributeMessages.RequiresPreview)>]
[<MeasureAnnotatedAbbreviation>]
type nativeint<[<Measure>] 'Measure> = nativeint

[<Experimental(ExperimentalAttributeMessages.RequiresPreview)>]
[<MeasureAnnotatedAbbreviation>]
type uint<[<Measure>] 'Measure> = uint

[<Experimental(ExperimentalAttributeMessages.RequiresPreview)>]
[<MeasureAnnotatedAbbreviation>]
type byte<[<Measure>] 'Measure> = byte

[<Experimental(ExperimentalAttributeMessages.RequiresPreview)>]
[<MeasureAnnotatedAbbreviation>]
type uint16<[<Measure>] 'Measure> = uint16

[<Experimental(ExperimentalAttributeMessages.RequiresPreview)>]
[<MeasureAnnotatedAbbreviation>]
type uint64<[<Measure>] 'Measure> = uint64

[<Experimental(ExperimentalAttributeMessages.RequiresPreview)>]
[<MeasureAnnotatedAbbreviation>]
type unativeint<[<Measure>] 'Measure> = unativeint

[<Experimental(ExperimentalAttributeMessages.RequiresPreview)>] type double<[<Measure>] 'Measure> = float<'Measure>
[<Experimental(ExperimentalAttributeMessages.RequiresPreview)>] type single<[<Measure>] 'Measure> = float32<'Measure>
[<Experimental(ExperimentalAttributeMessages.RequiresPreview)>] type int8<[<Measure>] 'Measure> = sbyte<'Measure>
[<Experimental(ExperimentalAttributeMessages.RequiresPreview)>] type int32<[<Measure>] 'Measure> = int<'Measure>
[<Experimental(ExperimentalAttributeMessages.RequiresPreview)>] type uint8<[<Measure>] 'Measure> = byte<'Measure>
[<Experimental(ExperimentalAttributeMessages.RequiresPreview)>] type uint32<[<Measure>] 'Measure> = uint<'Measure>

/// <summary>Represents a managed pointer in F# code.</summary>
type byref<'T> = (# "!0&" #)

/// <summary>Represents a managed pointer in F# code.</summary>
/// <summary>Represents a managed pointer in F# code.</summary>
type byref<'T, 'Kind> = (# "!0&" #)

/// Represents the types of byrefs in F# 4.5+
Expand Down Expand Up @@ -2256,6 +2287,24 @@ namespace Microsoft.FSharp.Core
let inline Int16WithMeasure (f : int16) : int16<'Measure> = retype f
let inline SByteWithMeasure (f : sbyte) : sbyte<'Measure> = retype f
let inline Int64WithMeasure (f : int64) : int64<'Measure> = retype f

[<Experimental(ExperimentalAttributeMessages.RequiresPreview)>]
let inline IntPtrWithMeasure (f : nativeint) : nativeint<'Measure> = retype f

[<Experimental(ExperimentalAttributeMessages.RequiresPreview)>]
let inline UInt32WithMeasure (f : uint) : uint<'Measure> = retype f

[<Experimental(ExperimentalAttributeMessages.RequiresPreview)>]
let inline UInt16WithMeasure (f : uint16) : uint16<'Measure> = retype f

[<Experimental(ExperimentalAttributeMessages.RequiresPreview)>]
let inline UInt64WithMeasure (f : uint64) : uint64<'Measure> = retype f

[<Experimental(ExperimentalAttributeMessages.RequiresPreview)>]
let inline ByteWithMeasure (f : byte) : byte<'Measure> = retype f

[<Experimental(ExperimentalAttributeMessages.RequiresPreview)>]
let inline UIntPtrWithMeasure (f : unativeint) : unativeint<'Measure> = retype f

let inline formatError() = raise (new System.FormatException(SR.GetString(SR.badFormatString)))

Expand Down
172 changes: 167 additions & 5 deletions src/fsharp/FSharp.Core/prim-types.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -921,17 +921,17 @@ namespace Microsoft.FSharp.Core
member Path: string

[<MeasureAnnotatedAbbreviation>]
/// <summary>The type of floating point numbers, annotated with a unit of measure. The unit
/// of measure is erased in compiled code and when values of this type
/// <summary>The type of double-precision floating point numbers, annotated with a unit of measure.
/// The unit of measure is erased in compiled code and when values of this type
/// are analyzed using reflection. The type is representationally equivalent to
/// <see cref="T:System.Double"/>.</summary>
///
/// <category index="6">Basic Types with Units of Measure</category>
type float<[<Measure>] 'Measure> = float

[<MeasureAnnotatedAbbreviation>]
/// <summary>The type of floating point numbers, annotated with a unit of measure. The unit
/// of measure is erased in compiled code and when values of this type
/// <summary>The type of single-precision floating point numbers, annotated with a unit of measure.
/// The unit of measure is erased in compiled code and when values of this type
/// are analyzed using reflection. The type is representationally equivalent to
/// <see cref="T:System.Single"/>.
/// </summary>
Expand All @@ -956,7 +956,7 @@ namespace Microsoft.FSharp.Core
///
/// <category>Basic Types with Units of Measure</category>
type int<[<Measure>] 'Measure> = int

[<MeasureAnnotatedAbbreviation>]
/// <summary>The type of 8-bit signed integer numbers, annotated with a unit of measure. The unit
/// of measure is erased in compiled code and when values of this type
Expand Down Expand Up @@ -984,6 +984,120 @@ namespace Microsoft.FSharp.Core
/// <category>Basic Types with Units of Measure</category>
type int64<[<Measure>] 'Measure> = int64

[<Experimental("Experimental library feature, requires '--langversion:preview'")>]
[<MeasureAnnotatedAbbreviation>]
/// <summary>The type of machine-sized signed integer numbers, annotated with a unit of measure.
/// The unit of measure is erased in compiled code and when values of this type
/// are analyzed using reflection. The type is representationally equivalent to
/// <see cref="T:System.IntPtr"/>.</summary>
///
/// <category>Basic Types with Units of Measure</category>
type nativeint<[<Measure>] 'Measure> = nativeint

[<Experimental("Experimental library feature, requires '--langversion:preview'")>]
[<MeasureAnnotatedAbbreviation>]
/// <summary>The type of 32-bit unsigned integer numbers, annotated with a unit of measure.
/// The unit of measure is erased in compiled code and when values of this type
/// are analyzed using reflection. The type is representationally equivalent to
/// <see cref="T:System.UInt32"/>.</summary>
///
/// <category>Basic Types with Units of Measure</category>
type uint<[<Measure>] 'Measure> = uint

[<Experimental("Experimental library feature, requires '--langversion:preview'")>]
[<MeasureAnnotatedAbbreviation>]
/// <summary>The type of 8-bit unsigned integer numbers, annotated with a unit of measure.
/// The unit of measure is erased in compiled code and when values of this type
/// are analyzed using reflection. The type is representationally equivalent to
/// <see cref="T:System.Byte"/>.</summary>
///
/// <category>Basic Types with Units of Measure</category>
type byte<[<Measure>] 'Measure> = byte

[<Experimental("Experimental library feature, requires '--langversion:preview'")>]
[<MeasureAnnotatedAbbreviation>]
/// <summary>The type of 16-bit unsigned integer numbers, annotated with a unit of measure.
/// The unit of measure is erased in compiled code and when values of this type
/// are analyzed using reflection. The type is representationally equivalent to
/// <see cref="T:System.UInt16"/>.</summary>
///
/// <category>Basic Types with Units of Measure</category>
type uint16<[<Measure>] 'Measure> = uint16

[<Experimental("Experimental library feature, requires '--langversion:preview'")>]
[<MeasureAnnotatedAbbreviation>]
/// <summary>The type of 64-bit unsigned integer numbers, annotated with a unit of measure.
/// The unit of measure is erased in compiled code and when values of this type
/// are analyzed using reflection. The type is representationally equivalent to
/// <see cref="T:System.UInt64"/>.</summary>
///
/// <category>Basic Types with Units of Measure</category>
type uint64<[<Measure>] 'Measure> = uint64

[<Experimental("Experimental library feature, requires '--langversion:preview'")>]
[<MeasureAnnotatedAbbreviation>]
/// <summary>The type of machine-sized unsigned integer numbers, annotated with a unit of measure.
/// The unit of measure is erased in compiled code and when values of this type
/// are analyzed using reflection. The type is representationally equivalent to
/// <see cref="T:System.UIntPtr"/>.</summary>
///
/// <category>Basic Types with Units of Measure</category>
type unativeint<[<Measure>] 'Measure> = unativeint

[<Experimental("Experimental library feature, requires '--langversion:preview'")>]
/// <summary>The type of double-precision floating point numbers, annotated with a unit of measure.
/// The unit of measure is erased in compiled code and when values of this type
/// are analyzed using reflection. The type is representationally equivalent to
/// <see cref="T:System.Double"/>.</summary>
///
/// <category index="6">Basic Types with Units of Measure</category>
type double<[<Measure>] 'Measure> = float<'Measure>

[<Experimental("Experimental library feature, requires '--langversion:preview'")>]
/// <summary>The type of single-precision floating point numbers, annotated with a unit of measure.
/// The unit of measure is erased in compiled code and when values of this type
/// are analyzed using reflection. The type is representationally equivalent to
/// <see cref="T:System.Single"/>.</summary>
///
/// <category index="6">Basic Types with Units of Measure</category>
type single<[<Measure>] 'Measure> = float32<'Measure>

[<Experimental("Experimental library feature, requires '--langversion:preview'")>]
/// <summary>The type of 8-bit signed integer numbers, annotated with a unit of measure.
/// The unit of measure is erased in compiled code and when values of this type
/// are analyzed using reflection. The type is representationally equivalent to
/// <see cref="T:System.SByte"/>.</summary>
///
/// <category>Basic Types with Units of Measure</category>
type int8<[<Measure>] 'Measure> = sbyte<'Measure>

[<Experimental("Experimental library feature, requires '--langversion:preview'")>]
/// <summary>The type of 32-bit signed integer numbers, annotated with a unit of measure.
/// The unit of measure is erased in compiled code and when values of this type
/// are analyzed using reflection. The type is representationally equivalent to
/// <see cref="T:System.Int32"/>.</summary>
///
/// <category>Basic Types with Units of Measure</category>
type int32<[<Measure>] 'Measure> = int<'Measure>

[<Experimental("Experimental library feature, requires '--langversion:preview'")>]
/// <summary>The type of 8-bit unsigned integer numbers, annotated with a unit of measure.
/// The unit of measure is erased in compiled code and when values of this type
/// are analyzed using reflection. The type is representationally equivalent to
/// <see cref="T:System.Byte"/>.</summary>
///
/// <category>Basic Types with Units of Measure</category>
type uint8<[<Measure>] 'Measure> = byte<'Measure>

[<Experimental("Experimental library feature, requires '--langversion:preview'")>]
/// <summary>The type of 32-bit unsigned integer numbers, annotated with a unit of measure.
/// The unit of measure is erased in compiled code and when values of this type
/// are analyzed using reflection. The type is representationally equivalent to
/// <see cref="T:System.UInt32"/>.</summary>
///
/// <category>Basic Types with Units of Measure</category>
type uint32<[<Measure>] 'Measure> = uint<'Measure>

/// <summary>Represents a managed pointer in F# code.</summary>
#if BUILDING_WITH_LKG || BUILD_FROM_SOURCE
[<CompilerMessage("This construct is for use in the FSharp.Core library and should not be used directly", 1204, IsHidden=true)>]
Expand Down Expand Up @@ -1278,6 +1392,54 @@ namespace Microsoft.FSharp.Core
/// <returns>The sbyte with units-of-measure.</returns>
val inline SByteWithMeasure : input: sbyte -> sbyte<'Measure>

[<Experimental("Experimental library feature, requires '--langversion:preview'")>]
/// <summary>Creates a nativeint value with units-of-measure</summary>
///
/// <param name="input">The input nativeint.</param>
///
/// <returns>The nativeint with units-of-measure.</returns>
val inline IntPtrWithMeasure : input: nativeint -> nativeint<'Measure>

[<Experimental("Experimental library feature, requires '--langversion:preview'")>]
/// <summary>Creates a uint value with units-of-measure</summary>
///
/// <param name="input">The input uint.</param>
///
/// <returns>The uint with units-of-measure.</returns>
val inline UInt32WithMeasure : input: uint -> uint<'Measure>

[<Experimental("Experimental library feature, requires '--langversion:preview'")>]
/// <summary>Creates a uint64 value with units-of-measure</summary>
///
/// <param name="input">The input uint64.</param>
///
/// <returns>The uint64 with units-of-measure.</returns>
val inline UInt64WithMeasure : input: uint64 -> uint64<'Measure>

[<Experimental("Experimental library feature, requires '--langversion:preview'")>]
/// <summary>Creates a uint16 value with units-of-measure</summary>
///
/// <param name="input">The input uint16.</param>
///
/// <returns>The uint16 with units-of-measure.</returns>
val inline UInt16WithMeasure : input: uint16 -> uint16<'Measure>

[<Experimental("Experimental library feature, requires '--langversion:preview'")>]
/// <summary>Creates a byte value with units-of-measure</summary>
///
/// <param name="input">The input byte.</param>
///
/// <returns>The byte with units-of-measure.</returns>
val inline ByteWithMeasure : input: byte -> byte<'Measure>

[<Experimental("Experimental library feature, requires '--langversion:preview'")>]
/// <summary>Creates a unativeint value with units-of-measure</summary>
///
/// <param name="input">The input unativeint.</param>
///
/// <returns>The unativeint with units-of-measure.</returns>
val inline UIntPtrWithMeasure : input: unativeint -> unativeint<'Measure>

/// <summary>Parse an int32 according to the rules used by the overloaded 'int32' conversion operator when applied to strings</summary>
///
/// <param name="s">The input string.</param>
Expand Down
3 changes: 3 additions & 0 deletions src/fsharp/LanguageFeatures.fs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type LanguageFeature =
| InterfacesWithMultipleGenericInstantiation
| StringInterpolation
| OverloadsForCustomOperations
| ExpandedMeasurables

/// LanguageVersion management
type LanguageVersion (specifiedVersionAsString) =
Expand Down Expand Up @@ -75,6 +76,7 @@ type LanguageVersion (specifiedVersionAsString) =
LanguageFeature.NameOf, previewVersion
LanguageFeature.StringInterpolation, previewVersion
LanguageFeature.OverloadsForCustomOperations, previewVersion
LanguageFeature.ExpandedMeasurables, previewVersion
]

let specified =
Expand Down Expand Up @@ -147,6 +149,7 @@ type LanguageVersion (specifiedVersionAsString) =
| LanguageFeature.InterfacesWithMultipleGenericInstantiation -> FSComp.SR.featureInterfacesWithMultipleGenericInstantiation()
| LanguageFeature.StringInterpolation -> FSComp.SR.featureStringInterpolation()
| LanguageFeature.OverloadsForCustomOperations -> FSComp.SR.featureOverloadsForCustomOperations()
| LanguageFeature.ExpandedMeasurables -> FSComp.SR.featureExpandedMeasurables()

/// Get a version string associated with the given feature.
member _.GetFeatureVersionString feature =
Expand Down
1 change: 1 addition & 0 deletions src/fsharp/LanguageFeatures.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type LanguageFeature =
| InterfacesWithMultipleGenericInstantiation
| StringInterpolation
| OverloadsForCustomOperations
| ExpandedMeasurables

/// LanguageVersion management
type LanguageVersion =
Expand Down
2 changes: 1 addition & 1 deletion src/fsharp/LexFilter.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2229,7 +2229,7 @@ type LexFilterImpl (lightStatus: LightSyntaxStatus, compilingFsLib, lexer, lexbu
true

// Insert HIGH_PRECEDENCE_TYAPP if needed
| (DELEGATE | IDENT _ | IEEE64 _ | IEEE32 _ | DECIMAL _ | INT8 _ | INT16 _ | INT32 _ | INT64 _ | NATIVEINT _ | UINT8 _ | UINT16 _ | UINT32 _ | UINT64 _ | BIGNUM _) when peekAdjacentTypars false tokenTup ->
| (DELEGATE | IDENT _ | IEEE64 _ | IEEE32 _ | DECIMAL _ | INT8 _ | INT16 _ | INT32 _ | INT64 _ | NATIVEINT _ | UINT8 _ | UINT16 _ | UINT32 _ | UINT64 _ | UNATIVEINT _ | BIGNUM _) when peekAdjacentTypars false tokenTup ->
let lessTokenTup = popNextTokenTup()
delayToken (pool.UseLocation(lessTokenTup, match lessTokenTup.Token with LESS _ -> LESS true | _ -> failwith "unreachable"))

Expand Down
Loading