Skip to content
This repository has been archived by the owner on Dec 23, 2024. It is now read-only.

Commit

Permalink
Extend Unsigned Integers to Carry Units of Measure (dotnet#9978)
Browse files Browse the repository at this point in the history
  • Loading branch information
pblasucci authored and nosami committed Feb 22, 2021
1 parent 7fed47b commit 56ac8b8
Show file tree
Hide file tree
Showing 29 changed files with 454 additions and 93 deletions.
27 changes: 19 additions & 8 deletions src/fsharp/CheckExpressions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -774,9 +774,15 @@ let TcConst cenv ty m env c =
| _ -> mkAppTy tcr [TType_measure Measure.One]
unif measureTy

let expandedMeasurablesEnabled =
cenv.g.langVersion.SupportsFeature LanguageFeature.ExpandedMeasurables

match c with
| SynConst.Unit -> unif cenv.g.unit_ty; Const.Unit
| SynConst.Bool i -> unif cenv.g.bool_ty; Const.Bool i
| SynConst.Single f -> unif cenv.g.float32_ty; Const.Single f
| SynConst.Double f -> unif cenv.g.float_ty; Const.Double f
| SynConst.Decimal f -> unif (mkAppTy cenv.g.decimal_tcr []); Const.Decimal f
| SynConst.SByte i -> unif cenv.g.sbyte_ty; Const.SByte i
| SynConst.Int16 i -> unif cenv.g.int16_ty; Const.Int16 i
| SynConst.Int32 i -> unif cenv.g.int_ty; Const.Int32 i
Expand All @@ -787,18 +793,23 @@ let TcConst cenv ty m env c =
| SynConst.UInt32 i -> unif cenv.g.uint32_ty; Const.UInt32 i
| SynConst.UInt64 i -> unif cenv.g.uint64_ty; Const.UInt64 i
| SynConst.UIntPtr i -> unif cenv.g.unativeint_ty; Const.UIntPtr i
| SynConst.Measure(SynConst.Single f, _) | SynConst.Single f -> unifyMeasureArg (f=0.0f) cenv.g.pfloat32_tcr c; Const.Single f
| SynConst.Measure(SynConst.Double f, _) | SynConst.Double f -> unifyMeasureArg (f=0.0) cenv.g.pfloat_tcr c; Const.Double f
| SynConst.Measure(SynConst.Decimal s, _) | SynConst.Decimal s -> unifyMeasureArg false cenv.g.pdecimal_tcr c; Const.Decimal s
| SynConst.Measure(SynConst.SByte i, _) | SynConst.SByte i -> unifyMeasureArg (i=0y) cenv.g.pint8_tcr c; Const.SByte i
| SynConst.Measure(SynConst.Int16 i, _) | SynConst.Int16 i -> unifyMeasureArg (i=0s) cenv.g.pint16_tcr c; Const.Int16 i
| SynConst.Measure(SynConst.Int32 i, _) | SynConst.Int32 i -> unifyMeasureArg (i=0) cenv.g.pint_tcr c; Const.Int32 i
| SynConst.Measure(SynConst.Int64 i, _) | SynConst.Int64 i -> unifyMeasureArg (i=0L) cenv.g.pint64_tcr c; Const.Int64 i
| SynConst.Measure(SynConst.Single f, _) -> unifyMeasureArg (f=0.0f) cenv.g.pfloat32_tcr c; Const.Single f
| SynConst.Measure(SynConst.Double f, _) -> unifyMeasureArg (f=0.0) cenv.g.pfloat_tcr c; Const.Double f
| SynConst.Measure(SynConst.Decimal f, _) -> unifyMeasureArg false cenv.g.pdecimal_tcr c; Const.Decimal f
| SynConst.Measure(SynConst.SByte i, _) -> unifyMeasureArg (i=0y) cenv.g.pint8_tcr c; Const.SByte i
| SynConst.Measure(SynConst.Int16 i, _) -> unifyMeasureArg (i=0s) cenv.g.pint16_tcr c; Const.Int16 i
| SynConst.Measure(SynConst.Int32 i, _) -> unifyMeasureArg (i=0) cenv.g.pint_tcr c; Const.Int32 i
| SynConst.Measure(SynConst.Int64 i, _) -> unifyMeasureArg (i=0L) cenv.g.pint64_tcr c; Const.Int64 i
| SynConst.Measure(SynConst.IntPtr i, _) when expandedMeasurablesEnabled -> unifyMeasureArg (i=0L) cenv.g.pnativeint_tcr c; Const.IntPtr i
| SynConst.Measure(SynConst.Byte i, _) when expandedMeasurablesEnabled -> unifyMeasureArg (i=0uy) cenv.g.puint8_tcr c; Const.Byte i
| SynConst.Measure(SynConst.UInt16 i, _) when expandedMeasurablesEnabled -> unifyMeasureArg (i=0us) cenv.g.puint16_tcr c; Const.UInt16 i
| SynConst.Measure(SynConst.UInt32 i, _) when expandedMeasurablesEnabled -> unifyMeasureArg (i=0u) cenv.g.puint_tcr c; Const.UInt32 i
| SynConst.Measure(SynConst.UInt64 i, _) when expandedMeasurablesEnabled -> unifyMeasureArg (i=0UL) cenv.g.puint64_tcr c; Const.UInt64 i
| SynConst.Measure(SynConst.UIntPtr i, _) when expandedMeasurablesEnabled -> unifyMeasureArg (i=0UL) cenv.g.punativeint_tcr c; Const.UIntPtr i
| SynConst.Char c -> unif cenv.g.char_ty; Const.Char c
| SynConst.String (s, _) -> unif cenv.g.string_ty; Const.String s
| SynConst.UserNum _ -> error (InternalError(FSComp.SR.tcUnexpectedBigRationalConstant(), m))
| SynConst.Measure _ -> error (Error(FSComp.SR.tcInvalidTypeForUnitsOfMeasure(), m))

| SynConst.UInt16s _ -> error (InternalError(FSComp.SR.tcUnexpectedConstUint16Array(), m))
| SynConst.Bytes _ -> error (InternalError(FSComp.SR.tcUnexpectedConstByteArray(), m))

Expand Down
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 @@ -1227,6 +1227,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
Loading

0 comments on commit 56ac8b8

Please sign in to comment.