low/high for float ranges (#11177)

This commit is contained in:
Oscar Nihlgård 2019-05-06 21:19:40 +02:00 • committed by Andreas Rumpf
commit 4c6fc173b7
4 changed files with 27 additions and 7 deletions

View file

@ -316,7 +316,7 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
n.typ = getSysType(c.graph, n.info, tyInt) n.typ = getSysType(c.graph, n.info, tyInt)
of tyArray: of tyArray:
n.typ = typ.sons[0] # indextype n.typ = typ.sons[0] # indextype
of tyInt..tyInt64, tyChar, tyBool, tyEnum, tyUInt8, tyUInt16, tyUInt32: of tyInt..tyInt64, tyChar, tyBool, tyEnum, tyUInt8, tyUInt16, tyUInt32, tyFloat..tyFloat64:
# do not skip the range! # do not skip the range!
n.typ = n.sons[1].typ.skipTypes(abstractVar) n.typ = n.sons[1].typ.skipTypes(abstractVar)
of tyGenericParam: of tyGenericParam:

View file

@ -617,11 +617,17 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
# If it has no sideEffect, it should be evaluated. But not here. # If it has no sideEffect, it should be evaluated. But not here.
return return
of mLow: of mLow:
result = newIntNodeT(firstOrd(g.config, n.sons[1].typ), n, g) if skipTypes(n.sons[1].typ, abstractVarRange).kind in tyFloat..tyFloat64:
result = newFloatNodeT(firstFloat(n.sons[1].typ), n, g)
else:
result = newIntNodeT(firstOrd(g.config, n.sons[1].typ), n, g)
of mHigh: of mHigh:
if skipTypes(n.sons[1].typ, abstractVar+{tyUserTypeClassInst}).kind notin if skipTypes(n.sons[1].typ, abstractVar+{tyUserTypeClassInst}).kind notin
{tySequence, tyString, tyCString, tyOpenArray, tyVarargs}: {tySequence, tyString, tyCString, tyOpenArray, tyVarargs}:
result = newIntNodeT(lastOrd(g.config, skipTypes(n[1].typ, abstractVar)), n, g) if skipTypes(n.sons[1].typ, abstractVarRange).kind in tyFloat..tyFloat64:
result = newFloatNodeT(lastFloat(n.sons[1].typ), n, g)
else:
result = newIntNodeT(lastOrd(g.config, skipTypes(n[1].typ, abstractVar)), n, g)
else: else:
var a = getArrayConstr(m, n.sons[1], g) var a = getArrayConstr(m, n.sons[1], g)
if a.kind == nkBracket: if a.kind == nkBracket:

View file

@ -303,7 +303,7 @@ else:
type sink*{.magic: "BuiltinType".}[T] type sink*{.magic: "BuiltinType".}[T]
type lent*{.magic: "BuiltinType".}[T] type lent*{.magic: "BuiltinType".}[T]
proc high*[T: Ordinal](x: T): T {.magic: "High", noSideEffect.} proc high*[T: Ordinal|enum|range](x: T): T {.magic: "High", noSideEffect.}
## Returns the highest possible value of an ordinal value `x`. ## Returns the highest possible value of an ordinal value `x`.
## ##
## As a special semantic rule, `x` may also be a type identifier. ## As a special semantic rule, `x` may also be a type identifier.
@ -314,7 +314,7 @@ proc high*[T: Ordinal](x: T): T {.magic: "High", noSideEffect.}
## .. code-block:: Nim ## .. code-block:: Nim
## high(2) # => 9223372036854775807 ## high(2) # => 9223372036854775807
proc high*[T: Ordinal|enum](x: typeDesc[T]): T {.magic: "High", noSideEffect.} proc high*[T: Ordinal|enum|range](x: typeDesc[T]): T {.magic: "High", noSideEffect.}
## Returns the highest possible value of an ordinal or enum type. ## Returns the highest possible value of an ordinal or enum type.
## ##
## ``high(int)`` is Nim's way of writing `INT_MAX`:idx: or `MAX_INT`:idx:. ## ``high(int)`` is Nim's way of writing `INT_MAX`:idx: or `MAX_INT`:idx:.
@ -375,7 +375,7 @@ proc high*(x: string): int {.magic: "High", noSideEffect.}
## var str = "Hello world!" ## var str = "Hello world!"
## high(str) # => 11 ## high(str) # => 11
proc low*[T](x: T): T {.magic: "Low", noSideEffect.} proc low*[T: Ordinal|enum|range](x: T): T {.magic: "Low", noSideEffect.}
## Returns the lowest possible value of an ordinal value `x`. As a special ## Returns the lowest possible value of an ordinal value `x`. As a special
## semantic rule, `x` may also be a type identifier. ## semantic rule, `x` may also be a type identifier.
## ##
@ -385,7 +385,7 @@ proc low*[T](x: T): T {.magic: "Low", noSideEffect.}
## .. code-block:: Nim ## .. code-block:: Nim
## low(2) # => -9223372036854775808 ## low(2) # => -9223372036854775808
proc low*[T: Ordinal|enum](x: typeDesc[T]): T {.magic: "Low", noSideEffect.} proc low*[T: Ordinal|enum|range](x: typeDesc[T]): T {.magic: "Low", noSideEffect.}
## Returns the lowest possible value of an ordinal or enum type. ## Returns the lowest possible value of an ordinal or enum type.
## ##
## ``low(int)`` is Nim's way of writing `INT_MIN`:idx: or `MIN_INT`:idx:. ## ``low(int)`` is Nim's way of writing `INT_MIN`:idx: or `MIN_INT`:idx:.

14
tests/misc/tlowhigh.nim Normal file
View file

@ -0,0 +1,14 @@
discard """
action: run
"""
var x: range[-1'f32..1'f32]
doAssert x.low == -1'f32
doAssert x.high == 1'f32
doAssert x.type.low == -1'f32
doAssert x.type.high == 1'f32
var y: range[-1'f64..1'f64]
doAssert y.low == -1'f64
doAssert y.high == 1'f64
doAssert y.type.low == -1'f64
doAssert y.type.high == 1'f64