low/high/of are now overloadable operations
This commit is contained in:
parent
786f9315e3
commit
8d714d2b02
3 changed files with 71 additions and 63 deletions
|
|
@ -274,41 +274,6 @@ proc semSizeof(c: PContext, n: PNode): PNode =
|
||||||
n.typ = getSysType(tyInt)
|
n.typ = getSysType(tyInt)
|
||||||
result = n
|
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 =
|
proc isOpImpl(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
internalAssert n.sonsLen == 3 and
|
internalAssert n.sonsLen == 3 and
|
||||||
n[1].typ != nil and n[1].typ.kind == tyTypeDesc 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 mDefined: result = semDefined(c, setMs(n, s), false)
|
||||||
of mDefinedInScope: result = semDefined(c, setMs(n, s), true)
|
of mDefinedInScope: result = semDefined(c, setMs(n, s), true)
|
||||||
of mCompiles: result = semCompiles(c, setMs(n, s), flags)
|
of mCompiles: result = semCompiles(c, setMs(n, s), flags)
|
||||||
of mLow: result = semLowHigh(c, setMs(n, s), mLow)
|
#of mLow: result = semLowHigh(c, setMs(n, s), mLow)
|
||||||
of mHigh: result = semLowHigh(c, setMs(n, s), mHigh)
|
#of mHigh: result = semLowHigh(c, setMs(n, s), mHigh)
|
||||||
of mSizeOf: result = semSizeof(c, setMs(n, s))
|
of mSizeOf: result = semSizeof(c, setMs(n, s))
|
||||||
of mIs: result = semIs(c, setMs(n, s), flags)
|
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 mShallowCopy: result = semShallowCopy(c, n, flags)
|
||||||
of mExpandToAst: result = semExpandToAst(c, n, s, flags)
|
of mExpandToAst: result = semExpandToAst(c, n, s, flags)
|
||||||
of mQuoteAst: result = semQuoteAst(c, n)
|
of mQuoteAst: result = semQuoteAst(c, n)
|
||||||
|
|
|
||||||
|
|
@ -200,6 +200,41 @@ proc isStrangeArray(t: PType): bool =
|
||||||
let t = t.skipTypes(abstractInst)
|
let t = t.skipTypes(abstractInst)
|
||||||
result = t.kind == tyArray and t.firstOrd != 0
|
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,
|
proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||||
flags: TExprFlags): PNode =
|
flags: TExprFlags): PNode =
|
||||||
case n[0].sym.magic
|
case n[0].sym.magic
|
||||||
|
|
@ -219,6 +254,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||||
result.typ = getSysType(tyString)
|
result.typ = getSysType(tyString)
|
||||||
of mInstantiationInfo: result = semInstantiationInfo(c, n)
|
of mInstantiationInfo: result = semInstantiationInfo(c, n)
|
||||||
of mOrd: result = semOrd(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 mHigh, mLow: result = semLowHigh(c, n, n[0].sym.magic)
|
||||||
of mShallowCopy: result = semShallowCopy(c, n, flags)
|
of mShallowCopy: result = semShallowCopy(c, n, flags)
|
||||||
of mNBindSym: result = semBindSym(c, n)
|
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
|
## resets an object `obj` to its initial (binary zero) value. This needs to
|
||||||
## be called before any possible `object branch transition`:idx:.
|
## 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
|
type
|
||||||
range*{.magic: "Range".}[T] ## Generic type to construct range types.
|
range*{.magic: "Range".}[T] ## Generic type to construct range types.
|
||||||
array*{.magic: "Array".}[I, T] ## Generic type to construct
|
array*{.magic: "Array".}[I, T] ## Generic type to construct
|
||||||
|
|
@ -271,6 +246,36 @@ type
|
||||||
UncheckedArray* {.unchecked.}[T] = array[0, T]
|
UncheckedArray* {.unchecked.}[T] = array[0, T]
|
||||||
## Array with no bounds checking
|
## 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):
|
when defined(nimArrIdx):
|
||||||
# :array|openarray|string|seq|cstring|tuple
|
# :array|openarray|string|seq|cstring|tuple
|
||||||
proc `[]`*[I: Ordinal;T](a: T; i: I): T {.
|
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)
|
template `isnot` *(x, y: untyped): untyped = not (x is y)
|
||||||
## Negated version of `is`. Equivalent to ``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.}
|
proc `of` *[T, S](x: T, y: S): bool {.magic: "Of", noSideEffect.}
|
||||||
## Checks if `x` has a type of `y`
|
## Checks if `x` has a type of `y`
|
||||||
##
|
##
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue