mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-13 06:43:52 +00:00
low/high/of are now overloadable operations
This commit is contained in:
@@ -274,41 +274,6 @@ proc semSizeof(c: PContext, n: PNode): PNode =
|
||||
n.typ = getSysType(tyInt)
|
||||
result = n
|
||||
|
||||
proc semOf(c: PContext, n: PNode): PNode =
|
||||
if sonsLen(n) == 3:
|
||||
n.sons[1] = semExprWithType(c, n.sons[1])
|
||||
n.sons[2] = semExprWithType(c, n.sons[2], {efDetermineType})
|
||||
#restoreOldStyleType(n.sons[1])
|
||||
#restoreOldStyleType(n.sons[2])
|
||||
let a = skipTypes(n.sons[1].typ, abstractPtrs)
|
||||
let b = skipTypes(n.sons[2].typ, abstractPtrs)
|
||||
let x = skipTypes(n.sons[1].typ, abstractPtrs-{tyTypeDesc})
|
||||
let y = skipTypes(n.sons[2].typ, abstractPtrs-{tyTypeDesc})
|
||||
|
||||
if x.kind == tyTypeDesc or y.kind != tyTypeDesc:
|
||||
localError(n.info, errXExpectsObjectTypes, "of")
|
||||
elif b.kind != tyObject or a.kind != tyObject:
|
||||
localError(n.info, errXExpectsObjectTypes, "of")
|
||||
else:
|
||||
let diff = inheritanceDiff(a, b)
|
||||
# | returns: 0 iff `a` == `b`
|
||||
# | returns: -x iff `a` is the x'th direct superclass of `b`
|
||||
# | returns: +x iff `a` is the x'th direct subclass of `b`
|
||||
# | returns: `maxint` iff `a` and `b` are not compatible at all
|
||||
if diff <= 0:
|
||||
# optimize to true:
|
||||
message(n.info, hintConditionAlwaysTrue, renderTree(n))
|
||||
result = newIntNode(nkIntLit, 1)
|
||||
result.info = n.info
|
||||
result.typ = getSysType(tyBool)
|
||||
return result
|
||||
elif diff == high(int):
|
||||
localError(n.info, errXcanNeverBeOfThisSubtype, typeToString(a))
|
||||
else:
|
||||
localError(n.info, errXExpectsTwoArguments, "of")
|
||||
n.typ = getSysType(tyBool)
|
||||
result = n
|
||||
|
||||
proc isOpImpl(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
internalAssert n.sonsLen == 3 and
|
||||
n[1].typ != nil and n[1].typ.kind == tyTypeDesc and
|
||||
@@ -1831,11 +1796,11 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||
of mDefined: result = semDefined(c, setMs(n, s), false)
|
||||
of mDefinedInScope: result = semDefined(c, setMs(n, s), true)
|
||||
of mCompiles: result = semCompiles(c, setMs(n, s), flags)
|
||||
of mLow: result = semLowHigh(c, setMs(n, s), mLow)
|
||||
of mHigh: result = semLowHigh(c, setMs(n, s), mHigh)
|
||||
#of mLow: result = semLowHigh(c, setMs(n, s), mLow)
|
||||
#of mHigh: result = semLowHigh(c, setMs(n, s), mHigh)
|
||||
of mSizeOf: result = semSizeof(c, setMs(n, s))
|
||||
of mIs: result = semIs(c, setMs(n, s), flags)
|
||||
of mOf: result = semOf(c, setMs(n, s))
|
||||
#of mOf: result = semOf(c, setMs(n, s))
|
||||
of mShallowCopy: result = semShallowCopy(c, n, flags)
|
||||
of mExpandToAst: result = semExpandToAst(c, n, s, flags)
|
||||
of mQuoteAst: result = semQuoteAst(c, n)
|
||||
|
||||
@@ -200,6 +200,41 @@ proc isStrangeArray(t: PType): bool =
|
||||
let t = t.skipTypes(abstractInst)
|
||||
result = t.kind == tyArray and t.firstOrd != 0
|
||||
|
||||
proc semOf(c: PContext, n: PNode): PNode =
|
||||
if sonsLen(n) == 3:
|
||||
n.sons[1] = semExprWithType(c, n.sons[1])
|
||||
n.sons[2] = semExprWithType(c, n.sons[2], {efDetermineType})
|
||||
#restoreOldStyleType(n.sons[1])
|
||||
#restoreOldStyleType(n.sons[2])
|
||||
let a = skipTypes(n.sons[1].typ, abstractPtrs)
|
||||
let b = skipTypes(n.sons[2].typ, abstractPtrs)
|
||||
let x = skipTypes(n.sons[1].typ, abstractPtrs-{tyTypeDesc})
|
||||
let y = skipTypes(n.sons[2].typ, abstractPtrs-{tyTypeDesc})
|
||||
|
||||
if x.kind == tyTypeDesc or y.kind != tyTypeDesc:
|
||||
localError(n.info, errXExpectsObjectTypes, "of")
|
||||
elif b.kind != tyObject or a.kind != tyObject:
|
||||
localError(n.info, errXExpectsObjectTypes, "of")
|
||||
else:
|
||||
let diff = inheritanceDiff(a, b)
|
||||
# | returns: 0 iff `a` == `b`
|
||||
# | returns: -x iff `a` is the x'th direct superclass of `b`
|
||||
# | returns: +x iff `a` is the x'th direct subclass of `b`
|
||||
# | returns: `maxint` iff `a` and `b` are not compatible at all
|
||||
if diff <= 0:
|
||||
# optimize to true:
|
||||
message(n.info, hintConditionAlwaysTrue, renderTree(n))
|
||||
result = newIntNode(nkIntLit, 1)
|
||||
result.info = n.info
|
||||
result.typ = getSysType(tyBool)
|
||||
return result
|
||||
elif diff == high(int):
|
||||
localError(n.info, errXcanNeverBeOfThisSubtype, typeToString(a))
|
||||
else:
|
||||
localError(n.info, errXExpectsTwoArguments, "of")
|
||||
n.typ = getSysType(tyBool)
|
||||
result = n
|
||||
|
||||
proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||
flags: TExprFlags): PNode =
|
||||
case n[0].sym.magic
|
||||
@@ -219,6 +254,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||
result.typ = getSysType(tyString)
|
||||
of mInstantiationInfo: result = semInstantiationInfo(c, n)
|
||||
of mOrd: result = semOrd(c, n)
|
||||
of mOf: result = semOf(c, n)
|
||||
of mHigh, mLow: result = semLowHigh(c, n, n[0].sym.magic)
|
||||
of mShallowCopy: result = semShallowCopy(c, n, flags)
|
||||
of mNBindSym: result = semBindSym(c, n)
|
||||
|
||||
@@ -231,31 +231,6 @@ proc reset*[T](obj: var T) {.magic: "Reset", noSideEffect.}
|
||||
## resets an object `obj` to its initial (binary zero) value. This needs to
|
||||
## be called before any possible `object branch transition`:idx:.
|
||||
|
||||
# for low and high the return type T may not be correct, but
|
||||
# we handle that with compiler magic in semLowHigh()
|
||||
proc high*[T](x: T): T {.magic: "High", noSideEffect.}
|
||||
## returns the highest possible index of an array, a sequence, a string or
|
||||
## the highest possible value of an ordinal value `x`. As a special
|
||||
## semantic rule, `x` may also be a type identifier.
|
||||
## ``high(int)`` is Nim's way of writing `INT_MAX`:idx: or `MAX_INT`:idx:.
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## var arr = [1,2,3,4,5,6,7]
|
||||
## high(arr) #=> 6
|
||||
## high(2) #=> 9223372036854775807
|
||||
## high(int) #=> 9223372036854775807
|
||||
|
||||
proc low*[T](x: T): T {.magic: "Low", noSideEffect.}
|
||||
## returns the lowest possible index of an array, a sequence, a string or
|
||||
## the lowest possible value of an ordinal value `x`. As a special
|
||||
## semantic rule, `x` may also be a type identifier.
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## var arr = [1,2,3,4,5,6,7]
|
||||
## low(arr) #=> 0
|
||||
## low(2) #=> -9223372036854775808
|
||||
## low(int) #=> -9223372036854775808
|
||||
|
||||
type
|
||||
range*{.magic: "Range".}[T] ## Generic type to construct range types.
|
||||
array*{.magic: "Array".}[I, T] ## Generic type to construct
|
||||
@@ -271,6 +246,36 @@ type
|
||||
UncheckedArray* {.unchecked.}[T] = array[0, T]
|
||||
## Array with no bounds checking
|
||||
|
||||
proc high*[T: Ordinal](x: T): T {.magic: "High", noSideEffect.}
|
||||
## returns the highest possible index of an array, a sequence, a string or
|
||||
## the highest possible value of an ordinal value `x`. As a special
|
||||
## semantic rule, `x` may also be a type identifier.
|
||||
## ``high(int)`` is Nim's way of writing `INT_MAX`:idx: or `MAX_INT`:idx:.
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## var arr = [1,2,3,4,5,6,7]
|
||||
## high(arr) #=> 6
|
||||
## high(2) #=> 9223372036854775807
|
||||
## high(int) #=> 9223372036854775807
|
||||
|
||||
proc high*[T: Ordinal](x: typeDesc[T]): T {.magic: "High", noSideEffect.}
|
||||
proc high*[T](x: openArray[T]): int {.magic: "High", noSideEffect.}
|
||||
proc high*[I, T](x: array[I, T]): I {.magic: "High", noSideEffect.}
|
||||
|
||||
proc low*[T: Ordinal](x: typeDesc[T]): T {.magic: "Low", noSideEffect.}
|
||||
proc low*[T](x: openArray[T]): int {.magic: "Low", noSideEffect.}
|
||||
proc low*[I, T](x: array[I, T]): I {.magic: "Low", noSideEffect.}
|
||||
proc low*[T](x: T): T {.magic: "Low", noSideEffect.}
|
||||
## returns the lowest possible index of an array, a sequence, a string or
|
||||
## the lowest possible value of an ordinal value `x`. As a special
|
||||
## semantic rule, `x` may also be a type identifier.
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## var arr = [1,2,3,4,5,6,7]
|
||||
## low(arr) #=> 0
|
||||
## low(2) #=> -9223372036854775808
|
||||
## low(int) #=> -9223372036854775808
|
||||
|
||||
when defined(nimArrIdx):
|
||||
# :array|openarray|string|seq|cstring|tuple
|
||||
proc `[]`*[I: Ordinal;T](a: T; i: I): T {.
|
||||
@@ -1175,6 +1180,8 @@ proc `is` *[T, S](x: T, y: S): bool {.magic: "Is", noSideEffect.}
|
||||
template `isnot` *(x, y: untyped): untyped = not (x is y)
|
||||
## Negated version of `is`. Equivalent to ``not(x is y)``.
|
||||
|
||||
proc `of` *[T, S](x: typeDesc[T], y: typeDesc[S]): bool {.magic: "Of", noSideEffect.}
|
||||
proc `of` *[T, S](x: T, y: typeDesc[S]): bool {.magic: "Of", noSideEffect.}
|
||||
proc `of` *[T, S](x: T, y: S): bool {.magic: "Of", noSideEffect.}
|
||||
## Checks if `x` has a type of `y`
|
||||
##
|
||||
|
||||
Reference in New Issue
Block a user