diff options
-rw-r--r-- | changelog.md | 3 | ||||
-rw-r--r-- | compiler/condsyms.nim | 1 | ||||
-rw-r--r-- | compiler/semtypes.nim | 16 | ||||
-rw-r--r-- | lib/pure/collections/sequtils.nim | 22 | ||||
-rw-r--r-- | lib/system.nim | 9 |
5 files changed, 47 insertions, 4 deletions
diff --git a/changelog.md b/changelog.md index 9a5671757..e9e48d035 100644 --- a/changelog.md +++ b/changelog.md @@ -27,6 +27,9 @@ - Added `or` for `NimNode` in `macros`. +- Added `system.typeof` for more control over how `type` expressions + can be deduced. + ### Library changes diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index 13e0d0d11..648dcd8c4 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -84,6 +84,7 @@ proc initDefines*(symbols: StringTableRef) = defineSymbol("nimNoNilSeqs2") defineSymbol("nimHasUserErrors") defineSymbol("nimUncheckedArrayTyp") + defineSymbol("nimHasTypeof") defineSymbol("nimHasNilSeqs") for f in low(Feature)..high(Feature): diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index bbd966b38..f3ad46a9d 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -1414,6 +1414,20 @@ proc semTypeof(c: PContext; n: PNode; prev: PType): PType = fixupTypeOf(c, prev, t) result = t.typ +proc semTypeof2(c: PContext; n: PNode; prev: PType): PType = + openScope(c) + var m = BiggestInt 1 # typeOfIter + if n.len == 3: + let mode = semConstExpr(c, n[2]) + if mode.kind != nkIntLit: + localError(c.config, n.info, "typeof: cannot evaluate 'mode' parameter at compile-time") + else: + m = mode.intVal + let t = semExprWithType(c, n[1], if m == 1: {efInTypeof} else: {}) + closeScope(c) + fixupTypeOf(c, prev, t) + result = t.typ + proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = result = nil inc c.inTypeContext @@ -1494,6 +1508,8 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = elif op.id == ord(wType): checkSonsLen(n, 2, c.config) result = semTypeof(c, n[1], prev) + elif op.s == "typeof" and n[0].kind == nkSym and n[0].sym.magic == mTypeof: + result = semTypeOf2(c, n, prev) else: if c.inGenericContext > 0 and n.kind == nkCall: result = makeTypeFromExpr(c, n.copyTree) diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim index 2e21786bb..e8ea675f5 100644 --- a/lib/pure/collections/sequtils.nim +++ b/lib/pure/collections/sequtils.nim @@ -673,10 +673,16 @@ template mapIt*(s: typed, op: untyped): untyped = ## nums = @[1, 2, 3, 4] ## strings = nums.mapIt($(4 * it)) ## assert strings == @["4", "8", "12", "16"] - type outType = type(( - block: - var it{.inject.}: type(items(s)); - op)) + when defined(nimHasTypeof): + type outType = typeof(( + block: + var it{.inject.}: typeof(items(s), typeOfIter); + op), typeOfProc) + else: + type outType = type(( + block: + var it{.inject.}: type(items(s)); + op)) when compiles(s.len): block: # using a block avoids https://github.com/nim-lang/Nim/issues/8580 @@ -1135,5 +1141,13 @@ when isMainModule: A, B doAssert mapIt(X, $it) == @["A", "B"] + block: + # bug #9093 + let inp = "a:b,c:d" + + let outp = inp.split(",").mapIt(it.split(":")) + doAssert outp == @[@["a", "b"], @["c", "d"]] + + when not defined(testing): echo "Finished doc tests" diff --git a/lib/system.nim b/lib/system.nim index 469f5cebe..5ff9ffbeb 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -180,6 +180,15 @@ else: ## Cannot be overloaded. discard +when defined(nimHasTypeof): + type + TypeOfMode* = enum ## Possible modes of `typeof`. + typeOfProc, ## Prefer the interpretation that means `x` is a proc call. + typeOfIter ## Prefer the interpretation that means `x` is an iterator call. + proc typeof*(x: untyped; mode = typeOfIter): typeDesc {.magic: "TypeOf", noSideEffect, compileTime.} = + ## Builtin 'typeof' operation for accessing the type of an expression. Since version 0.20.0. + discard + proc `not`*(x: bool): bool {.magic: "Not", noSideEffect.} ## Boolean not; returns true iff ``x == false``. |