From be4816f5097ce72e124e5e087ffa4d386fa17d4d Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Tue, 7 Aug 2018 08:48:52 +0200 Subject: [PATCH 1/6] Iterator over heap instances (#8548) Provide "dumpHeapInstances" for iterating over type statistics of heaps. This can be used to present structured heap information as an alternative to "dumpNumberOfInstances". --- lib/system/gc_common.nim | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/system/gc_common.nim b/lib/system/gc_common.nim index dcea0c4cc9..88e150cd13 100644 --- a/lib/system/gc_common.nim +++ b/lib/system/gc_common.nim @@ -37,22 +37,28 @@ when defined(nimTypeNames): a[j] = v if h == 1: break - proc dumpNumberOfInstances* = - # also add the allocated strings to the list of known types: + iterator dumpHeapInstances*(): tuple[name: cstring; count: int; sizes: int] = + ## Iterate over summaries of types on heaps. + ## This data may be inaccurate if allocations + ## are made by the iterator body. if strDesc.nextType == nil: strDesc.nextType = nimTypeRoot strDesc.name = "string" nimTypeRoot = addr strDesc + var it = nimTypeRoot + while it != nil: + if (it.instances > 0 or it.sizes != 0): + yield (it.name, it.instances, it.sizes) + it = it.nextType + + proc dumpNumberOfInstances* = var a: InstancesInfo var n = 0 - var it = nimTypeRoot var totalAllocated = 0 - while it != nil: - if (it.instances > 0 or it.sizes != 0) and n < a.len: - a[n] = (it.name, it.instances, it.sizes) - inc n + for it in dumpHeapInstances(): + a[n] = it + inc n inc totalAllocated, it.sizes - it = it.nextType sortInstances(a, n) for i in 0 .. n-1: c_fprintf(stdout, "[Heap] %s: #%ld; bytes: %ld\n", a[i][0], a[i][1], a[i][2]) From c3d5ec8eadf3aa887f34231c2d7b5818923818d4 Mon Sep 17 00:00:00 2001 From: andri lim Date: Tue, 7 Aug 2018 14:07:18 +0700 Subject: [PATCH 2/6] fixes #8421, fixes #7968, Nim compiler compiles with MSVC C89 version (#8556) --- compiler/rodutils.nim | 21 +++++++++++ lib/pure/math.nim | 80 +++++++++++++++++++++++++++++------------ lib/windows/winlean.nim | 2 +- 3 files changed, 79 insertions(+), 24 deletions(-) diff --git a/compiler/rodutils.nim b/compiler/rodutils.nim index 66d7f63c24..a774cdba77 100644 --- a/compiler/rodutils.nim +++ b/compiler/rodutils.nim @@ -10,6 +10,27 @@ ## Serialization utilities for the compiler. import strutils, math +# MSVC prior to 2013 doesn't have C99 functions +when defined(windows) and (defined(vcc) or defined(bcc)): + {.emit: """#if defined(_MSC_VER) && _MSC_VER < 1900 + #include + static int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) { + int count = -1; + if (size != 0) count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap); + if (count == -1) count = _vscprintf(format, ap); + return count; + } + int snprintf(char *outBuf, size_t size, const char *format, ...) { + int count; + va_list ap; + va_start(ap, format); + count = c99_vsnprintf(outBuf, size, format, ap); + va_end(ap); + return count; + } + #endif + """.} + proc c_snprintf(s: cstring; n:uint; frmt: cstring): cint {.importc: "snprintf", header: "", nodecl, varargs.} proc toStrMaxPrecision*(f: BiggestFloat, literalPostfix = ""): string = diff --git a/lib/pure/math.nim b/lib/pure/math.nim index b921b18417..eb09bf4a7e 100644 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -162,9 +162,6 @@ when not defined(JS): # C proc log10*(x: float32): float32 {.importc: "log10f", header: "".} proc log10*(x: float64): float64 {.importc: "log10", header: "".} ## Computes the common logarithm (base 10) of `x` - proc log2*(x: float32): float32 {.importc: "log2f", header: "".} - proc log2*(x: float64): float64 {.importc: "log2", header: "".} - ## Computes the binary logarithm (base 2) of `x` proc exp*(x: float32): float32 {.importc: "expf", header: "".} proc exp*(x: float64): float64 {.importc: "exp", header: "".} ## Computes the exponential function of `x` (pow(E, x)) @@ -268,6 +265,8 @@ proc arcsech*[T: float32|float64](x: T): T = arccosh(1.0 / x) proc arccsch*[T: float32|float64](x: T): T = arcsinh(1.0 / x) ## Computes the inverse hyperbolic cosecant of `x` +const windowsCC89 = defined(windows) and (defined(vcc) or defined(bcc)) + when not defined(JS): # C proc hypot*(x, y: float32): float32 {.importc: "hypotf", header: "".} proc hypot*(x, y: float64): float64 {.importc: "hypot", header: "".} @@ -280,25 +279,27 @@ when not defined(JS): # C ## ## To compute power between integers, use `^` e.g. 2 ^ 6 - proc erf*(x: float32): float32 {.importc: "erff", header: "".} - proc erf*(x: float64): float64 {.importc: "erf", header: "".} - ## The error function - proc erfc*(x: float32): float32 {.importc: "erfcf", header: "".} - proc erfc*(x: float64): float64 {.importc: "erfc", header: "".} - ## The complementary error function + # TODO: add C89 version on windows + when not windowsCC89: + proc erf*(x: float32): float32 {.importc: "erff", header: "".} + proc erf*(x: float64): float64 {.importc: "erf", header: "".} + ## The error function + proc erfc*(x: float32): float32 {.importc: "erfcf", header: "".} + proc erfc*(x: float64): float64 {.importc: "erfc", header: "".} + ## The complementary error function - proc gamma*(x: float32): float32 {.importc: "tgammaf", header: "".} - proc gamma*(x: float64): float64 {.importc: "tgamma", header: "".} - ## The gamma function - proc tgamma*(x: float32): float32 - {.deprecated: "use gamma instead", importc: "tgammaf", header: "".} - proc tgamma*(x: float64): float64 - {.deprecated: "use gamma instead", importc: "tgamma", header: "".} - ## The gamma function - ## **Deprecated since version 0.19.0**: Use ``gamma`` instead. - proc lgamma*(x: float32): float32 {.importc: "lgammaf", header: "".} - proc lgamma*(x: float64): float64 {.importc: "lgamma", header: "".} - ## Natural log of the gamma function + proc gamma*(x: float32): float32 {.importc: "tgammaf", header: "".} + proc gamma*(x: float64): float64 {.importc: "tgamma", header: "".} + ## The gamma function + proc tgamma*(x: float32): float32 + {.deprecated: "use gamma instead", importc: "tgammaf", header: "".} + proc tgamma*(x: float64): float64 + {.deprecated: "use gamma instead", importc: "tgamma", header: "".} + ## The gamma function + ## **Deprecated since version 0.19.0**: Use ``gamma`` instead. + proc lgamma*(x: float32): float32 {.importc: "lgammaf", header: "".} + proc lgamma*(x: float64): float64 {.importc: "lgamma", header: "".} + ## Natural log of the gamma function proc floor*(x: float32): float32 {.importc: "floorf", header: "".} proc floor*(x: float64): float64 {.importc: "floor", header: "".} @@ -314,7 +315,7 @@ when not defined(JS): # C ## .. code-block:: nim ## echo ceil(-2.1) ## -2.0 - when defined(windows) and (defined(vcc) or defined(bcc)): + when windowsCC89: # MSVC 2010 don't have trunc/truncf # this implementation was inspired by Go-lang Math.Trunc proc truncImpl(f: float64): float64 = @@ -452,6 +453,28 @@ when not defined(JS): var exp: int32 result = c_frexp(x, exp) exponent = exp + + when windowsCC89: + # taken from Go-lang Math.Log2 + const ln2 = 0.693147180559945309417232121458176568075500134360255254120680009 + template log2Impl[T](x: T): T = + var exp: int32 + var frac = frexp(x, exp) + # Make sure exact powers of two give an exact answer. + # Don't depend on Log(0.5)*(1/Ln2)+exp being exactly exp-1. + if frac == 0.5: return T(exp - 1) + log10(frac)*(1/ln2) + T(exp) + + proc log2*(x: float32): float32 = log2Impl(x) + proc log2*(x: float64): float64 = log2Impl(x) + ## Log2 returns the binary logarithm of x. + ## The special cases are the same as for Log. + + else: + proc log2*(x: float32): float32 {.importc: "log2f", header: "".} + proc log2*(x: float64): float64 {.importc: "log2", header: "".} + ## Computes the binary logarithm (base 2) of `x` + else: proc frexp*[T: float32|float64](x: T, exponent: var int): T = if x == 0.0: @@ -564,7 +587,7 @@ proc lcm*[T](x, y: T): T = ## Computes the least common multiple of ``x`` and ``y``. x div gcd(x, y) * y -when isMainModule and not defined(JS): +when isMainModule and not defined(JS) and not windowsCC89: # Check for no side effect annotation proc mySqrt(num: float): float {.noSideEffect.} = return sqrt(num) @@ -692,3 +715,14 @@ when isMainModule: block: # log doAssert log(4.0, 3.0) == ln(4.0) / ln(3.0) + doAssert log2(8.0'f64) == 3.0'f64 + doAssert log2(4.0'f64) == 2.0'f64 + doAssert log2(2.0'f64) == 1.0'f64 + doAssert log2(1.0'f64) == 0.0'f64 + doAssert classify(log2(0.0'f64)) == fcNegInf + + doAssert log2(8.0'f32) == 3.0'f32 + doAssert log2(4.0'f32) == 2.0'f32 + doAssert log2(2.0'f32) == 1.0'f32 + doAssert log2(1.0'f32) == 0.0'f32 + doAssert classify(log2(0.0'f32)) == fcNegInf diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim index 3263f1d370..60a6e5d9b3 100644 --- a/lib/windows/winlean.nim +++ b/lib/windows/winlean.nim @@ -396,7 +396,7 @@ else: proc moveFileA*(lpExistingFileName, lpNewFileName: cstring): WINBOOL {. importc: "MoveFileA", stdcall, dynlib: "kernel32".} - proc moveFileExA*(lpExistingFileName, lpNewFileName: WideCString, + proc moveFileExA*(lpExistingFileName, lpNewFileName: cstring, flags: DWORD): WINBOOL {. importc: "MoveFileExA", stdcall, dynlib: "kernel32".} From 9b9cfa7306d696961cc6fd590ca72c08f66bdcb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Nihlg=C3=A5rd?= Date: Tue, 7 Aug 2018 09:24:54 +0200 Subject: [PATCH 3/6] Stricter signature for countdown/countup (#8549) --- lib/system.nim | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/system.nim b/lib/system.nim index 0cfa39e196..94baf73706 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1978,7 +1978,7 @@ when sizeof(int) <= 2: else: type IntLikeForCount = int|int8|int16|int32|char|bool|uint8|uint16|enum -iterator countdown*[T](a, b: T, step = 1): T {.inline.} = +iterator countdown*[T](a, b: T, step: Positive = 1): T {.inline.} = ## Counts from ordinal value `a` down to `b` (inclusive) with the given ## step count. `T` may be any ordinal type, `step` may only ## be positive. **Note**: This fails to count to ``low(int)`` if T = int for @@ -2001,7 +2001,7 @@ iterator countdown*[T](a, b: T, step = 1): T {.inline.} = dec(res, step) when defined(nimNewRoof): - iterator countup*[T](a, b: T, step = 1): T {.inline.} = + iterator countup*[T](a, b: T, step: Positive = 1): T {.inline.} = ## Counts from ordinal value `a` up to `b` (inclusive) with the given ## step count. `S`, `T` may be any ordinal type, `step` may only ## be positive. **Note**: This fails to count to ``high(int)`` if T = int for @@ -2018,7 +2018,7 @@ when defined(nimNewRoof): inc(res, step) iterator `..`*[T](a, b: T): T {.inline.} = - ## An alias for `countup`. + ## An alias for `countup(a, b, 1)`. when T is IntLikeForCount: var res = int(a) while res <= int(b): From 4d5cce9882d554ada9cf737d63e40880d88ba170 Mon Sep 17 00:00:00 2001 From: andri lim Date: Tue, 7 Aug 2018 23:41:30 +0700 Subject: [PATCH 4/6] fixes #6255, add `system.ashr` arithmetic right shift (#8547) --- changelog.md | 3 ++- compiler/ast.nim | 2 +- compiler/ccgexprs.nim | 2 +- compiler/condsyms.nim | 1 + compiler/jsgen.nim | 1 + compiler/semfold.nim | 8 +++++++ compiler/sigmatch.nim | 4 ++++ compiler/vm.nim | 3 +++ compiler/vmdef.nim | 3 ++- compiler/vmgen.nim | 1 + lib/system.nim | 17 +++++++++++++++ tests/arithm/tashr.nim | 46 ++++++++++++++++++++++++++++++++++++++++ tests/concepts/t3330.nim | 16 +++++++------- 13 files changed, 95 insertions(+), 12 deletions(-) create mode 100644 tests/arithm/tashr.nim diff --git a/changelog.md b/changelog.md index 4c19abfc00..c1e7bd09ca 100644 --- a/changelog.md +++ b/changelog.md @@ -91,7 +91,8 @@ - ``parseOct`` and ``parseBin`` in parseutils now also support the ``maxLen`` argument similar to ``parseHexInt`` - Added the proc ``flush`` for memory mapped files. - Added the ``MemMapFileStream``. -- Added ``macros.copyLineInfo`` to copy lineInfo from other node +- Added ``macros.copyLineInfo`` to copy lineInfo from other node. +- Added ``system.ashr`` an arithmetic right shift for integers. ### Library changes diff --git a/compiler/ast.nim b/compiler/ast.nim index dbf1151a90..ef12e11843 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -591,7 +591,7 @@ type mAddI, mSubI, mMulI, mDivI, mModI, mSucc, mPred, mAddF64, mSubF64, mMulF64, mDivF64, - mShrI, mShlI, mBitandI, mBitorI, mBitxorI, + mShrI, mShlI, mAshrI, mBitandI, mBitorI, mBitxorI, mMinI, mMaxI, mMinF64, mMaxF64, mAddU, mSubU, mMulU, mDivU, mModU, diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 3bcf2c29bc..6803a9478f 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -552,9 +552,9 @@ proc binaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) = "(($4)($1) - ($4)($2))", # SubF64 "(($4)($1) * ($4)($2))", # MulF64 "(($4)($1) / ($4)($2))", # DivF64 - "($4)((NU$5)($1) >> (NU$3)($2))", # ShrI "($4)((NU$3)($1) << (NU$3)($2))", # ShlI + "($4)((NI$3)($1) >> (NU$3)($2))", # AshrI "($4)($1 & $2)", # BitandI "($4)($1 | $2)", # BitorI "($4)($1 ^ $2)", # BitxorI diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index 9dfe694426..5a62b46ad1 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -73,3 +73,4 @@ proc initDefines*(symbols: StringTableRef) = defineSymbol("nimNotNil") defineSymbol("nimVmExportFixed") defineSymbol("nimIncrSeqV3") + defineSymbol("nimAshr") diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index ef54841ae1..63100a68d5 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -379,6 +379,7 @@ const # magic checked op; magic unchecked op; checked op; unchecked op ["", "", "($1 / $2)", "($1 / $2)"], # DivF64 ["", "", "", ""], # ShrI ["", "", "($1 << $2)", "($1 << $2)"], # ShlI + ["", "", "($1 >> $2)", "($1 >> $2)"], # AshrI ["", "", "($1 & $2)", "($1 & $2)"], # BitandI ["", "", "($1 | $2)", "($1 | $2)"], # BitorI ["", "", "($1 ^ $2)", "($1 ^ $2)"], # BitxorI diff --git a/compiler/semfold.nim b/compiler/semfold.nim index d2abfac13f..a6c185fdcb 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -268,6 +268,14 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode = of tyInt64, tyInt, tyUInt..tyUInt64: result = newIntNodeT(`shr`(getInt(a), getInt(b)), n, g) else: internalError(g.config, n.info, "constant folding for shr") + of mAshrI: + case skipTypes(n.typ, abstractRange).kind + of tyInt8: result = newIntNodeT(ashr(int8(getInt(a)), int8(getInt(b))), n, g) + of tyInt16: result = newIntNodeT(ashr(int16(getInt(a)), int16(getInt(b))), n, g) + of tyInt32: result = newIntNodeT(ashr(int32(getInt(a)), int32(getInt(b))), n, g) + of tyInt64, tyInt: + result = newIntNodeT(ashr(getInt(a), getInt(b)), n, g) + else: internalError(g.config, n.info, "constant folding for ashr") of mDivI: result = foldDiv(getInt(a), getInt(b), n, g) of mModI: result = foldMod(getInt(a), getInt(b), n, g) of mAddF64: result = newFloatNodeT(getFloat(a) + getFloat(b), n, g) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 29f16b808f..5afa1b0312 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -858,6 +858,10 @@ proc inferStaticParam*(c: var TCandidate, lhs: PNode, rhs: BiggestInt): bool = if lhs[2].kind == nkIntLit: return inferStaticParam(c, lhs[1], rhs shl lhs[2].intVal) + of mAshrI: + if lhs[2].kind == nkIntLit: + return inferStaticParam(c, lhs[1], ashr(rhs, lhs[2].intVal)) + of mUnaryMinusI: return inferStaticParam(c, lhs[1], -rhs) diff --git a/compiler/vm.nim b/compiler/vm.nim index d4b041dea1..c49b66b82b 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -752,6 +752,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = of opcShlInt: decodeBC(rkInt) regs[ra].intVal = regs[rb].intVal shl regs[rc].intVal + of opcAshrInt: + decodeBC(rkInt) + regs[ra].intVal = ashr(regs[rb].intVal, regs[rc].intVal) of opcBitandInt: decodeBC(rkInt) regs[ra].intVal = regs[rb].intVal and regs[rc].intVal diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim index a4489513a7..50235c95f5 100644 --- a/compiler/vmdef.nim +++ b/compiler/vmdef.nim @@ -57,7 +57,8 @@ type opcLenStr, opcIncl, opcInclRange, opcExcl, opcCard, opcMulInt, opcDivInt, opcModInt, - opcAddFloat, opcSubFloat, opcMulFloat, opcDivFloat, opcShrInt, opcShlInt, + opcAddFloat, opcSubFloat, opcMulFloat, opcDivFloat, + opcShrInt, opcShlInt, opcAshrInt, opcBitandInt, opcBitorInt, opcBitxorInt, opcAddu, opcSubu, opcMulu, opcDivu, opcModu, opcEqInt, opcLeInt, opcLtInt, opcEqFloat, opcLeFloat, opcLtFloat, opcLeu, opcLtu, diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 965c754855..a36f559ca7 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -939,6 +939,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) = c.freeTemp(tmp2) of mShlI: genBinaryABCnarrowU(c, n, dest, opcShlInt) + of mAshrI: genBinaryABCnarrow(c, n, dest, opcAshrInt) of mBitandI: genBinaryABCnarrowU(c, n, dest, opcBitandInt) of mBitorI: genBinaryABCnarrowU(c, n, dest, opcBitorInt) of mBitxorI: genBinaryABCnarrowU(c, n, dest, opcBitxorInt) diff --git a/lib/system.nim b/lib/system.nim index 94baf73706..53605f9fdf 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -971,6 +971,23 @@ else: proc `shl`*(x, y: int32): int32 {.magic: "ShlI", noSideEffect.} proc `shl`*(x, y: int64): int64 {.magic: "ShlI", noSideEffect.} +when defined(nimAshr): + proc ashr*(x: int, y: SomeInteger): int {.magic: "AshrI", noSideEffect.} + proc ashr*(x: int8, y: SomeInteger): int8 {.magic: "AshrI", noSideEffect.} + proc ashr*(x: int16, y: SomeInteger): int16 {.magic: "AshrI", noSideEffect.} + proc ashr*(x: int32, y: SomeInteger): int32 {.magic: "AshrI", noSideEffect.} + proc ashr*(x: int64, y: SomeInteger): int64 {.magic: "AshrI", noSideEffect.} + ## Shifts right by pushing copies of the leftmost bit in from the left, + ## and let the rightmost bits fall off. + ## + ## .. code-block:: Nim + ## 0b0001_0000'i8 shr 2 == 0b0000_0100'i8 + ## 0b1000_0000'i8 shr 8 == 0b1111_1111'i8 + ## 0b1000_0000'i8 shr 1 == 0b1100_0000'i8 +else: + # used for bootstrapping the compiler + proc ashr*[T](x: T, y: SomeInteger): T = discard + proc `and`*(x, y: int): int {.magic: "BitandI", noSideEffect.} proc `and`*(x, y: int8): int8 {.magic: "BitandI", noSideEffect.} proc `and`*(x, y: int16): int16 {.magic: "BitandI", noSideEffect.} diff --git a/tests/arithm/tashr.nim b/tests/arithm/tashr.nim new file mode 100644 index 0000000000..aeb3b68436 --- /dev/null +++ b/tests/arithm/tashr.nim @@ -0,0 +1,46 @@ +discard """ + output: '''''' + targets: '''c js''' +""" + +# issue #6255, feature request +# arithmetic right shift + +var x1 = -123'i8 +var x2 = -123'i16 +var x3 = -123'i32 +var x4 = -123'i64 +var x5 = -123 + +block codegen_test: + doAssert ashr(x1, 1) == -62 + doAssert ashr(x2, 1) == -62 + doAssert ashr(x3, 1) == -62 + doAssert ashr(x4, 1) == -62 + doAssert ashr(x5, 1) == -62 + +block semfold_test: + doAssert ashr(-123'i8 , 1) == -62 + doAssert ashr(-123'i16, 1) == -62 + doAssert ashr(-123'i32, 1) == -62 + doAssert ashr(-123'i64, 1) == -62 + doAssert ashr(-123 , 1) == -62 + +static: # VM test + doAssert ashr(-123'i8 , 1) == -62 + doAssert ashr(-123'i16, 1) == -62 + doAssert ashr(-123'i32, 1) == -62 + doAssert ashr(-123'i64, 1) == -62 + doAssert ashr(-123 , 1) == -62 + + var y1 = -123'i8 + var y2 = -123'i16 + var y3 = -123'i32 + var y4 = -123'i64 + var y5 = -123 + + doAssert ashr(y1, 1) == -62 + doAssert ashr(y2, 1) == -62 + doAssert ashr(y3, 1) == -62 + doAssert ashr(y4, 1) == -62 + doAssert ashr(y5, 1) == -62 diff --git a/tests/concepts/t3330.nim b/tests/concepts/t3330.nim index 78dd876e28..8021db8278 100644 --- a/tests/concepts/t3330.nim +++ b/tests/concepts/t3330.nim @@ -13,18 +13,14 @@ proc add(result: var string; x: float) first type mismatch at position: 1 required type: var string but expression 'k' is of type: Alias -proc add(x: var string; y: cstring) - first type mismatch at position: 1 - required type: var string - but expression 'k' is of type: Alias -proc add(x: var string; y: char) - first type mismatch at position: 1 - required type: var string - but expression 'k' is of type: Alias proc add(x: var string; y: string) first type mismatch at position: 1 required type: var string but expression 'k' is of type: Alias +proc add(x: var string; y: cstring) + first type mismatch at position: 1 + required type: var string + but expression 'k' is of type: Alias proc add[T](x: var seq[T]; y: T) first type mismatch at position: 1 required type: var seq[T] @@ -33,6 +29,10 @@ proc add(result: var string; x: int64) first type mismatch at position: 1 required type: var string but expression 'k' is of type: Alias +proc add(x: var string; y: char) + first type mismatch at position: 1 + required type: var string + but expression 'k' is of type: Alias t3330.nim(48, 8) template/generic instantiation from here t3330.nim(55, 6) Foo: 'bar.value' cannot be assigned to From ba5e2d6fcb4d1dd5fde523076dafeed77360dba5 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 7 Aug 2018 18:45:27 +0200 Subject: [PATCH 5/6] Make mapIt work on openArray's (#8543) --- lib/pure/collections/sequtils.nim | 33 ++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim index db33e41afd..8f81fe4f50 100644 --- a/lib/pure/collections/sequtils.nim +++ b/lib/pure/collections/sequtils.nim @@ -635,6 +635,28 @@ template mapIt*(s, typ, op: untyped): untyped = result.add(op) result +# This is needed in order not to break the bootstrap, the fallback +# implementation is a "dumb" let that won't work in some cases (eg. when `exp` +# is an openArray) +when declared(macros.symKind): + macro evalOnce(v, exp: untyped): untyped = + expectKind(v, nnkIdent) + var val = exp + + result = newStmtList() + + # Not a parameter we can pass as-is, evaluate and store in a temporary + # variable + if exp.kind != nnkSym or exp.symKind != nskParam: + val = genSym() + result.add(newLetStmt(val, exp)) + + result.add( + newProc(name = genSym(nskTemplate, $v), params = [getType(untyped)], + body = val, procType = nnkTemplateDef)) +else: + macro evalOnce(v, exp: untyped): untyped = + result = newLetStmt(v, exp) template mapIt*(s, op: untyped): untyped = ## Convenience template around the ``map`` proc to reduce typing. @@ -654,8 +676,8 @@ template mapIt*(s, op: untyped): untyped = var it{.inject.}: type(items(s)); op)) var result: seq[outType] - when compiles(s.len): - let t = s + evalOnce(t, s) + when compiles(t.len): var i = 0 result = newSeq[outType](t.len) for it {.inject.} in t: @@ -663,7 +685,7 @@ template mapIt*(s, op: untyped): untyped = i += 1 else: result = @[] - for it {.inject.} in s: + for it {.inject.} in t: result.add(op) result @@ -1044,5 +1066,10 @@ when isMainModule: doAssert mapLiterals((1, ("abc"), 2), float, nested=false) == (float(1), "abc", float(2)) doAssert mapLiterals(([1], ("abc"), 2), `$`, nested=true) == (["1"], "abc", "2") + block: # mapIt with openArray + when declared(macros.symKind): + proc foo(x: openArray[int]): seq[int] = x.mapIt(it + 1) + doAssert foo([1,2,3]) == @[2,3,4] + when not defined(testing): echo "Finished doc tests" From c3523297143d730b1714f4987b5622d31c5f0c07 Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Tue, 7 Aug 2018 09:52:55 -0700 Subject: [PATCH 6/6] runnableExamples: keep (gitignored) generated foo_examples.nim for inspection even on success (#8544) --- compiler/lineinfos.nim | 6 +++--- compiler/sem.nim | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler/lineinfos.nim b/compiler/lineinfos.nim index 261dcb44e2..4f0c3a7780 100644 --- a/compiler/lineinfos.nim +++ b/compiler/lineinfos.nim @@ -92,7 +92,7 @@ const warnResultShadowed: "Special variable 'result' is shadowed.", warnInconsistentSpacing: "Number of spaces around '$#' is not consistent", warnUser: "$1", - hintSuccess: "operation successful", + hintSuccess: "operation successful: $#", hintSuccessX: "operation successful ($# lines compiled; $# sec total; $#; $#)", hintCC: "CC: \'$1\'", # unused hintLineTooLong: "line too long", @@ -169,8 +169,8 @@ proc computeNotesVerbosity(): array[0..3, TNoteKinds] = result[1] = result[2] - {warnShadowIdent, warnProveField, warnProveIndex, warnGcUnsafe, hintPath, hintDependency, hintCodeBegin, hintCodeEnd, hintSource, hintGlobalVar, hintGCStats} - result[0] = result[1] - {hintSuccessX, hintConf, hintProcessing, - hintPattern, hintExecuting, hintLinking} + result[0] = result[1] - {hintSuccessX, hintSuccess, hintConf, + hintProcessing, hintPattern, hintExecuting, hintLinking} const NotesVerbosity* = computeNotesVerbosity() diff --git a/compiler/sem.nim b/compiler/sem.nim index 2c3fab5a58..5d6e546043 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -621,7 +621,8 @@ proc testExamples(c: PContext) = if os.execShellCmd(os.getAppFilename() & " " & backend & " --nimcache:" & nimcache & " -r " & outp) != 0: quit "[Examples] failed: see " & outp else: - removeFile(outp) + # keep generated source file `outp` to allow inspection. + rawMessage(c.config, hintSuccess, ["runnableExamples: " & outp]) removeFile(outp.changeFileExt(ExeExt)) try: removeDir(nimcache)