diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 81799e7624..63039b36da 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -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) diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index c664f735c9..8b3d9c0144 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -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) diff --git a/lib/system.nim b/lib/system.nim index 93152a9e01..f8896ed134 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -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` ##