From 4e483bb01abf89b164e21c77003ead033fa92e08 Mon Sep 17 00:00:00 2001 From: pacien Date: Mon, 26 Nov 2018 12:58:43 +0100 Subject: [PATCH 001/110] add SinglyLinkedList.append procs --- lib/pure/collections/lists.nim | 15 +++++++++++++++ tests/stdlib/tlists.nim | 3 ++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/pure/collections/lists.nim b/lib/pure/collections/lists.nim index 0b3708a7c..15ce5d074 100644 --- a/lib/pure/collections/lists.nim +++ b/lib/pure/collections/lists.nim @@ -140,11 +140,26 @@ proc contains*[T](L: SomeLinkedCollection[T], value: T): bool {.inline.} = ## exist, true otherwise. result = find(L, value) != nil +proc append*[T](L: var SinglyLinkedList[T], + n: SinglyLinkedNode[T]) {.inline.} = + ## appends a node `n` to `L`. Efficiency: O(1). + n.next = nil + if L.tail != nil: + assert(L.tail.next == nil) + L.tail.next = n + L.tail = n + if L.head == nil: L.head = n + +proc append*[T](L: var SinglyLinkedList[T], value: T) {.inline.} = + ## appends a value to `L`. Efficiency: O(1). + append(L, newSinglyLinkedNode(value)) + proc prepend*[T](L: var SinglyLinkedList[T], n: SinglyLinkedNode[T]) {.inline.} = ## prepends a node to `L`. Efficiency: O(1). n.next = L.head L.head = n + if L.tail == nil: L.tail = n proc prepend*[T](L: var SinglyLinkedList[T], value: T) {.inline.} = ## prepends a node to `L`. Efficiency: O(1). diff --git a/tests/stdlib/tlists.nim b/tests/stdlib/tlists.nim index b7c7f9f5a..a288af781 100644 --- a/tests/stdlib/tlists.nim +++ b/tests/stdlib/tlists.nim @@ -10,7 +10,8 @@ const block SinglyLinkedListTest1: var L: SinglyLinkedList[int] for d in items(data): L.prepend(d) - assert($L == "[6, 5, 4, 3, 2, 1]") + for d in items(data): L.append(d) + assert($L == "[6, 5, 4, 3, 2, 1, 1, 2, 3, 4, 5, 6]") assert(4 in L) From 4b31d7bb83e2cfdeaab2500f83d0b6728310b549 Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Thu, 29 Nov 2018 23:33:48 +0000 Subject: [PATCH 002/110] move moves --- compiler/destroyer.nim | 191 ++++++++++++++++++--------- tests/destructor/tmove_objconstr.nim | 33 ++++- 2 files changed, 161 insertions(+), 63 deletions(-) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index 2d21a6019..8471d70d1 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -408,9 +408,12 @@ proc passCopyToSink(n: PNode; c: var Con): PNode = else: result.add newTree(nkAsgn, tmp, p(n, c)) result.add tmp - + proc pArg(arg: PNode; c: var Con; isSink: bool): PNode = - if isSink: + if arg.typ == nil: + # typ is nil if we are in if/case branch with noreturn + result = copyTree(arg) + elif isSink: if arg.kind in nkCallKinds: # recurse but skip the call expression in order to prevent # destructor injections: Rule 5.1 is different from rule 5.4! @@ -420,7 +423,7 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode = result.add arg[0] for i in 1.. 5: raise newException(ValueError, "new error") + else: newMySeq(x, 1.0), + b:0, + c: if y > 0: move(cc) else: newMySeq(1, 3.0)) let (seq1, seq2) = myfunc(2, 3) doAssert seq1.len == 2 @@ -122,4 +129,26 @@ doAssert seq3.len == 2 doAssert seq3[0] == 1.0 var seq4, seq5: MySeqNonCopyable -(seq4, i, seq5) = myfunc2(2, 3) \ No newline at end of file +(seq4, i, seq5) = myfunc2(2, 3) + +seq4 = block: + var tmp = newMySeq(4, 1.0) + tmp[0] = 3.0 + tmp + +doAssert seq4[0] == 3.0 + +import macros + +seq4 = + if i > 0: newMySeq(2, 5.0) + elif i < -100: raise newException(ValueError, "Parse Error") + else: newMySeq(2, 3.0) + +seq4 = + case (char) i: + of 'A', {'W'..'Z'}: newMySeq(2, 5.0) + of 'B': quit(-1) + else: + let (x1, x2, x3) = myfunc2(2, 3) + x3 \ No newline at end of file From 9bba790534be76c6b50033d54d061eb076f35d9d Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Thu, 29 Nov 2018 23:36:06 +0000 Subject: [PATCH 003/110] fix spacing --- compiler/destroyer.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index 8471d70d1..b3ec6d510 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -408,7 +408,7 @@ proc passCopyToSink(n: PNode; c: var Con): PNode = else: result.add newTree(nkAsgn, tmp, p(n, c)) result.add tmp - + proc pArg(arg: PNode; c: var Con; isSink: bool): PNode = if arg.typ == nil: # typ is nil if we are in if/case branch with noreturn From c0b91bc02457158505a690e1e7bf87b185484f4d Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Thu, 29 Nov 2018 23:43:19 +0000 Subject: [PATCH 004/110] revert debug statements --- compiler/destroyer.nim | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index ca17057b5..b81f6c0fc 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -632,7 +632,7 @@ proc p(n: PNode; c: var Con): PNode = recurse(n, result) proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode = - when true: # defined(nimDebugDestroys): + when false: # defined(nimDebugDestroys): echo "injecting into ", n var c: Con c.owner = owner @@ -668,7 +668,8 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode = else: result.add body - when true: - echo "------------------------------------" - echo owner.name.s, " transformed to: " - echo result + when defined(nimDebugDestroys): + if true: + echo "------------------------------------" + echo owner.name.s, " transformed to: " + echo result From e90f70af423caa6ffa9b5dd3c59b38c85a9a3f03 Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Fri, 30 Nov 2018 09:36:04 +0000 Subject: [PATCH 005/110] Improve approach --- compiler/destroyer.nim | 45 +++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index b81f6c0fc..ee930018a 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -411,10 +411,12 @@ proc passCopyToSink(n: PNode; c: var Con): PNode = result.add tmp proc pArg(arg: PNode; c: var Con; isSink: bool): PNode = - if arg.typ == nil: - # typ is nil if we are in if/case branch with noreturn - result = copyTree(arg) - elif isSink: + template pArgIfTyped(arg_part: PNode): PNode = + # typ is nil if we are in if/case expr branch with noreturn + if arg_part.typ == nil: copyTree(arg_part) + else: pArg(arg_part, c, isSink) + + if isSink: if arg.kind in nkCallKinds: # recurse but skip the call expression in order to prevent # destructor injections: Rule 5.1 is different from rule 5.4! @@ -446,9 +448,9 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode = var branch = copyNode(arg[i]) if arg[i].kind in {nkElifBranch, nkElifExpr}: branch.add p(arg[i][0], c) - branch.add pArg(arg[i][1], c, isSink) + branch.add pArgIfTyped(arg[i][1]) else: - branch.add pArg(arg[i][0], c, isSink) + branch.add pArgIfTyped(arg[i][0]) result.add branch elif arg.kind == nkCaseStmt: result = copyNode(arg) @@ -457,14 +459,14 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode = var branch: PNode if arg[i].kind == nkOfbranch: branch = arg[i] # of branch conditions are constants - branch[^1] = pArg(arg[i][^1], c, isSink) + branch[^1] = pArgIfTyped(arg[i][^1]) elif arg[i].kind in {nkElifBranch, nkElifExpr}: branch = copyNode(arg[i]) branch.add p(arg[i][0], c) - branch.add pArg(arg[i][1], c, isSink) + branch.add pArgIfTyped(arg[i][1]) else: branch = copyNode(arg[i]) - branch.add pArg(arg[i][0], c, isSink) + branch.add pArgIfTyped(arg[i][0]) result.add branch else: # an object that is not temporary but passed to a 'sink' parameter @@ -474,11 +476,12 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode = result = p(arg, c) proc moveOrCopy(dest, ri: PNode; c: var Con): PNode = - if ri.typ == nil: - # typ is nil if we are in if/case branch with noreturn - result = copyTree(ri) - else: - case ri.kind + template moveOrCopyIfTyped(ri_part: PNode): PNode = + # typ is nil if we are in if/case expr branch with noreturn + if ri_part.typ == nil: copyTree(ri_part) + else: moveOrCopy(dest, ri_part, c) + + case ri.kind of nkCallKinds: result = genSink(c, dest.typ, dest, ri) # watch out and no not transform 'ri' twice if it's a call: @@ -505,18 +508,16 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode = of nkBlockExpr, nkBlockStmt: result = newNodeI(nkBlockStmt, ri.info) result.add ri[0] ## add label - for i in 1..ri.len-2: - result.add p(ri[i], c) - result.add moveOrCopy(dest, ri[^1], c) + result.add moveOrCopy(dest, ri[1], c) of nkIfExpr, nkIfStmt: result = newNodeI(nkIfStmt, ri.info) for i in 0.. Date: Fri, 30 Nov 2018 09:37:26 +0000 Subject: [PATCH 006/110] reduce changes --- compiler/destroyer.nim | 160 ++++++++++++++++++++--------------------- 1 file changed, 80 insertions(+), 80 deletions(-) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index ee930018a..a4bed4674 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -482,93 +482,93 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode = else: moveOrCopy(dest, ri_part, c) case ri.kind - of nkCallKinds: + of nkCallKinds: + result = genSink(c, dest.typ, dest, ri) + # watch out and no not transform 'ri' twice if it's a call: + let ri2 = copyNode(ri) + let parameters = ri[0].typ + let L = if parameters != nil: parameters.len else: 0 + ri2.add ri[0] + for i in 1.. Date: Fri, 30 Nov 2018 09:47:55 +0000 Subject: [PATCH 007/110] add array constructors --- compiler/destroyer.nim | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index a4bed4674..a26a4d379 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -426,7 +426,7 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode = result.add arg[0] for i in 1.. Date: Wed, 5 Dec 2018 19:29:14 +0000 Subject: [PATCH 008/110] add test --- compiler/destroyer.nim | 33 ++++++++++++++++------------ tests/destructor/tmove_objconstr.nim | 11 +++++++++- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index a26a4d379..352b4aaad 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -413,7 +413,7 @@ proc passCopyToSink(n: PNode; c: var Con): PNode = proc pArg(arg: PNode; c: var Con; isSink: bool): PNode = template pArgIfTyped(arg_part: PNode): PNode = # typ is nil if we are in if/case expr branch with noreturn - if arg_part.typ == nil: copyTree(arg_part) + if arg_part.typ == nil: p(arg_part, c) else: pArg(arg_part, c, isSink) if isSink: @@ -478,7 +478,7 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode = proc moveOrCopy(dest, ri: PNode; c: var Con): PNode = template moveOrCopyIfTyped(ri_part: PNode): PNode = # typ is nil if we are in if/case expr branch with noreturn - if ri_part.typ == nil: copyTree(ri_part) + if ri_part.typ == nil: p(ri_part, c) else: moveOrCopy(dest, ri_part, c) case ri.kind @@ -537,29 +537,32 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode = result.add branch of nkBracket: # array constructor + result = genSink(c, dest.typ, dest, ri) let ri2 = copyTree(ri) for i in 0.. 1: newMySeq(3, 1.0) else: newMySeq(0, 0.0)] +var seqOfSeq2 = @[newMySeq(2, 5.0), newMySeq(3, 1.0)] \ No newline at end of file From 69347f6c95b35e8969cf650b59644b20ef1528de Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Wed, 5 Dec 2018 21:33:15 +0000 Subject: [PATCH 009/110] implement everything --- compiler/ast.nim | 2 +- compiler/ccgexprs.nim | 8 --- compiler/destroyer.nim | 101 ++++++++++++++------------------ compiler/semexprs.nim | 3 +- lib/pure/collections/tables.nim | 46 +++++++++++++++ 5 files changed, 93 insertions(+), 67 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index 7cf35450b..2b595aee1 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -627,7 +627,7 @@ type mIsPartOf, mAstToStr, mParallel, mSwap, mIsNil, mArrToSeq, mCopyStr, mCopyStrLast, mNewString, mNewStringOfCap, mParseBiggestFloat, - mMove, mWasMoved, mDestroy, + mMove, mDestroy, mReset, mArray, mOpenArray, mRange, mSet, mSeq, mOpt, mVarargs, mRef, mPtr, mVar, mDistinct, mVoid, mTuple, diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 34836d843..bf1494b3d 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -1901,13 +1901,6 @@ proc binaryFloatArith(p: BProc, e: PNode, d: var TLoc, m: TMagic) = proc skipAddr(n: PNode): PNode = result = if n.kind in {nkAddr, nkHiddenAddr}: n[0] else: n -proc genWasMoved(p: BProc; n: PNode) = - var a: TLoc - initLocExpr(p, n[1].skipAddr, a) - resetLoc(p, a) - #linefmt(p, cpsStmts, "#nimZeroMem((void*)$1, sizeof($2));$n", - # addrLoc(p.config, a), getTypeDesc(p.module, a.t)) - proc genMove(p: BProc; n: PNode; d: var TLoc) = if d.k == locNone: getTemp(p, n.typ, d) var a: TLoc @@ -2046,7 +2039,6 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = initLocExpr(p, e.sons[2], b) genDeepCopy(p, a, b) of mDotDot, mEqCString: genCall(p, e, d) - of mWasMoved: genWasMoved(p, e) of mMove: genMove(p, e, d) of mDestroy: discard "ignore calls to the default destructor" of mSlice: diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index 352b4aaad..4703c31dd 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -100,12 +100,12 @@ Rule Pattern Transformed into finally: `=destroy`(x) 1.2 var x: sink T; stmts var x: sink T; stmts; ensureEmpty(x) 2 x = f() `=sink`(x, f()) -3 x = lastReadOf z `=sink`(x, z); wasMoved(z) +3 x = lastReadOf z `=sink`(x, z); 4.1 y = sinkParam `=sink`(y, sinkParam) 4.2 x = y `=`(x, y) # a copy 5.1 f_sink(g()) f_sink(g()) 5.2 f_sink(y) f_sink(copy y); # copy unless we can see it's the last read -5.3 f_sink(move y) f_sink(y); wasMoved(y) # explicit moves empties 'y' +5.3 f_sink(move y) f_sink(y); # explicit moves empties 'y' 5.4 f_noSink(g()) var tmp = bitwiseCopy(g()); f(tmp); `=destroy`(tmp) Remarks: Rule 1.2 is not yet implemented because ``sink`` is currently @@ -116,7 +116,7 @@ Remarks: Rule 1.2 is not yet implemented because ``sink`` is currently import intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees, - strutils, options, dfa, lowerings, tables, modulegraphs, + strutils, options, dfa, lowerings, tables, modulegraphs, msgs, lineinfos, parampatterns const @@ -127,20 +127,13 @@ type owner: PSym g: ControlFlowGraph jumpTargets: IntSet - tmpObj: PType - tmp: PSym - destroys, topLevelVars: PNode + topLevelVars: PNode + destroys: OrderedTable[int, tuple[enabled: bool, destroy_call: PNode]] # Symbol to destructor table toDropBit: Table[int, PSym] graph: ModuleGraph emptyNode: PNode otherRead: PNode -proc getTemp(c: var Con; typ: PType; info: TLineInfo): PNode = - # XXX why are temps fields in an object here? - let f = newSym(skField, getIdent(c.graph.cache, ":d" & $c.tmpObj.n.len), c.owner, info) - f.typ = typ - rawAddField c.tmpObj, f - result = rawDirectAccess(c.tmp, f) proc isHarmlessVar*(s: PSym; c: Con): bool = # 's' is harmless if it used only once and its @@ -333,6 +326,22 @@ proc dropBit(c: var Con; s: PSym): PSym = result = c.toDropBit.getOrDefault(s.id) assert result != nil +proc addDestructor(c: var Con; s: PSym; destructor_call: PNode) = + let alreadyIn = c.destroys.hasKeyOrPut(s.id, (true, destructor_call)) + if alreadyIn: + let lineInfo = if s.ast != nil: s.ast.info else: c.owner.info + internalError(c.graph.config, lineInfo, "Destructor call for sym " & s.name.s & " is already injected") + +proc disableDestructor(c: var Con; s: PSym) = + ## disable destructor, but do not delete such that it can be enabled back again later + c.destroys.with_value(s.id, value): + value.enabled = false + +proc enableDestructor(c: var Con; s: PSym) = + ## if destructor does not exist then ignore, otherwise make sure destructor is enabled + c.destroys.with_value(s.id, value): + value.enabled = true + proc registerDropBit(c: var Con; s: PSym) = let result = newSym(skTemp, getIdent(c.graph.cache, s.name.s & "_AliveBit"), c.owner, s.info) result.typ = getSysType(c.graph, s.info, tyBool) @@ -343,8 +352,14 @@ proc registerDropBit(c: var Con; s: PSym) = # if not sinkParam_AliveBit: `=destroy`(sinkParam) let t = s.typ.skipTypes({tyGenericInst, tyAlias, tySink}) if t.destructor != nil: - c.destroys.add newTree(nkIfStmt, - newTree(nkElifBranch, newSymNode result, genDestroy(c, t, newSymNode s))) + c.addDestructor(s, newTree(nkIfStmt, + newTree(nkElifBranch, newSymNode result, genDestroy(c, t, newSymNode s)))) + +proc getTemp(c: var Con; typ: PType; info: TLineInfo): PNode = + let sym = newSym(skTemp, getIdent(c.graph.cache, ":tmpD"), c.owner, info) + sym.typ = typ + result = newSymNode(sym) + c.addTopVar(result) proc p(n: PNode; c: var Con): PNode @@ -370,31 +385,6 @@ proc genMagicCall(n: PNode; c: var Con; magicname: string; m: TMagic): PNode = result.add(newSymNode(createMagic(c.graph, magicname, m))) result.add n -proc genWasMoved(n: PNode; c: var Con): PNode = - # The mWasMoved builtin does not take the address. - result = genMagicCall(n, c, "wasMoved", mWasMoved) - -proc destructiveMoveVar(n: PNode; c: var Con): PNode = - # generate: (let tmp = v; reset(v); tmp) - # XXX: Strictly speaking we can only move if there is a ``=sink`` defined - # or if no ``=sink`` is defined and also no assignment. - result = newNodeIT(nkStmtListExpr, n.info, n.typ) - - var temp = newSym(skLet, getIdent(c.graph.cache, "blitTmp"), c.owner, n.info) - temp.typ = n.typ - var v = newNodeI(nkLetSection, n.info) - let tempAsNode = newSymNode(temp) - - var vpart = newNodeI(nkIdentDefs, tempAsNode.info, 3) - vpart.sons[0] = tempAsNode - vpart.sons[1] = c.emptyNode - vpart.sons[2] = n - add(v, vpart) - - result.add v - result.add genWasMoved(n, c) - result.add tempAsNode - proc passCopyToSink(n: PNode; c: var Con): PNode = result = newNodeIT(nkStmtListExpr, n.info, n.typ) let tmp = getTemp(c, n.typ, n.info) @@ -415,7 +405,7 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode = # typ is nil if we are in if/case expr branch with noreturn if arg_part.typ == nil: p(arg_part, c) else: pArg(arg_part, c, isSink) - + if isSink: if arg.kind in nkCallKinds: # recurse but skip the call expression in order to prevent @@ -431,9 +421,9 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode = result = arg elif arg.kind == nkSym and arg.sym.kind in InterestingSyms and isLastRead(arg, c): # if x is a variable and it its last read we eliminate its - # destructor invokation, but don't. We need to reset its memory - # to disable its destructor which we have not elided: - result = destructiveMoveVar(arg, c) + # destructor invocation + c.disableDestructor(arg.sym) + result = arg elif arg.kind == nkSym and isSinkParam(arg.sym): # mark the sink parameter as used: result = destructiveMoveSink(arg, c) @@ -566,9 +556,8 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode = of nkSym: if ri.sym.kind != skParam and isLastRead(ri, c): # Rule 3: `=sink`(x, z); wasMoved(z) - var snk = genSink(c, dest.typ, dest, ri) - snk.add p(ri, c) - result = newTree(nkStmtList, snk, genMagicCall(ri, c, "wasMoved", mWasMoved)) + result = genSink(c, dest.typ, dest, ri) + result.add p(ri, c) elif isSinkParam(ri.sym): result = genSink(c, dest.typ, dest, ri) result.add destructiveMoveSink(ri, c) @@ -599,7 +588,7 @@ proc p(n: PNode; c: var Con): PNode = # move the variable declaration to the top of the frame: c.addTopVar v # make sure it's destroyed at the end of the proc: - c.destroys.add genDestroy(c, v.typ, v) + c.addDestructor(v.sym, genDestroy(c, v.typ, v)) if ri.kind != nkEmpty: let r = moveOrCopy(v, ri, c) result.add r @@ -625,12 +614,13 @@ proc p(n: PNode; c: var Con): PNode = sinkExpr.add n result.add sinkExpr result.add tmp - c.destroys.add genDestroy(c, n.typ, tmp) + c.addDestructor(tmp.sym, genDestroy(c, n.typ, tmp)) else: result = n of nkAsgn, nkFastAsgn: if hasDestructor(n[0].typ): result = moveOrCopy(n[0], n[1], c) + c.enableDestructor(n[0].sym) else: result = copyNode(n) recurse(n, result) @@ -646,12 +636,9 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode = # echo "injecting into ", n var c: Con c.owner = owner - c.tmp = newSym(skTemp, getIdent(g.cache, ":d"), owner, n.info) - c.tmpObj = createObj(g, owner, n.info) - c.tmp.typ = c.tmpObj - c.destroys = newNodeI(nkStmtList, n.info) c.topLevelVars = newNodeI(nkVarSection, n.info) - c.toDropBit = initTable[int, PSym]() + c.toDropBit = initTable[int, PSym](16) + c.destroys = initOrderedTable[int, (bool, PNode)](16) c.graph = g c.emptyNode = newNodeI(nkEmpty, n.info) let cfg = constructCfg(owner, n) @@ -668,13 +655,15 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode = let param = params[i].sym if param.typ.kind == tySink: registerDropBit(c, param) let body = p(n, c) - if c.tmp.typ.n.len > 0: - c.addTopVar(newSymNode c.tmp) result = newNodeI(nkStmtList, n.info) if c.topLevelVars.len > 0: result.add c.topLevelVars if c.destroys.len > 0: - result.add newTryFinally(body, c.destroys) + var destroy_list = newNodeI(nkStmtList, n.info) + for val in c.destroys.values: + if val.enabled: + destroy_list.add val.destroy_call + result.add newTryFinally(body, destroy_list) else: result.add body diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 669862c56..517356434 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -614,8 +614,7 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) = const FakeVarParams = {mNew, mNewFinalize, mInc, ast.mDec, mIncl, mExcl, mSetLengthStr, mSetLengthSeq, mAppendStrCh, mAppendStrStr, mSwap, - mAppendSeqElem, mNewSeq, mReset, mShallowCopy, mDeepCopy, mMove, - mWasMoved} + mAppendSeqElem, mNewSeq, mReset, mShallowCopy, mDeepCopy, mMove} # get the real type of the callee # it may be a proc var with a generic alias type, so we skip over them diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim index f46a368b1..9597d18fd 100644 --- a/lib/pure/collections/tables.nim +++ b/lib/pure/collections/tables.nim @@ -248,6 +248,7 @@ template withValue*[A, B](t: var Table[A, B], key: A, else: body2 + iterator allValues*[A, B](t: Table[A, B]; key: A): B = ## iterates over any value in the table ``t`` that belongs to the given ``key``. var h: Hash = genHash(key) and high(t.data) @@ -879,6 +880,51 @@ proc del*[A, B](t: var OrderedTableRef[A, B], key: A) = ## if the key does not exist. t[].del(key) + +template withValue*[A, B](t: var OrderedTable[A, B], key: A, value, body: untyped) = + ## retrieves the value at ``t[key]``. + ## ``value`` can be modified in the scope of the ``withValue`` call. + ## + ## .. code-block:: nim + ## + ## orderedTable.withValue(key, value) do: + ## # block is executed only if ``key`` in ``t`` + ## value.name = "username" + ## value.uid = 1000 + ## + mixin rawGet + var hc: Hash + var index = rawGet(t, key, hc) + let hasKey = index >= 0 + if hasKey: + var value {.inject.} = addr(t.data[index].val) + body + +template withValue*[A, B](t: var OrderedTable[A, B], key: A, + value, body1, body2: untyped) = + ## retrieves the value at ``t[key]``. + ## ``value`` can be modified in the scope of the ``withValue`` call. + ## + ## .. code-block:: nim + ## + ## orderedTable.withValue(key, value) do: + ## # block is executed only if ``key`` in ``t`` + ## value.name = "username" + ## value.uid = 1000 + ## do: + ## # block is executed when ``key`` not in ``t`` + ## raise newException(KeyError, "Key not found") + ## + mixin rawGet + var hc: Hash + var index = rawGet(t, key, hc) + let hasKey = index >= 0 + if hasKey: + var value {.inject.} = addr(t.data[index].val) + body1 + else: + body2 + # ------------------------------ count tables ------------------------------- type From f46573c1ed9f041d23a54d0911d7727d84c1a9cd Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Wed, 5 Dec 2018 21:36:42 +0000 Subject: [PATCH 010/110] remove debug statements --- compiler/destroyer.nim | 18 +++++++++--------- lib/system.nim | 7 +------ 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index 4703c31dd..82db5af7f 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -632,8 +632,8 @@ proc p(n: PNode; c: var Con): PNode = recurse(n, result) proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode = - #when true: # defined(nimDebugDestroys): - # echo "injecting into ", n + when false: # defined(nimDebugDestroys): + echo "injecting into ", n var c: Con c.owner = owner c.topLevelVars = newNodeI(nkVarSection, n.info) @@ -667,10 +667,10 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode = else: result.add body - #when defined(nimDebugDestroys): - if true: - echo "------------------------------------" - echo n - echo "-------" - echo owner.name.s, " transformed to: " - echo result + when defined(nimDebugDestroys): + if true: + echo "------------------------------------" + echo n + echo "-------" + echo owner.name.s, " transformed to: " + echo result diff --git a/lib/system.nim b/lib/system.nim index 9111ddd86..ec0dd629c 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -221,15 +221,10 @@ proc reset*[T](obj: var T) {.magic: "Reset", noSideEffect.} ## be called before any possible `object branch transition`:idx:. when defined(nimNewRuntime): - proc wasMoved*[T](obj: var T) {.magic: "WasMoved", noSideEffect.} = - ## resets an object `obj` to its initial (binary zero) value to signify - ## it was "moved" and to signify its destructor should do nothing and - ## ideally be optimized away. - discard proc move*[T](x: var T): T {.magic: "Move", noSideEffect.} = result = x - wasMoved(x) + reset(x) type range*{.magic: "Range".}[T] ## Generic type to construct range types. From 972707440ad0837d3de11cc6d60abbd3dc7ace75 Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Wed, 5 Dec 2018 21:37:27 +0000 Subject: [PATCH 011/110] remove debug --- compiler/destroyer.nim | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index 82db5af7f..59ee5dcb6 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -670,7 +670,5 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode = when defined(nimDebugDestroys): if true: echo "------------------------------------" - echo n - echo "-------" echo owner.name.s, " transformed to: " echo result From 268461f06ea8b03c1b72c25163418076df22b88d Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Wed, 5 Dec 2018 21:45:01 +0000 Subject: [PATCH 012/110] add comment --- compiler/destroyer.nim | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index 59ee5dcb6..3811cccad 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -620,7 +620,8 @@ proc p(n: PNode; c: var Con): PNode = of nkAsgn, nkFastAsgn: if hasDestructor(n[0].typ): result = moveOrCopy(n[0], n[1], c) - c.enableDestructor(n[0].sym) + c.enableDestructor(n[0].sym) # last read to sink argument could have disabled the destructor + # but the variable is assigned again and new value should be destroyed else: result = copyNode(n) recurse(n, result) From 135191d9d661581db06a00f4396c024a8fd3a537 Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Wed, 5 Dec 2018 22:17:19 +0000 Subject: [PATCH 013/110] collapse to tables into one --- compiler/destroyer.nim | 16 +++++++--------- lib/pure/collections/tables.nim | 1 - 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index 3811cccad..56f941514 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -128,8 +128,8 @@ type g: ControlFlowGraph jumpTargets: IntSet topLevelVars: PNode - destroys: OrderedTable[int, tuple[enabled: bool, destroy_call: PNode]] # Symbol to destructor table - toDropBit: Table[int, PSym] + destroys: OrderedTable[int, tuple[enabled: bool, dropBit: PSym, destroy_call: PNode]] + # Symbol to destructor call table graph: ModuleGraph emptyNode: PNode otherRead: PNode @@ -323,11 +323,11 @@ proc addTopVar(c: var Con; v: PNode) = c.topLevelVars.add newTree(nkIdentDefs, v, c.emptyNode, c.emptyNode) proc dropBit(c: var Con; s: PSym): PSym = - result = c.toDropBit.getOrDefault(s.id) + result = c.destroys.getOrDefault(s.id).dropBit assert result != nil -proc addDestructor(c: var Con; s: PSym; destructor_call: PNode) = - let alreadyIn = c.destroys.hasKeyOrPut(s.id, (true, destructor_call)) +proc addDestructor(c: var Con; s: PSym; destructor_call: PNode, dropBit: PSym = nil) = + let alreadyIn = c.destroys.hasKeyOrPut(s.id, (true, dropBit, destructor_call)) if alreadyIn: let lineInfo = if s.ast != nil: s.ast.info else: c.owner.info internalError(c.graph.config, lineInfo, "Destructor call for sym " & s.name.s & " is already injected") @@ -347,13 +347,12 @@ proc registerDropBit(c: var Con; s: PSym) = result.typ = getSysType(c.graph, s.info, tyBool) let trueVal = newIntTypeNode(nkIntLit, 1, result.typ) c.topLevelVars.add newTree(nkIdentDefs, newSymNode result, c.emptyNode, trueVal) - c.toDropBit[s.id] = result # generate: # if not sinkParam_AliveBit: `=destroy`(sinkParam) let t = s.typ.skipTypes({tyGenericInst, tyAlias, tySink}) if t.destructor != nil: c.addDestructor(s, newTree(nkIfStmt, - newTree(nkElifBranch, newSymNode result, genDestroy(c, t, newSymNode s)))) + newTree(nkElifBranch, newSymNode result, genDestroy(c, t, newSymNode s))), result) proc getTemp(c: var Con; typ: PType; info: TLineInfo): PNode = let sym = newSym(skTemp, getIdent(c.graph.cache, ":tmpD"), c.owner, info) @@ -638,8 +637,7 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode = var c: Con c.owner = owner c.topLevelVars = newNodeI(nkVarSection, n.info) - c.toDropBit = initTable[int, PSym](16) - c.destroys = initOrderedTable[int, (bool, PNode)](16) + c.destroys = initOrderedTable[int, (bool, PSym, PNode)](16) c.graph = g c.emptyNode = newNodeI(nkEmpty, n.info) let cfg = constructCfg(owner, n) diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim index 9597d18fd..ce87deea0 100644 --- a/lib/pure/collections/tables.nim +++ b/lib/pure/collections/tables.nim @@ -248,7 +248,6 @@ template withValue*[A, B](t: var Table[A, B], key: A, else: body2 - iterator allValues*[A, B](t: Table[A, B]; key: A): B = ## iterates over any value in the table ``t`` that belongs to the given ``key``. var h: Hash = genHash(key) and high(t.data) From 43ea41bdf4626831116568b0b19e665a41c3f98b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arne=20D=C3=B6ring?= Date: Fri, 7 Dec 2018 16:21:50 +0100 Subject: [PATCH 014/110] added lib/std/diff.nim --- lib/std/diff.nim | 463 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 463 insertions(+) create mode 100644 lib/std/diff.nim diff --git a/lib/std/diff.nim b/lib/std/diff.nim new file mode 100644 index 000000000..940b5888d --- /dev/null +++ b/lib/std/diff.nim @@ -0,0 +1,463 @@ + +## This Class implements the Difference Algorithm published in +## "An O(ND) Difference Algorithm and its Variations" by Eugene Myers +## Algorithmica Vol. 1 No. 2, 1986, p 251. +## +## There are many C, Java, Lisp implementations public available but they all seem to come +## from the same source (diffutils) that is under the (unfree) GNU public License +## and cannot be reused as a sourcecode for a commercial application. +## There are very old C implementations that use other (worse) algorithms. +## Microsoft also published sourcecode of a diff-tool (windiff) that uses some tree data. +## Also, a direct transfer from a C source to C# is not easy because there is a lot of pointer +## arithmetic in the typical C solutions and i need a managed solution. +## These are the reasons why I implemented the original published algorithm from the scratch and +## make it avaliable without the GNU license limitations. +## I do not need a high performance diff tool because it is used only sometimes. +## I will do some performace tweaking when needed. +## +## The algorithm itself is comparing 2 arrays of numbers so when comparing 2 text documents +## each line is converted into a (hash) number. See diffText(). +## +## Some chages to the original algorithm: +## The original algorithm was described using a recursive approach and comparing zero indexed arrays. +## Extracting sub-arrays and rejoining them is very performance and memory intensive so the same +## (readonly) data arrays are passed arround together with their lower and upper bounds. +## This circumstance makes the lcs and sms functions more complicate. +## I added some code to the lcs function to get a fast response on sub-arrays that are identical, +## completely deleted or inserted. +## +## The result from a comparisation is stored in 2 arrays that flag for modified (deleted or inserted) +## lines in the 2 data arrays. These bits are then analysed to produce a array of Item objects. +## +## Further possible optimizations: +## (first rule: don't do it; second: don't do it yet) +## The arrays dataA and dataB are passed as parameters, but are never changed after the creation +## so they can be members of the class to avoid the paramter overhead. +## In sms is a lot of boundary arithmetic in the for-D and for-k loops that can be done by increment +## and decrement of local variables. +## The downVector and upVector arrays are alywas created and destroyed each time the sms gets called. +## It is possible to reuse tehm when transfering them to members of the class. +## See TODO: hints. +## +## diff.cs: A port of the algorythm to C# +## Copyright (c) by Matthias Hertel, http://www.mathertel.de +## This work is licensed under a BSD style license. See http://www.mathertel.de/License.aspx +## +## Changes: +## 2002.09.20 There was a "hang" in some situations. +## Now I undestand a little bit more of the sms algorithm. +## There have been overlapping boxes; that where analyzed partial differently. +## One return-point is enough. +## A assertion was added in createDiffs when in debug-mode, that counts the number of equal (no modified) lines in both arrays. +## They must be identical. +## +## 2003.02.07 Out of bounds error in the Up/Down vector arrays in some situations. +## The two vetors are now accessed using different offsets that are adjusted using the start k-Line. +## A test case is added. +## +## 2006.03.05 Some documentation and a direct Diff entry point. +## +## 2006.03.08 Refactored the API to static methods on the Diff class to make usage simpler. +## 2006.03.10 using the standard Debug class for self-test now. +## compile with: csc /target:exe /out:diffTest.exe /d:DEBUG /d:TRACE /d:SELFTEST Diff.cs +## 2007.01.06 license agreement changed to a BSD style license. +## 2007.06.03 added the optimize method. +## 2007.09.23 upVector and downVector optimization by Jan Stoklasa (). +## 2008.05.31 Adjusted the testing code that failed because of the optimize method (not a bug in the diff algorithm). +## 2008.10.08 Fixing a test case and adding a new test case. +## 2018.12.07 Port to Nim. + +import tables, strutils + +type + Item* = object + startA*: int ## Start Line number in Data A. + startB*: int ## Start Line number in Data B. + deletedA*: int ## Number of changes in Data A. + insertedB*: int ## Number of changes in Data B. + + DiffData = object + ## Data on one input file being compared. + len: int ## Number of elements (lines). + data: seq[int] ## Buffer of numbers that will be compared. + modified: seq[bool] ## Array of booleans that flag for modified + ## data. This is the result of the diff. + ## This means deletedA in the first Data or + ## inserted in the second Data. + + SMSRD = object + x,y: int + +proc newDiffData(initData: seq[int]): DiffData = + ## Initialize the Diff-Data buffer. + result.len = initData.len + result.data = initData + result.modified = newSeq[bool](result.len + 2) + +proc diffCodes(aText: string; h: var Table[string,int]): seq[int] = + ## This function converts all textlines of the text into unique numbers for every unique textline + ## so further work can work only with simple numbers. + ## ``aText`` the input text + ## ``h`` This extern initialized hashtable is used for storing all ever used textlines. + ## ``trimSpace`` ignore leading and trailing space characters + ## Returns a array of integers. + + # get all codes of the text + var lastUsedCode = h.len + var codes = newSeq[int]() + for s in aText.splitLines: + if h.contains s: + codes.add h[s] + else: + inc lastUsedCode + h[s] = lastUsedCode + codes.add lastUsedCode + + return codes + +proc optimize(data: var DiffData): void = + ## If a sequence of modified lines starts with a line that contains the same content + ## as the line that appends the changes, the difference sequence is modified so that the + ## appended line and not the starting line is marked as modified. + ## This leads to more readable diff sequences when comparing text files. + ## ``data`` A Diff data buffer containing the identified changes. + + var startPos, endPos: int + startPos = 0 + + while startPos < data.len: + while (startPos < data.len) and (data.modified[startPos] == false): + inc startPos + endPos = startPos + while (endPos < data.len) and (data.modified[endPos] == true): + inc endPos + + if (endPos < data.len) and (data.data[startPos] == data.data[endPos]): + data.modified[startPos] = false + data.modified[endPos] = true + else: + startPos = endPos + +proc sms(dataA: var DiffData; lowerA, upperA: int; dataB: DiffData; lowerB, upperB: int; + downVector, upVector: var openArray[int]): SMSRD = + ## This is the algorithm to find the Shortest Middle Snake (sms). + ## ``dataA`` sequence A + ## ``lowerA`` lower bound of the actual range in dataA + ## ``upperA`` upper bound of the actual range in dataA (exclusive) + ## ``dataB`` sequence B + ## ``lowerB`` lower bound of the actual range in dataB + ## ``upperB`` upper bound of the actual range in dataB (exclusive) + ## ``downVector`` a vector for the (0,0) to (x,y) search. Passed as a parameter for speed reasons. + ## ``upVector`` a vector for the (u,v) to (N,M) search. Passed as a parameter for speed reasons. + ## Returns a MiddleSnakeData record containing x,y and u,v. + + let max: int = dataA.len + dataB.len + 1 + + let downK = lowerA - lowerB; # the k-line to start the forward search + let upK = upperA - upperB; # the k-line to start the reverse search + + let delta = (upperA - lowerA) - (upperB - lowerB) + let oddDelta = (delta and 1) != 0 + + # The vectors in the publication accepts negative indexes. the vectors implemented here are 0-based + # and are access using a specific offset: upOffset upVector and downOffset for downVector + let downOffset = max - downK + let upOffset = max - upK + + let maxD = ((upperA - lowerA + upperB - lowerB) div 2) + 1 + + # Debug.Write(2, "sms", String.Format("Search the box: A[{0}-{1}] to B[{2}-{3}]", lowerA, upperA, lowerB, upperB)) + + # init vectors + downVector[downOffset + downK + 1] = lowerA + upVector[upOffset + upK - 1] = upperA + + for D in 0 .. maxD: + + # Extend the forward path. + + for k in countUp(downK - D, downK + D, 2): + # Debug.Write(0, "sms", "extend forward path " + k.ToString()) + + # find the only or better starting point + var x, y: int + if k == downK - D: + x = downVector[downOffset + k + 1]; # down + else: + x = downVector[downOffset + k - 1] + 1; # a step to the right + if (k < downK + D) and (downVector[downOffset + k + 1] >= x): + x = downVector[downOffset + k + 1]; # down + + y = x - k + + # find the end of the furthest reaching forward D-path in diagonal k. + while (x < upperA) and (y < upperB) and (dataA.data[x] == dataB.data[y]): + inc x + inc y + + downVector[downOffset + k] = x + + # overlap ? + if oddDelta and (upK - D < k) and (k < upK + D): + if upVector[upOffset + k] <= downVector[downOffset + k]: + result.x = downVector[downOffset + k] + result.y = downVector[downOffset + k] - k + return + + # Extend the reverse path. + for k in countUp(upK - D, upK + D, 2): + # Debug.Write(0, "sms", "extend reverse path " + k.ToString()) + + # find the only or better starting point + var x, y: int + if k == upK + D: + x = upVector[upOffset + k - 1]; # up + else: + x = upVector[upOffset + k + 1] - 1; # left + if (k > upK - D) and (upVector[upOffset + k - 1] < x): + x = upVector[upOffset + k - 1]; # up + # if + y = x - k + + while (x > lowerA) and (y > lowerB) and (dataA.data[x - 1] == dataB.data[y - 1]): + dec x + dec y + + upVector[upOffset + k] = x + + # overlap ? + if (not oddDelta) and (downK - D <= k) and (k <= downK + D): + if upVector[upOffset + k] <= downVector[downOffset + k]: + result.x = downVector[downOffset + k] + result.y = downVector[downOffset + k] - k + return + + assert false, "the algorithm should never come here." + +proc lcs(dataA: var DiffData; lowerA, upperA: int; dataB: var DiffData; lowerB, upperB: int; downVector, upVector: var openArray[int]): void = + ## This is the divide-and-conquer implementation of the longes common-subsequence (lcs) + ## algorithm. + ## The published algorithm passes recursively parts of the A and B sequences. + ## To avoid copying these arrays the lower and upper bounds are passed while the sequences stay constant. + ## ``dataA`` sequence A + ## ``lowerA`` lower bound of the actual range in dataA + ## ``upperA`` upper bound of the actual range in dataA (exclusive) + ## ``dataB`` sequence B + ## ``lowerB`` lower bound of the actual range in dataB + ## ``upperB`` upper bound of the actual range in dataB (exclusive) + ## ``downVector`` a vector for the (0,0) to (x,y) search. Passed as a parameter for speed reasons. + ## ``upVector`` a vector for the (u,v) to (N,M) search. Passed as a parameter for speed reasons. + # make mutable copy + var lowerA = lowerA + var lowerB = lowerB + var upperA = upperA + var upperB = upperB + + # Debug.Write(2, "lcs", String.Format("Analyse the box: A[{0}-{1}] to B[{2}-{3}]", lowerA, upperA, lowerB, upperB)) + + # Fast walkthrough equal lines at the start + while lowerA < upperA and lowerB < upperB and dataA.data[lowerA] == dataB.data[lowerB]: + inc lowerA + inc lowerB + + # Fast walkthrough equal lines at the end + while lowerA < upperA and lowerB < upperB and dataA.data[upperA - 1] == dataB.data[upperB - 1]: + dec upperA + dec upperB + + if lowerA == upperA: + # mark as inserted lines. + while lowerB < upperB: + dataB.modified[lowerB] = true + inc lowerB + + elif lowerB == upperB: + # mark as deleted lines. + while lowerA < upperA: + dataA.modified[lowerA] = true + inc lowerA + + else: + # Find the middle snakea and length of an optimal path for A and B + let smsrd = sms(dataA, lowerA, upperA, dataB, lowerB, upperB, downVector, upVector) + # Debug.Write(2, "MiddleSnakeData", String.Format("{0},{1}", smsrd.x, smsrd.y)) + + # The path is from LowerX to (x,y) and (x,y) to UpperX + lcs(dataA, lowerA, smsrd.x, dataB, lowerB, smsrd.y, downVector, upVector) + lcs(dataA, smsrd.x, upperA, dataB, smsrd.y, upperB, downVector, upVector) # 2002.09.20: no need for 2 points + +# lcs() + +proc createDiffs(dataA, dataB: DiffData): seq[Item] = + ## Scan the tables of which lines are inserted and deleted, + ## producing an edit script in forward order. + + var startA: int + var startB: int + var lineA: int + var lineB: int + + while lineA < dataA.len or lineB < dataB.len: + if (lineA < dataA.len) and (not dataA.modified[lineA]) and + (lineB < dataB.len) and (not dataB.modified[lineB]): + # equal lines + inc lineA + inc lineB + else: + # maybe deleted and/or inserted lines + startA = lineA + startB = lineB + + while lineA < dataA.len and (lineB >= dataB.len or dataA.modified[lineA]): + # while (lineA < dataA.len and dataA.modified[lineA]) + inc lineA + + while lineB < dataB.len and (lineA >= dataA.len or dataB.modified[lineB]): + # while (lineB < dataB.len and dataB.modified[lineB]) + inc lineB + + if (startA < lineA) or (startB < lineB): + # store a new difference-item + var aItem: Item + aItem.startA = startA + aItem.startB = startB + aItem.deletedA = lineA - startA + aItem.insertedB = lineB - startB + result.add aItem + + +proc diffInt*(arrayA, arrayB: openArray[int]): seq[Item] = + ## Find the difference in 2 arrays of integers. + ## ``arrayA`` A-version of the numbers (usualy the old one) + ## ``arrayB`` B-version of the numbers (usualy the new one) + ## Returns a array of Items that describe the differences. + + # The A-Version of the data (original data) to be compared. + var dataA = newDiffData(@arrayA) + + # The B-Version of the data (modified data) to be compared. + var dataB = newDiffData(@arrayB) + + let max = dataA.len + dataB.len + 1 + ## vector for the (0,0) to (x,y) search + var downVector = newSeq[int](2 * max + 2) + ## vector for the (u,v) to (N,M) search + var upVector = newSeq[int](2 * max + 2) + + lcs(dataA, 0, dataA.len, dataB, 0, dataB.len, downVector, upVector) + return createDiffs(dataA, dataB) + +proc diffText*(textA,textB: string): seq[Item] = + ## Find the difference in 2 text documents, comparing by textlines. + ## The algorithm itself is comparing 2 arrays of numbers so when comparing 2 text documents + ## each line is converted into a (hash) number. This hash-value is computed by storing all + ## textlines into a common hashtable so i can find dublicates in there, and generating a + ## new number each time a new textline is inserted. + ## ``TextA`` A-version of the text (usualy the old one) + ## ``TextB`` B-version of the text (usualy the new one) + ## ``trimSpace`` When set to true, all leading and trailing whitespace characters are stripped out before the comparation is done. + ## ``ignoreSpace`` When set to true, all whitespace characters are converted to a single space character before the comparation is done. + ## ``ignoreCase`` When set to true, all characters are converted to their lowercase equivivalence before the comparation is done. + ## Returns a seq of Items that describe the differences. + + # prepare the input-text and convert to comparable numbers. + var h = initTable[string,int]() # TextA.len + TextB.len <- probably wrong initial size + # The A-Version of the data (original data) to be compared. + var dataA = newDiffData(diffCodes(textA, h)) + + # The B-Version of the data (modified data) to be compared. + var dataB = newDiffData(diffCodes(textB, h)) + + h.clear # free up hashtable memory (maybe) + + let max = dataA.len + dataB.len + 1 + ## vector for the (0,0) to (x,y) search + var downVector = newSeq[int](2 * max + 2) + ## vector for the (u,v) to (N,M) search + var upVector = newSeq[int](2 * max + 2) + + lcs(dataA, 0, dataA.len, dataB, 0, dataB.len, downVector, upVector) + + optimize(dataA) + optimize(dataB) + return createDiffs(dataA, dataB) + +when isMainModule: + + proc testHelper(f: seq[Item]): string = + for it in f: + result.add( + $it.deletedA & "." & $it.insertedB & "." & $it.startA & "." & $it.startB & "*" + ) + + proc main(): void = + var a, b: string + + stdout.writeLine("Diff Self Test...") + + # test all changes + a = "a,b,c,d,e,f,g,h,i,j,k,l".replace(',', '\n') + b = "0,1,2,3,4,5,6,7,8,9".replace(',', '\n') + assert(testHelper(diffText(a, b)) == + "12.10.0.0*", + "all-changes test failed.") + stdout.writeLine("all-changes test passed.") + # test all same + a = "a,b,c,d,e,f,g,h,i,j,k,l".replace(',', '\n') + b = a + assert(testHelper(diffText(a, b)) == + "", + "all-same test failed.") + stdout.writeLine("all-same test passed.") + + # test snake + a = "a,b,c,d,e,f".replace(',', '\n') + b = "b,c,d,e,f,x".replace(',', '\n') + assert(testHelper(diffText(a, b)) == + "1.0.0.0*0.1.6.5*", + "snake test failed.") + stdout.writeLine("snake test passed.") + + # 2002.09.20 - repro + a = "c1,a,c2,b,c,d,e,g,h,i,j,c3,k,l".replace(',', '\n') + b = "C1,a,C2,b,c,d,e,I1,e,g,h,i,j,C3,k,I2,l".replace(',', '\n') + assert(testHelper(diffText(a, b)) == + "1.1.0.0*1.1.2.2*0.2.7.7*1.1.11.13*0.1.13.15*", + "repro20020920 test failed.") + stdout.writeLine("repro20020920 test passed.") + + # 2003.02.07 - repro + a = "F".replace(',', '\n') + b = "0,F,1,2,3,4,5,6,7".replace(',', '\n') + assert(testHelper(diffText(a, b)) == + "0.1.0.0*0.7.1.2*", + "repro20030207 test failed.") + stdout.writeLine("repro20030207 test passed.") + + # Muegel - repro + a = "HELLO\nWORLD" + b = "\n\nhello\n\n\n\nworld\n" + assert(testHelper(diffText(a, b)) == + "2.8.0.0*", + "repro20030409 test failed.") + stdout.writeLine("repro20030409 test passed.") + + # test some differences + a = "a,b,-,c,d,e,f,f".replace(',', '\n') + b = "a,b,x,c,e,f".replace(',', '\n') + assert(testHelper(diffText(a, b)) == + "1.1.2.2*1.0.4.4*1.0.7.6*", + "some-changes test failed.") + stdout.writeLine("some-changes test passed.") + + # test one change within long chain of repeats + a = "a,a,a,a,a,a,a,a,a,a".replace(',', '\n') + b = "a,a,a,a,-,a,a,a,a,a".replace(',', '\n') + assert(testHelper(diffText(a, b)) == + "0.1.4.4*1.0.9.10*", + "long chain of repeats test failed.") + + stdout.writeLine("End.") + stdout.flushFile + + main() From 4799589fb3f7f21b2981a7b256fb479054f8492b Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Fri, 7 Dec 2018 21:59:43 +0000 Subject: [PATCH 015/110] undo some changes --- compiler/ast.nim | 2 +- compiler/ccgexprs.nim | 7 +++++++ compiler/semexprs.nim | 3 ++- lib/system.nim | 7 ++++++- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index 2b595aee1..7cf35450b 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -627,7 +627,7 @@ type mIsPartOf, mAstToStr, mParallel, mSwap, mIsNil, mArrToSeq, mCopyStr, mCopyStrLast, mNewString, mNewStringOfCap, mParseBiggestFloat, - mMove, mDestroy, + mMove, mWasMoved, mDestroy, mReset, mArray, mOpenArray, mRange, mSet, mSeq, mOpt, mVarargs, mRef, mPtr, mVar, mDistinct, mVoid, mTuple, diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index bf1494b3d..0cb3d3ad5 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -1901,6 +1901,13 @@ proc binaryFloatArith(p: BProc, e: PNode, d: var TLoc, m: TMagic) = proc skipAddr(n: PNode): PNode = result = if n.kind in {nkAddr, nkHiddenAddr}: n[0] else: n +proc genWasMoved(p: BProc; n: PNode) = + var a: TLoc + initLocExpr(p, n[1].skipAddr, a) + resetLoc(p, a) + #linefmt(p, cpsStmts, "#nimZeroMem((void*)$1, sizeof($2));$n", + # addrLoc(p.config, a), getTypeDesc(p.module, a.t)) + proc genMove(p: BProc; n: PNode; d: var TLoc) = if d.k == locNone: getTemp(p, n.typ, d) var a: TLoc diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 517356434..669862c56 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -614,7 +614,8 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) = const FakeVarParams = {mNew, mNewFinalize, mInc, ast.mDec, mIncl, mExcl, mSetLengthStr, mSetLengthSeq, mAppendStrCh, mAppendStrStr, mSwap, - mAppendSeqElem, mNewSeq, mReset, mShallowCopy, mDeepCopy, mMove} + mAppendSeqElem, mNewSeq, mReset, mShallowCopy, mDeepCopy, mMove, + mWasMoved} # get the real type of the callee # it may be a proc var with a generic alias type, so we skip over them diff --git a/lib/system.nim b/lib/system.nim index ec0dd629c..9111ddd86 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -221,10 +221,15 @@ proc reset*[T](obj: var T) {.magic: "Reset", noSideEffect.} ## be called before any possible `object branch transition`:idx:. when defined(nimNewRuntime): + proc wasMoved*[T](obj: var T) {.magic: "WasMoved", noSideEffect.} = + ## resets an object `obj` to its initial (binary zero) value to signify + ## it was "moved" and to signify its destructor should do nothing and + ## ideally be optimized away. + discard proc move*[T](x: var T): T {.magic: "Move", noSideEffect.} = result = x - reset(x) + wasMoved(x) type range*{.magic: "Range".}[T] ## Generic type to construct range types. From 961b7a9f6672c5422738364bea45a19060a8de5e Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Fri, 7 Dec 2018 22:00:55 +0000 Subject: [PATCH 016/110] undo more changes --- compiler/ccgexprs.nim | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 0cb3d3ad5..34836d843 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -2046,6 +2046,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = initLocExpr(p, e.sons[2], b) genDeepCopy(p, a, b) of mDotDot, mEqCString: genCall(p, e, d) + of mWasMoved: genWasMoved(p, e) of mMove: genMove(p, e, d) of mDestroy: discard "ignore calls to the default destructor" of mSlice: From 948c625f95d061e7f2608d9ead20d1fd05a64cd0 Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Fri, 7 Dec 2018 22:11:34 +0000 Subject: [PATCH 017/110] undo more stuff --- compiler/destroyer.nim | 61 ++++++++++++++++++++------------- lib/pure/collections/tables.nim | 44 ------------------------ 2 files changed, 37 insertions(+), 68 deletions(-) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index 56f941514..ebe8d1185 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -100,12 +100,12 @@ Rule Pattern Transformed into finally: `=destroy`(x) 1.2 var x: sink T; stmts var x: sink T; stmts; ensureEmpty(x) 2 x = f() `=sink`(x, f()) -3 x = lastReadOf z `=sink`(x, z); +3 x = lastReadOf z `=sink`(x, z); wasMoved(z) 4.1 y = sinkParam `=sink`(y, sinkParam) 4.2 x = y `=`(x, y) # a copy 5.1 f_sink(g()) f_sink(g()) 5.2 f_sink(y) f_sink(copy y); # copy unless we can see it's the last read -5.3 f_sink(move y) f_sink(y); # explicit moves empties 'y' +5.3 f_sink(move y) f_sink(y); # wasMoved(z) # explicit moves empties 'y' 5.4 f_noSink(g()) var tmp = bitwiseCopy(g()); f(tmp); `=destroy`(tmp) Remarks: Rule 1.2 is not yet implemented because ``sink`` is currently @@ -128,7 +128,7 @@ type g: ControlFlowGraph jumpTargets: IntSet topLevelVars: PNode - destroys: OrderedTable[int, tuple[enabled: bool, dropBit: PSym, destroy_call: PNode]] + destroys: OrderedTable[int, tuple[dropBit: PSym, destroy_call: PNode]] # Symbol to destructor call table graph: ModuleGraph emptyNode: PNode @@ -327,21 +327,11 @@ proc dropBit(c: var Con; s: PSym): PSym = assert result != nil proc addDestructor(c: var Con; s: PSym; destructor_call: PNode, dropBit: PSym = nil) = - let alreadyIn = c.destroys.hasKeyOrPut(s.id, (true, dropBit, destructor_call)) + let alreadyIn = c.destroys.hasKeyOrPut(s.id, (dropBit, destructor_call)) if alreadyIn: let lineInfo = if s.ast != nil: s.ast.info else: c.owner.info internalError(c.graph.config, lineInfo, "Destructor call for sym " & s.name.s & " is already injected") -proc disableDestructor(c: var Con; s: PSym) = - ## disable destructor, but do not delete such that it can be enabled back again later - c.destroys.with_value(s.id, value): - value.enabled = false - -proc enableDestructor(c: var Con; s: PSym) = - ## if destructor does not exist then ignore, otherwise make sure destructor is enabled - c.destroys.with_value(s.id, value): - value.enabled = true - proc registerDropBit(c: var Con; s: PSym) = let result = newSym(skTemp, getIdent(c.graph.cache, s.name.s & "_AliveBit"), c.owner, s.info) result.typ = getSysType(c.graph, s.info, tyBool) @@ -384,6 +374,31 @@ proc genMagicCall(n: PNode; c: var Con; magicname: string; m: TMagic): PNode = result.add(newSymNode(createMagic(c.graph, magicname, m))) result.add n +proc genWasMoved(n: PNode; c: var Con): PNode = + # The mWasMoved builtin does not take the address. + result = genMagicCall(n, c, "wasMoved", mWasMoved) + +proc destructiveMoveVar(n: PNode; c: var Con): PNode = + # generate: (let tmp = v; reset(v); tmp) + # XXX: Strictly speaking we can only move if there is a ``=sink`` defined + # or if no ``=sink`` is defined and also no assignment. + result = newNodeIT(nkStmtListExpr, n.info, n.typ) + + var temp = newSym(skLet, getIdent(c.graph.cache, "blitTmp"), c.owner, n.info) + temp.typ = n.typ + var v = newNodeI(nkLetSection, n.info) + let tempAsNode = newSymNode(temp) + + var vpart = newNodeI(nkIdentDefs, tempAsNode.info, 3) + vpart.sons[0] = tempAsNode + vpart.sons[1] = c.emptyNode + vpart.sons[2] = n + add(v, vpart) + + result.add v + result.add genWasMoved(n, c) + result.add tempAsNode + proc passCopyToSink(n: PNode; c: var Con): PNode = result = newNodeIT(nkStmtListExpr, n.info, n.typ) let tmp = getTemp(c, n.typ, n.info) @@ -420,9 +435,9 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode = result = arg elif arg.kind == nkSym and arg.sym.kind in InterestingSyms and isLastRead(arg, c): # if x is a variable and it its last read we eliminate its - # destructor invocation - c.disableDestructor(arg.sym) - result = arg + # destructor invokation, but don't. We need to reset its memory + # to disable its destructor which we have not elided: + result = destructiveMoveVar(arg, c) elif arg.kind == nkSym and isSinkParam(arg.sym): # mark the sink parameter as used: result = destructiveMoveSink(arg, c) @@ -580,14 +595,15 @@ proc p(n: PNode; c: var Con): PNode = if it.kind == nkVarTuple and hasDestructor(ri.typ): let x = lowerTupleUnpacking(c.graph, it, c.owner) result.add p(x, c) - elif it.kind == nkIdentDefs and hasDestructor(it[0].typ) and not isUnpackedTuple(it[0].sym): + elif it.kind == nkIdentDefs and hasDestructor(it[0].typ): for j in 0..L-2: let v = it[j] doAssert v.kind == nkSym # move the variable declaration to the top of the frame: c.addTopVar v # make sure it's destroyed at the end of the proc: - c.addDestructor(v.sym, genDestroy(c, v.typ, v)) + if not isUnpackedTuple(it[0].sym): + c.addDestructor(v.sym, genDestroy(c, v.typ, v)) if ri.kind != nkEmpty: let r = moveOrCopy(v, ri, c) result.add r @@ -619,8 +635,6 @@ proc p(n: PNode; c: var Con): PNode = of nkAsgn, nkFastAsgn: if hasDestructor(n[0].typ): result = moveOrCopy(n[0], n[1], c) - c.enableDestructor(n[0].sym) # last read to sink argument could have disabled the destructor - # but the variable is assigned again and new value should be destroyed else: result = copyNode(n) recurse(n, result) @@ -637,7 +651,7 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode = var c: Con c.owner = owner c.topLevelVars = newNodeI(nkVarSection, n.info) - c.destroys = initOrderedTable[int, (bool, PSym, PNode)](16) + c.destroys = initOrderedTable[int, (PSym, PNode)](32) c.graph = g c.emptyNode = newNodeI(nkEmpty, n.info) let cfg = constructCfg(owner, n) @@ -660,8 +674,7 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode = if c.destroys.len > 0: var destroy_list = newNodeI(nkStmtList, n.info) for val in c.destroys.values: - if val.enabled: - destroy_list.add val.destroy_call + destroy_list.add val.destroy_call result.add newTryFinally(body, destroy_list) else: result.add body diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim index ce87deea0..e7a4d1de0 100644 --- a/lib/pure/collections/tables.nim +++ b/lib/pure/collections/tables.nim @@ -880,50 +880,6 @@ proc del*[A, B](t: var OrderedTableRef[A, B], key: A) = t[].del(key) -template withValue*[A, B](t: var OrderedTable[A, B], key: A, value, body: untyped) = - ## retrieves the value at ``t[key]``. - ## ``value`` can be modified in the scope of the ``withValue`` call. - ## - ## .. code-block:: nim - ## - ## orderedTable.withValue(key, value) do: - ## # block is executed only if ``key`` in ``t`` - ## value.name = "username" - ## value.uid = 1000 - ## - mixin rawGet - var hc: Hash - var index = rawGet(t, key, hc) - let hasKey = index >= 0 - if hasKey: - var value {.inject.} = addr(t.data[index].val) - body - -template withValue*[A, B](t: var OrderedTable[A, B], key: A, - value, body1, body2: untyped) = - ## retrieves the value at ``t[key]``. - ## ``value`` can be modified in the scope of the ``withValue`` call. - ## - ## .. code-block:: nim - ## - ## orderedTable.withValue(key, value) do: - ## # block is executed only if ``key`` in ``t`` - ## value.name = "username" - ## value.uid = 1000 - ## do: - ## # block is executed when ``key`` not in ``t`` - ## raise newException(KeyError, "Key not found") - ## - mixin rawGet - var hc: Hash - var index = rawGet(t, key, hc) - let hasKey = index >= 0 - if hasKey: - var value {.inject.} = addr(t.data[index].val) - body1 - else: - body2 - # ------------------------------ count tables ------------------------------- type From d9815574c0ac38cf832515c0034ff2be96da24d9 Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Fri, 7 Dec 2018 22:14:46 +0000 Subject: [PATCH 018/110] more undo --- compiler/destroyer.nim | 2 +- lib/pure/collections/tables.nim | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index ebe8d1185..158e8cc4a 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -105,7 +105,7 @@ Rule Pattern Transformed into 4.2 x = y `=`(x, y) # a copy 5.1 f_sink(g()) f_sink(g()) 5.2 f_sink(y) f_sink(copy y); # copy unless we can see it's the last read -5.3 f_sink(move y) f_sink(y); # wasMoved(z) # explicit moves empties 'y' +5.3 f_sink(move y) f_sink(y); wasMoved(y) # explicit moves empties 'y' 5.4 f_noSink(g()) var tmp = bitwiseCopy(g()); f(tmp); `=destroy`(tmp) Remarks: Rule 1.2 is not yet implemented because ``sink`` is currently diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim index e7a4d1de0..f46a368b1 100644 --- a/lib/pure/collections/tables.nim +++ b/lib/pure/collections/tables.nim @@ -879,7 +879,6 @@ proc del*[A, B](t: var OrderedTableRef[A, B], key: A) = ## if the key does not exist. t[].del(key) - # ------------------------------ count tables ------------------------------- type From 43c70a6b12e24a6eed6e8b93cf21f225cef912da Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Fri, 7 Dec 2018 22:25:32 +0000 Subject: [PATCH 019/110] improve test --- compiler/destroyer.nim | 14 +++++++++----- tests/destructor/tmove_objconstr.nim | 11 ++++++++--- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index 158e8cc4a..74a796e7c 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -441,11 +441,15 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode = elif arg.kind == nkSym and isSinkParam(arg.sym): # mark the sink parameter as used: result = destructiveMoveSink(arg, c) - elif arg.kind in {nkStmtListExpr, nkBlockExpr, nkBlockStmt}: - result = copyNode(arg) - for i in 0..arg.len-2: - result.add p(arg[i], c) - result.add pArg(arg[^1], c, isSink) + elif arg.kind in {nkBlockExpr, nkBlockStmt}: + result = copyNode(arg) + result.add arg[0] + result.add pArg(arg[1], c, isSink) + elif arg.kind == nkStmtListExpr: + result = copyNode(arg) + for i in 0..arg.len-2: + result.add p(arg[i], c) + result.add pArg(arg[^1], c, isSink) elif arg.kind in {nkIfExpr, nkIfStmt}: result = copyNode(arg) for i in 0.. 5: raise newException(ValueError, "new error") else: newMySeq(x, 1.0), - b:0, - c: if y > 0: move(cc) else: newMySeq(1, 3.0)) + b: 0, + c: block: + var tmp = if y > 0: move(cc) else: newMySeq(1, 3.0) + tmp[0] = 5 + tmp + ) + let (seq1, seq2) = myfunc(2, 3) doAssert seq1.len == 2 @@ -160,4 +165,4 @@ seq4 = var ii = 1 let arr2 = [newMySeq(2, 5.0), if i > 1: newMySeq(3, 1.0) else: newMySeq(0, 0.0)] -var seqOfSeq2 = @[newMySeq(2, 5.0), newMySeq(3, 1.0)] \ No newline at end of file +var seqOfSeq2 = @[newMySeq(2, 5.0), newMySeq(3, 1.0)] From 775bfb3e8dc332d54d2de80996735f7cd2b0788f Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Fri, 7 Dec 2018 22:47:10 +0000 Subject: [PATCH 020/110] Merge async common into asyncdispatch. --- lib/pure/asyncdispatch.nim | 213 +++++++++++++++++++++++++++++- lib/pure/includes/asynccommon.nim | 211 ----------------------------- 2 files changed, 211 insertions(+), 213 deletions(-) delete mode 100644 lib/pure/includes/asynccommon.nim diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index aef4f1ce6..36319a317 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -1513,8 +1513,217 @@ proc poll*(timeout = 500) = ## `epoll`:idx: or `kqueue`:idx: primitive only once. discard runOnce(timeout) -# Common procedures between current and upcoming asyncdispatch -include includes/asynccommon +template createAsyncNativeSocketImpl(domain, sockType, protocol) = + let handle = newNativeSocket(domain, sockType, protocol) + if handle == osInvalidSocket: + return osInvalidSocket.AsyncFD + handle.setBlocking(false) + when defined(macosx) and not defined(nimdoc): + handle.setSockOptInt(SOL_SOCKET, SO_NOSIGPIPE, 1) + result = handle.AsyncFD + register(result) + +proc createAsyncNativeSocket*(domain: cint, sockType: cint, + protocol: cint): AsyncFD = + createAsyncNativeSocketImpl(domain, sockType, protocol) + +proc createAsyncNativeSocket*(domain: Domain = Domain.AF_INET, + sockType: SockType = SOCK_STREAM, + protocol: Protocol = IPPROTO_TCP): AsyncFD = + createAsyncNativeSocketImpl(domain, sockType, protocol) + +proc newAsyncNativeSocket*(domain: cint, sockType: cint, + protocol: cint): AsyncFD {.deprecated: "use createAsyncNativeSocket instead".} = + createAsyncNativeSocketImpl(domain, sockType, protocol) + +proc newAsyncNativeSocket*(domain: Domain = Domain.AF_INET, + sockType: SockType = SOCK_STREAM, + protocol: Protocol = IPPROTO_TCP): AsyncFD + {.deprecated: "use createAsyncNativeSocket instead".} = + createAsyncNativeSocketImpl(domain, sockType, protocol) + +when defined(windows) or defined(nimdoc): + proc bindToDomain(handle: SocketHandle, domain: Domain) = + # Extracted into a separate proc, because connect() on Windows requires + # the socket to be initially bound. + template doBind(saddr) = + if bindAddr(handle, cast[ptr SockAddr](addr(saddr)), + sizeof(saddr).SockLen) < 0'i32: + raiseOSError(osLastError()) + + if domain == Domain.AF_INET6: + var saddr: Sockaddr_in6 + saddr.sin6_family = uint16(toInt(domain)) + doBind(saddr) + else: + var saddr: Sockaddr_in + saddr.sin_family = uint16(toInt(domain)) + doBind(saddr) + + proc doConnect(socket: AsyncFD, addrInfo: ptr AddrInfo): Future[void] = + let retFuture = newFuture[void]("doConnect") + result = retFuture + + var ol = PCustomOverlapped() + GC_ref(ol) + ol.data = CompletionData(fd: socket, cb: + proc (fd: AsyncFD, bytesCount: Dword, errcode: OSErrorCode) = + if not retFuture.finished: + if errcode == OSErrorCode(-1): + retFuture.complete() + else: + retFuture.fail(newException(OSError, osErrorMsg(errcode))) + ) + + let ret = connectEx(socket.SocketHandle, addrInfo.ai_addr, + cint(addrInfo.ai_addrlen), nil, 0, nil, + cast[POVERLAPPED](ol)) + if ret: + # Request to connect completed immediately. + retFuture.complete() + # We don't deallocate ``ol`` here because even though this completed + # immediately poll will still be notified about its completion and it + # will free ``ol``. + else: + let lastError = osLastError() + if lastError.int32 != ERROR_IO_PENDING: + # With ERROR_IO_PENDING ``ol`` will be deallocated in ``poll``, + # and the future will be completed/failed there, too. + GC_unref(ol) + retFuture.fail(newException(OSError, osErrorMsg(lastError))) +else: + proc doConnect(socket: AsyncFD, addrInfo: ptr AddrInfo): Future[void] = + let retFuture = newFuture[void]("doConnect") + result = retFuture + + proc cb(fd: AsyncFD): bool = + let ret = SocketHandle(fd).getSockOptInt( + cint(SOL_SOCKET), cint(SO_ERROR)) + if ret == 0: + # We have connected. + retFuture.complete() + return true + elif ret == EINTR: + # interrupted, keep waiting + return false + else: + retFuture.fail(newException(OSError, osErrorMsg(OSErrorCode(ret)))) + return true + + let ret = connect(socket.SocketHandle, + addrInfo.ai_addr, + addrInfo.ai_addrlen.Socklen) + if ret == 0: + # Request to connect completed immediately. + retFuture.complete() + else: + let lastError = osLastError() + if lastError.int32 == EINTR or lastError.int32 == EINPROGRESS: + addWrite(socket, cb) + else: + retFuture.fail(newException(OSError, osErrorMsg(lastError))) + +template asyncAddrInfoLoop(addrInfo: ptr AddrInfo, fd: untyped, + protocol: Protocol = IPPROTO_RAW) = + ## Iterates through the AddrInfo linked list asynchronously + ## until the connection can be established. + const shouldCreateFd = not declared(fd) + + when shouldCreateFd: + let sockType = protocol.toSockType() + + var fdPerDomain: array[low(Domain).ord..high(Domain).ord, AsyncFD] + for i in low(fdPerDomain)..high(fdPerDomain): + fdPerDomain[i] = osInvalidSocket.AsyncFD + template closeUnusedFds(domainToKeep = -1) {.dirty.} = + for i, fd in fdPerDomain: + if fd != osInvalidSocket.AsyncFD and i != domainToKeep: + fd.closeSocket() + + var lastException: ref Exception + var curAddrInfo = addrInfo + var domain: Domain + when shouldCreateFd: + var curFd: AsyncFD + else: + var curFd = fd + proc tryNextAddrInfo(fut: Future[void]) {.gcsafe.} = + if fut == nil or fut.failed: + if fut != nil: + lastException = fut.readError() + + while curAddrInfo != nil: + let domainOpt = curAddrInfo.ai_family.toKnownDomain() + if domainOpt.isSome: + domain = domainOpt.unsafeGet() + break + curAddrInfo = curAddrInfo.ai_next + + if curAddrInfo == nil: + freeAddrInfo(addrInfo) + when shouldCreateFd: + closeUnusedFds() + if lastException != nil: + retFuture.fail(lastException) + else: + retFuture.fail(newException( + IOError, "Couldn't resolve address: " & address)) + return + + when shouldCreateFd: + curFd = fdPerDomain[ord(domain)] + if curFd == osInvalidSocket.AsyncFD: + try: + curFd = newAsyncNativeSocket(domain, sockType, protocol) + except: + freeAddrInfo(addrInfo) + closeUnusedFds() + raise getCurrentException() + when defined(windows): + curFd.SocketHandle.bindToDomain(domain) + fdPerDomain[ord(domain)] = curFd + + doConnect(curFd, curAddrInfo).callback = tryNextAddrInfo + curAddrInfo = curAddrInfo.ai_next + else: + freeAddrInfo(addrInfo) + when shouldCreateFd: + closeUnusedFds(ord(domain)) + retFuture.complete(curFd) + else: + retFuture.complete() + + tryNextAddrInfo(nil) + +proc dial*(address: string, port: Port, + protocol: Protocol = IPPROTO_TCP): Future[AsyncFD] = + ## Establishes connection to the specified ``address``:``port`` pair via the + ## specified protocol. The procedure iterates through possible + ## resolutions of the ``address`` until it succeeds, meaning that it + ## seamlessly works with both IPv4 and IPv6. + ## Returns the async file descriptor, registered in the dispatcher of + ## the current thread, ready to send or receive data. + let retFuture = newFuture[AsyncFD]("dial") + result = retFuture + let sockType = protocol.toSockType() + + let aiList = getAddrInfo(address, port, Domain.AF_UNSPEC, sockType, protocol) + asyncAddrInfoLoop(aiList, noFD, protocol) + +proc connect*(socket: AsyncFD, address: string, port: Port, + domain = Domain.AF_INET): Future[void] = + let retFuture = newFuture[void]("connect") + result = retFuture + + when defined(windows): + verifyPresence(socket) + else: + assert getSockDomain(socket.SocketHandle) == domain + + let aiList = getAddrInfo(address, port, domain) + when defined(windows): + socket.SocketHandle.bindToDomain(domain) + asyncAddrInfoLoop(aiList, socket) proc sleepAsync*(ms: int | float): Future[void] = ## Suspends the execution of the current async procedure for the next diff --git a/lib/pure/includes/asynccommon.nim b/lib/pure/includes/asynccommon.nim deleted file mode 100644 index 13887acc9..000000000 --- a/lib/pure/includes/asynccommon.nim +++ /dev/null @@ -1,211 +0,0 @@ -template createAsyncNativeSocketImpl(domain, sockType, protocol) = - let handle = newNativeSocket(domain, sockType, protocol) - if handle == osInvalidSocket: - return osInvalidSocket.AsyncFD - handle.setBlocking(false) - when defined(macosx) and not defined(nimdoc): - handle.setSockOptInt(SOL_SOCKET, SO_NOSIGPIPE, 1) - result = handle.AsyncFD - register(result) - -proc createAsyncNativeSocket*(domain: cint, sockType: cint, - protocol: cint): AsyncFD = - createAsyncNativeSocketImpl(domain, sockType, protocol) - -proc createAsyncNativeSocket*(domain: Domain = Domain.AF_INET, - sockType: SockType = SOCK_STREAM, - protocol: Protocol = IPPROTO_TCP): AsyncFD = - createAsyncNativeSocketImpl(domain, sockType, protocol) - -proc newAsyncNativeSocket*(domain: cint, sockType: cint, - protocol: cint): AsyncFD {.deprecated: "use createAsyncNativeSocket instead".} = - createAsyncNativeSocketImpl(domain, sockType, protocol) - -proc newAsyncNativeSocket*(domain: Domain = Domain.AF_INET, - sockType: SockType = SOCK_STREAM, - protocol: Protocol = IPPROTO_TCP): AsyncFD - {.deprecated: "use createAsyncNativeSocket instead".} = - createAsyncNativeSocketImpl(domain, sockType, protocol) - -when defined(windows) or defined(nimdoc): - proc bindToDomain(handle: SocketHandle, domain: Domain) = - # Extracted into a separate proc, because connect() on Windows requires - # the socket to be initially bound. - template doBind(saddr) = - if bindAddr(handle, cast[ptr SockAddr](addr(saddr)), - sizeof(saddr).SockLen) < 0'i32: - raiseOSError(osLastError()) - - if domain == Domain.AF_INET6: - var saddr: Sockaddr_in6 - saddr.sin6_family = uint16(toInt(domain)) - doBind(saddr) - else: - var saddr: Sockaddr_in - saddr.sin_family = uint16(toInt(domain)) - doBind(saddr) - - proc doConnect(socket: AsyncFD, addrInfo: ptr AddrInfo): Future[void] = - let retFuture = newFuture[void]("doConnect") - result = retFuture - - var ol = PCustomOverlapped() - GC_ref(ol) - ol.data = CompletionData(fd: socket, cb: - proc (fd: AsyncFD, bytesCount: Dword, errcode: OSErrorCode) = - if not retFuture.finished: - if errcode == OSErrorCode(-1): - retFuture.complete() - else: - retFuture.fail(newException(OSError, osErrorMsg(errcode))) - ) - - let ret = connectEx(socket.SocketHandle, addrInfo.ai_addr, - cint(addrInfo.ai_addrlen), nil, 0, nil, - cast[POVERLAPPED](ol)) - if ret: - # Request to connect completed immediately. - retFuture.complete() - # We don't deallocate ``ol`` here because even though this completed - # immediately poll will still be notified about its completion and it - # will free ``ol``. - else: - let lastError = osLastError() - if lastError.int32 != ERROR_IO_PENDING: - # With ERROR_IO_PENDING ``ol`` will be deallocated in ``poll``, - # and the future will be completed/failed there, too. - GC_unref(ol) - retFuture.fail(newException(OSError, osErrorMsg(lastError))) -else: - proc doConnect(socket: AsyncFD, addrInfo: ptr AddrInfo): Future[void] = - let retFuture = newFuture[void]("doConnect") - result = retFuture - - proc cb(fd: AsyncFD): bool = - let ret = SocketHandle(fd).getSockOptInt( - cint(SOL_SOCKET), cint(SO_ERROR)) - if ret == 0: - # We have connected. - retFuture.complete() - return true - elif ret == EINTR: - # interrupted, keep waiting - return false - else: - retFuture.fail(newException(OSError, osErrorMsg(OSErrorCode(ret)))) - return true - - let ret = connect(socket.SocketHandle, - addrInfo.ai_addr, - addrInfo.ai_addrlen.Socklen) - if ret == 0: - # Request to connect completed immediately. - retFuture.complete() - else: - let lastError = osLastError() - if lastError.int32 == EINTR or lastError.int32 == EINPROGRESS: - addWrite(socket, cb) - else: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) - -template asyncAddrInfoLoop(addrInfo: ptr AddrInfo, fd: untyped, - protocol: Protocol = IPPROTO_RAW) = - ## Iterates through the AddrInfo linked list asynchronously - ## until the connection can be established. - const shouldCreateFd = not declared(fd) - - when shouldCreateFd: - let sockType = protocol.toSockType() - - var fdPerDomain: array[low(Domain).ord..high(Domain).ord, AsyncFD] - for i in low(fdPerDomain)..high(fdPerDomain): - fdPerDomain[i] = osInvalidSocket.AsyncFD - template closeUnusedFds(domainToKeep = -1) {.dirty.} = - for i, fd in fdPerDomain: - if fd != osInvalidSocket.AsyncFD and i != domainToKeep: - fd.closeSocket() - - var lastException: ref Exception - var curAddrInfo = addrInfo - var domain: Domain - when shouldCreateFd: - var curFd: AsyncFD - else: - var curFd = fd - proc tryNextAddrInfo(fut: Future[void]) {.gcsafe.} = - if fut == nil or fut.failed: - if fut != nil: - lastException = fut.readError() - - while curAddrInfo != nil: - let domainOpt = curAddrInfo.ai_family.toKnownDomain() - if domainOpt.isSome: - domain = domainOpt.unsafeGet() - break - curAddrInfo = curAddrInfo.ai_next - - if curAddrInfo == nil: - freeAddrInfo(addrInfo) - when shouldCreateFd: - closeUnusedFds() - if lastException != nil: - retFuture.fail(lastException) - else: - retFuture.fail(newException( - IOError, "Couldn't resolve address: " & address)) - return - - when shouldCreateFd: - curFd = fdPerDomain[ord(domain)] - if curFd == osInvalidSocket.AsyncFD: - try: - curFd = newAsyncNativeSocket(domain, sockType, protocol) - except: - freeAddrInfo(addrInfo) - closeUnusedFds() - raise getCurrentException() - when defined(windows): - curFd.SocketHandle.bindToDomain(domain) - fdPerDomain[ord(domain)] = curFd - - doConnect(curFd, curAddrInfo).callback = tryNextAddrInfo - curAddrInfo = curAddrInfo.ai_next - else: - freeAddrInfo(addrInfo) - when shouldCreateFd: - closeUnusedFds(ord(domain)) - retFuture.complete(curFd) - else: - retFuture.complete() - - tryNextAddrInfo(nil) - -proc dial*(address: string, port: Port, - protocol: Protocol = IPPROTO_TCP): Future[AsyncFD] = - ## Establishes connection to the specified ``address``:``port`` pair via the - ## specified protocol. The procedure iterates through possible - ## resolutions of the ``address`` until it succeeds, meaning that it - ## seamlessly works with both IPv4 and IPv6. - ## Returns the async file descriptor, registered in the dispatcher of - ## the current thread, ready to send or receive data. - let retFuture = newFuture[AsyncFD]("dial") - result = retFuture - let sockType = protocol.toSockType() - - let aiList = getAddrInfo(address, port, Domain.AF_UNSPEC, sockType, protocol) - asyncAddrInfoLoop(aiList, noFD, protocol) - -proc connect*(socket: AsyncFD, address: string, port: Port, - domain = Domain.AF_INET): Future[void] = - let retFuture = newFuture[void]("connect") - result = retFuture - - when defined(windows): - verifyPresence(socket) - else: - assert getSockDomain(socket.SocketHandle) == domain - - let aiList = getAddrInfo(address, port, domain) - when defined(windows): - socket.SocketHandle.bindToDomain(domain) - asyncAddrInfoLoop(aiList, socket) From 0a749f1a37e372d99bfa956803affeb63ec04ce5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Nihlg=C3=A5rd?= Date: Sat, 8 Dec 2018 10:01:21 +0100 Subject: [PATCH 021/110] Make options.UnpackError inherit from system.Defect --- changelog.md | 2 ++ lib/pure/options.nim | 34 +++++++++++++++------------------- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/changelog.md b/changelog.md index 6dbfa1a2d..093ea7ae2 100644 --- a/changelog.md +++ b/changelog.md @@ -29,6 +29,8 @@ - `osproc.execProcess` now also takes a `workingDir` parameter. +- `options.UnpackError` is no longer a ref type and inherits from `System.Defect` instead of `System.ValueError`. + #### Breaking changes in the compiler - The compiler now implements the "generic symbol prepass" for `when` statements diff --git a/lib/pure/options.nim b/lib/pure/options.nim index 12e38d8b5..b827e1aa3 100644 --- a/lib/pure/options.nim +++ b/lib/pure/options.nim @@ -39,17 +39,18 @@ ## ## .. code-block:: nim ## -## try: -## assert("abc".find('c').get() == 2) # Immediately extract the value -## except UnpackError: # If there is no value -## assert false # This will not be reached, because the value is present -## +## let found = "abc".find('c') +## assert found.isSome and found.get() == 2 +## ## The ``get`` operation demonstrated above returns the underlying value, or -## raises ``UnpackError`` if there is no value. There is another option for -## obtaining the value: ``unsafeGet``, but you must only use it when you are -## absolutely sure the value is present (e.g. after checking ``isSome``). If -## you do not care about the tiny overhead that ``get`` causes, you should -## simply never use ``unsafeGet``. +## raises ``UnpackError`` if there is no value. Note that ``UnpackError`` inherits +## from ``system.Defect``, and should therefore never be catched. Instead, rely on +## checking if the option contains a value with ``isSome`` and ``isNone``. +## +## There is another option for obtaining the value: ``unsafeGet``, but you must +## only use it when you are absolutely sure the value is present (e.g. after +## checking ``isSome``). If you do not care about the tiny overhead that ``get`` +## causes, you should simply never use ``unsafeGet``. ## ## How to deal with an absence of a value: ## @@ -61,12 +62,7 @@ ## assert(result == none(int)) ## # It has no value: ## assert(result.isNone) -## -## try: -## echo result.get() -## assert(false) # This will not be reached -## except UnpackError: # Because an exception is raised -## discard + import typetraits type @@ -81,7 +77,7 @@ type val: T has: bool - UnpackError* = ref object of ValueError + UnpackError* = object of Defect proc some*[T](val: T): Option[T] = ## Returns a ``Option`` that has this value. @@ -129,7 +125,7 @@ proc get*[T](self: Option[T]): T = ## Returns contents of the Option. If it is none, then an exception is ## thrown. if self.isNone: - raise UnpackError(msg: "Can't obtain a value from a `none`") + raise newException(UnpackError, "Can't obtain a value from a `none`") self.val proc get*[T](self: Option[T], otherwise: T): T = @@ -143,7 +139,7 @@ proc get*[T](self: var Option[T]): var T = ## Returns contents of the Option. If it is none, then an exception is ## thrown. if self.isNone: - raise UnpackError(msg: "Can't obtain a value from a `none`") + raise newException(UnpackError, "Can't obtain a value from a `none`") return self.val proc map*[T](self: Option[T], callback: proc (input: T)) = From 94a63eef9a5da8441d17e1f5214c1823056bcf68 Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Sat, 8 Dec 2018 11:35:18 +0000 Subject: [PATCH 022/110] Fix hintXDeclaredButNotUsed for enum fields marked as used --- compiler/lookups.nim | 3 ++- tests/pragmas/tused.nim | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/compiler/lookups.nim b/compiler/lookups.nim index 2fb4e5241..91d6bd745 100644 --- a/compiler/lookups.nim +++ b/compiler/lookups.nim @@ -169,7 +169,8 @@ proc ensureNoMissingOrUnusedSymbols(c: PContext; scope: PScope) = getSymRepr(c.config, s)) inc missingImpls elif {sfUsed, sfExported} * s.flags == {}: - if s.kind notin {skForVar, skParam, skMethod, skUnknown, skGenericParam}: + if s.kind notin {skForVar, skParam, skMethod, skUnknown, skGenericParam} and + not (s.kind == skEnumField and {sfUsed, sfExported} * s.owner.flags != {}): # XXX: implicit type params are currently skTypes # maybe they can be made skGenericParam as well. if s.typ != nil and tfImplicitTypeParam notin s.typ.flags and diff --git a/tests/pragmas/tused.nim b/tests/pragmas/tused.nim index 83c62b7bb..eb9cb08aa 100644 --- a/tests/pragmas/tused.nim +++ b/tests/pragmas/tused.nim @@ -31,5 +31,10 @@ block: implementArithOpsNew(int) echoAdd 3, 5 +type + MyEnum {.used.} = enum + Val1, Val2, Val3 + + static: echo "compile end" From 5f9234e5cbea12e01286d0789dc4ae6d4b537dbb Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Sat, 8 Dec 2018 11:39:11 +0000 Subject: [PATCH 023/110] add comment, fixes #9896 --- tests/pragmas/tused.nim | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/pragmas/tused.nim b/tests/pragmas/tused.nim index eb9cb08aa..dce854146 100644 --- a/tests/pragmas/tused.nim +++ b/tests/pragmas/tused.nim @@ -31,6 +31,7 @@ block: implementArithOpsNew(int) echoAdd 3, 5 +# issue #9896 type MyEnum {.used.} = enum Val1, Val2, Val3 From e8747059710370819800bdc0742fa86761c6737b Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 8 Dec 2018 13:30:06 +0100 Subject: [PATCH 024/110] fixes nested gensym'ed parameters; fixes #9476 --- compiler/ast.nim | 6 ++--- compiler/evaltempl.nim | 14 +++++++--- compiler/lambdalifting.nim | 5 +--- compiler/sem.nim | 11 ++++---- compiler/semexprs.nim | 4 +++ compiler/seminst.nim | 2 +- compiler/semstmts.nim | 17 ++++++++---- compiler/semtypes.nim | 6 ++++- tests/template/tparams_gensymed.nim | 40 +++++++++++++++++++++++++++++ 9 files changed, 82 insertions(+), 23 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index 40a05e6bf..0247acb03 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1087,9 +1087,6 @@ proc newSym*(symKind: TSymKind, name: PIdent, owner: PSym, result.id = getID() when debugIds: registerId(result) - #if result.id == 77131: - # writeStacktrace() - # echo name.s proc isMetaType*(t: PType): bool = return t.kind in tyMetaTypes or @@ -1261,6 +1258,9 @@ proc `$`*(x: TLockLevel): string = elif x.ord == UnknownLockLevel.ord: result = "" else: result = $int16(x) +proc `$`*(s: PSym): string = + result = s.name.s & "@" & $s.id + proc newType*(kind: TTypeKind, owner: PSym): PType = new(result) result.kind = kind diff --git a/compiler/evaltempl.nim b/compiler/evaltempl.nim index 09a1cd436..0f9220102 100644 --- a/compiler/evaltempl.nim +++ b/compiler/evaltempl.nim @@ -37,18 +37,21 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) = case templ.kind of nkSym: var s = templ.sym - if s.owner.id == c.owner.id: + if s.owner == nil or s.owner.id == c.owner.id: if s.kind == skParam and sfGenSym notin s.flags: handleParam actual.sons[s.position] - elif s.kind == skGenericParam or - s.kind == skType and s.typ != nil and s.typ.kind == tyGenericParam: + elif (s.owner != nil) and (s.kind == skGenericParam or + s.kind == skType and s.typ != nil and s.typ.kind == tyGenericParam): handleParam actual.sons[s.owner.typ.len + s.position - 1] else: internalAssert c.config, sfGenSym in s.flags or s.kind == skType var x = PSym(idTableGet(c.mapping, s)) if x == nil: x = copySym(s) - x.owner = c.genSymOwner + # sem'check needs to set the owner properly later, see bug #9476 + x.owner = nil # c.genSymOwner + #if x.kind == skParam and x.owner.kind == skModule: + # internalAssert c.config, false idTablePut(c.mapping, s, x) result.add newSymNode(x, if c.instLines: actual.info else: templ.info) else: @@ -173,6 +176,7 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym; initIdTable(ctx.mapping) let body = tmpl.getBody + #echo "instantion of ", renderTree(body, {renderIds}) if isAtom(body): result = newNodeI(nkPar, body.info) evalTemplateAux(body, args, ctx, result) @@ -189,5 +193,7 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym; evalTemplateAux(body.sons[i], args, ctx, result) result.flags.incl nfFromTemplate result = wrapInComesFrom(n.info, tmpl, result) + #if ctx.debugActive: + # echo "instantion of ", renderTree(result, {renderIds}) dec(conf.evalTemplateCounter) diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index 874cb4bd0..ddde1be31 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -407,11 +407,8 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) = obj.n[0].sym.id = -s.id else: addField(obj, s, c.graph.cache) - # but always return because the rest of the proc is only relevant when - # ow != owner: - return # direct or indirect dependency: - if (innerProc and s.typ.callConv == ccClosure) or interestingVar(s): + elif (innerProc and s.typ.callConv == ccClosure) or interestingVar(s): discard """ proc outer() = var x: int diff --git a/compiler/sem.nim b/compiler/sem.nim index 924e53b66..8332af346 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -207,11 +207,12 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym = if result.kind notin {kind, skTemp}: localError(c.config, n.info, "cannot use symbol of kind '" & $result.kind & "' as a '" & $kind & "'") - if sfGenSym in result.flags and result.kind notin {skTemplate, skMacro, skParam}: - # declarative context, so produce a fresh gensym: - result = copySym(result) - result.ast = n.sym.ast - put(c.p, n.sym, result) + when false: + if sfGenSym in result.flags and result.kind notin {skTemplate, skMacro, skParam}: + # declarative context, so produce a fresh gensym: + result = copySym(result) + result.ast = n.sym.ast + put(c.p, n.sym, result) # when there is a nested proc inside a template, semtmpl # will assign a wrong owner during the first pass over the # template; we must fix it here: see #909 diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 08917cb29..ddec457a1 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1083,6 +1083,8 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode = # XXX see the hack in sigmatch.nim ... return s.typ.n elif sfGenSym in s.flags: + # the owner should have been set by now by addParamOrResult + internalAssert c.config, s.owner != nil if c.p.wasForwarded: # gensym'ed parameters that nevertheless have been forward declared # need a special fixup: @@ -2289,6 +2291,8 @@ proc semBlock(c: PContext, n: PNode; flags: TExprFlags): PNode = var labl = newSymG(skLabel, n.sons[0], c) if sfGenSym notin labl.flags: addDecl(c, labl) + elif labl.owner == nil: + labl.owner = c.p.owner n.sons[0] = newSymNode(labl, n.sons[0].info) suggestSym(c.config, n.sons[0].info, labl, c.graph.usageSym) styleCheckDef(c.config, labl) diff --git a/compiler/seminst.nim b/compiler/seminst.nim index 17f61c7dd..09991048e 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -116,7 +116,7 @@ proc freshGenSyms(n: PNode, owner, orig: PSym, symMap: var TIdTable) = var x = PSym(idTableGet(symMap, s)) if x != nil: n.sym = x - elif s.owner.kind == skPackage: + elif s.owner == nil or s.owner.kind == skPackage: #echo "copied this ", s.name.s x = copySym(s) x.owner = owner diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 48aa75528..2e2a3a20a 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -497,8 +497,10 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = var v = semIdentDef(c, a.sons[j], symkind) styleCheckDef(c.config, v) onDef(a[j].info, v) - if sfGenSym notin v.flags and not isDiscardUnderscore(v): - addInterfaceDecl(c, v) + if sfGenSym notin v.flags: + if not isDiscardUnderscore(v): addInterfaceDecl(c, v) + else: + if v.owner == nil: v.owner = c.p.owner when oKeepVariableNames: if c.inUnrolledContext > 0: v.flags.incl(sfShadowed) else: @@ -573,6 +575,7 @@ proc semConst(c: PContext, n: PNode): PNode = setVarType(c, v, typ) v.ast = def # no need to copy if sfGenSym notin v.flags: addInterfaceDecl(c, v) + elif v.owner == nil: v.owner = getCurrOwner(c) var b = newNodeI(nkConstDef, a.info) if importantComments(c.config): b.comment = a.comment addSon(b, newSymNode(v)) @@ -616,6 +619,7 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode = v.typ = iterBase n.sons[0] = newSymNode(v) if sfGenSym notin v.flags: addForVarDecl(c, v) + elif v.owner == nil: v.owner = getCurrOwner(c) else: localError(c.config, n.info, errWrongNumberOfVariables) elif length-2 != sonsLen(iter): @@ -626,8 +630,9 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode = if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal) v.typ = iter.sons[i] n.sons[i] = newSymNode(v) - if sfGenSym notin v.flags and not isDiscardUnderscore(v): - addForVarDecl(c, v) + if sfGenSym notin v.flags: + if not isDiscardUnderscore(v): addForVarDecl(c, v) + elif v.owner == nil: v.owner = getCurrOwner(c) inc(c.p.nestedLoopCounter) openScope(c) n.sons[length-1] = semExprBranch(c, n.sons[length-1], flags) @@ -922,6 +927,7 @@ proc typeSectionLeftSidePass(c: PContext, n: PNode) = s = typsym # add it here, so that recursive types are possible: if sfGenSym notin s.flags: addInterfaceDecl(c, s) + elif s.owner == nil: s.owner = getCurrOwner(c) if name.kind == nkPragmaExpr: a.sons[0].sons[0] = newSymNode(s) @@ -1620,7 +1626,8 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, else: s.typ.callConv = lastOptionEntry(c).defaultCC # add it here, so that recursive procs are possible: - if sfGenSym in s.flags: discard + if sfGenSym in s.flags: + if s.owner == nil: s.owner = getCurrOwner(c) elif kind in OverloadableSyms: if not typeIsDetermined: addInterfaceOverloadableSymAt(c, oldScope, s) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index a011a8fc8..1e75b563e 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -821,7 +821,11 @@ proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) = a.typ = nn.typ addDecl(c, a) else: - if sfGenSym notin param.flags: addDecl(c, param) + if sfGenSym in param.flags: + # bug #XXX, fix the gensym'ed parameters owner: + if param.owner == nil: + param.owner = getCurrOwner(c) + else: addDecl(c, param) template shouldHaveMeta(t) = internalAssert c.config, tfHasMeta in t.flags diff --git a/tests/template/tparams_gensymed.nim b/tests/template/tparams_gensymed.nim index da86d63dc..91fa26596 100644 --- a/tests/template/tparams_gensymed.nim +++ b/tests/template/tparams_gensymed.nim @@ -70,3 +70,43 @@ proc genericProc(x: any) = concreteProc(7) # This works genericProc(7) # This doesn't compile + +import tables + +# bug #9476 +proc getTypeInfo*(T: typedesc): pointer = + var dummy: T + getTypeInfo(dummy) + + +macro implementUnary(op: untyped): untyped = + result = newStmtList() + + template defineTable(tableSymbol) = + var tableSymbol = initTable[pointer, pointer]() + let tableSymbol = genSym(nskVar, "registeredProcs") + result.add(getAst(defineTable(tableSymbol))) + + template defineRegisterInstantiation(tableSym, regTemplSym, instSym, op) = + template regTemplSym*(T: typedesc) = + let ti = getTypeInfo(T) + + proc instSym(xOrig: int): int {.gensym, cdecl.} = + let x {.inject.} = xOrig + op + + tableSym[ti] = cast[pointer](instSym) + + let regTemplSymbol = ident("registerInstantiation") + let instSymbol = ident("instantiation") + result.add(getAst(defineRegisterInstantiation( + tableSymbol, regTemplSymbol, instSymbol, op + ))) + + echo result.repr + + +implementUnary(): x*x + +registerInstantiation(int) +registerInstantiation(float) From 0fdd7629b423d77178052c98f42d0683d3ec17ba Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Sat, 8 Dec 2018 19:18:00 +0000 Subject: [PATCH 025/110] remove dropbits in favour of destructive moves --- compiler/destroyer.nim | 71 ++++++++++-------------------------------- 1 file changed, 16 insertions(+), 55 deletions(-) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index 74a796e7c..75cf86124 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -128,8 +128,7 @@ type g: ControlFlowGraph jumpTargets: IntSet topLevelVars: PNode - destroys: OrderedTable[int, tuple[dropBit: PSym, destroy_call: PNode]] - # Symbol to destructor call table + destroys: PNode graph: ModuleGraph emptyNode: PNode otherRead: PNode @@ -322,28 +321,6 @@ proc genDestroy(c: Con; t: PType; dest: PNode): PNode = proc addTopVar(c: var Con; v: PNode) = c.topLevelVars.add newTree(nkIdentDefs, v, c.emptyNode, c.emptyNode) -proc dropBit(c: var Con; s: PSym): PSym = - result = c.destroys.getOrDefault(s.id).dropBit - assert result != nil - -proc addDestructor(c: var Con; s: PSym; destructor_call: PNode, dropBit: PSym = nil) = - let alreadyIn = c.destroys.hasKeyOrPut(s.id, (dropBit, destructor_call)) - if alreadyIn: - let lineInfo = if s.ast != nil: s.ast.info else: c.owner.info - internalError(c.graph.config, lineInfo, "Destructor call for sym " & s.name.s & " is already injected") - -proc registerDropBit(c: var Con; s: PSym) = - let result = newSym(skTemp, getIdent(c.graph.cache, s.name.s & "_AliveBit"), c.owner, s.info) - result.typ = getSysType(c.graph, s.info, tyBool) - let trueVal = newIntTypeNode(nkIntLit, 1, result.typ) - c.topLevelVars.add newTree(nkIdentDefs, newSymNode result, c.emptyNode, trueVal) - # generate: - # if not sinkParam_AliveBit: `=destroy`(sinkParam) - let t = s.typ.skipTypes({tyGenericInst, tyAlias, tySink}) - if t.destructor != nil: - c.addDestructor(s, newTree(nkIfStmt, - newTree(nkElifBranch, newSymNode result, genDestroy(c, t, newSymNode s))), result) - proc getTemp(c: var Con; typ: PType; info: TLineInfo): PNode = let sym = newSym(skTemp, getIdent(c.graph.cache, ":tmpD"), c.owner, info) sym.typ = typ @@ -359,16 +336,6 @@ template recurse(n, dest) = proc isSinkParam(s: PSym): bool {.inline.} = result = s.kind == skParam and s.typ.kind == tySink -proc destructiveMoveSink(n: PNode; c: var Con): PNode = - # generate: (chckMove(sinkParam_AliveBit); sinkParam_AliveBit = false; sinkParam) - result = newNodeIT(nkStmtListExpr, n.info, n.typ) - let bit = newSymNode dropBit(c, n.sym) - if optMoveCheck in c.owner.options: - result.add callCodegenProc(c.graph, "chckMove", bit.info, bit) - result.add newTree(nkAsgn, bit, - newIntTypeNode(nkIntLit, 0, getSysType(c.graph, n.info, tyBool))) - result.add n - proc genMagicCall(n: PNode; c: var Con; magicname: string; m: TMagic): PNode = result = newNodeI(nkCall, n.info) result.add(newSymNode(createMagic(c.graph, magicname, m))) @@ -433,14 +400,11 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode = elif arg.kind in {nkBracket, nkObjConstr, nkTupleConstr, nkBracket, nkCharLit..nkFloat128Lit}: discard "object construction to sink parameter: nothing to do" result = arg - elif arg.kind == nkSym and arg.sym.kind in InterestingSyms and isLastRead(arg, c): - # if x is a variable and it its last read we eliminate its - # destructor invokation, but don't. We need to reset its memory - # to disable its destructor which we have not elided: + elif arg.kind == nkSym and (isSinkParam(arg.sym) or + arg.sym.kind in InterestingSyms and isLastRead(arg, c)): + # it is the last read be final consumption. We need to reset the memory + # to disable the destructor which we have not elided: result = destructiveMoveVar(arg, c) - elif arg.kind == nkSym and isSinkParam(arg.sym): - # mark the sink parameter as used: - result = destructiveMoveSink(arg, c) elif arg.kind in {nkBlockExpr, nkBlockStmt}: result = copyNode(arg) result.add arg[0] @@ -572,13 +536,11 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode = ri2[i] = pArg(ri[i], c, isSink = true) result.add ri2 of nkSym: - if ri.sym.kind != skParam and isLastRead(ri, c): + if isSinkParam(ri.sym) or (ri.sym.kind != skParam and isLastRead(ri, c)): # Rule 3: `=sink`(x, z); wasMoved(z) - result = genSink(c, dest.typ, dest, ri) - result.add p(ri, c) - elif isSinkParam(ri.sym): - result = genSink(c, dest.typ, dest, ri) - result.add destructiveMoveSink(ri, c) + var snk = genSink(c, dest.typ, dest, ri) + snk.add ri + result = newTree(nkStmtList, snk, genMagicCall(ri, c, "wasMoved", mWasMoved)) else: result = genCopy(c, dest.typ, dest, ri) result.add p(ri, c) @@ -607,7 +569,7 @@ proc p(n: PNode; c: var Con): PNode = c.addTopVar v # make sure it's destroyed at the end of the proc: if not isUnpackedTuple(it[0].sym): - c.addDestructor(v.sym, genDestroy(c, v.typ, v)) + c.destroys.add genDestroy(c, v.typ, v) if ri.kind != nkEmpty: let r = moveOrCopy(v, ri, c) result.add r @@ -633,7 +595,7 @@ proc p(n: PNode; c: var Con): PNode = sinkExpr.add n result.add sinkExpr result.add tmp - c.addDestructor(tmp.sym, genDestroy(c, n.typ, tmp)) + c.destroys.add genDestroy(c, n.typ, tmp) else: result = n of nkAsgn, nkFastAsgn: @@ -655,7 +617,7 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode = var c: Con c.owner = owner c.topLevelVars = newNodeI(nkVarSection, n.info) - c.destroys = initOrderedTable[int, (PSym, PNode)](32) + c.destroys = newNodeI(nkStmtList, n.info) c.graph = g c.emptyNode = newNodeI(nkEmpty, n.info) let cfg = constructCfg(owner, n) @@ -670,16 +632,15 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode = let params = owner.typ.n for i in 1 ..< params.len: let param = params[i].sym - if param.typ.kind == tySink: registerDropBit(c, param) + if param.typ.kind == tySink: + c.destroys.add genDestroy(c, param.typ.skipTypes({tyGenericInst, tyAlias, tySink}), params[i]) + let body = p(n, c) result = newNodeI(nkStmtList, n.info) if c.topLevelVars.len > 0: result.add c.topLevelVars if c.destroys.len > 0: - var destroy_list = newNodeI(nkStmtList, n.info) - for val in c.destroys.values: - destroy_list.add val.destroy_call - result.add newTryFinally(body, destroy_list) + result.add newTryFinally(body, c.destroys) else: result.add body From e5b9d89bcf15f34b54aeb95a8678b0223d1d9f7a Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Sat, 8 Dec 2018 19:20:34 +0000 Subject: [PATCH 026/110] style improvements --- compiler/destroyer.nim | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index 75cf86124..c5f49984e 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -116,7 +116,7 @@ Remarks: Rule 1.2 is not yet implemented because ``sink`` is currently import intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees, - strutils, options, dfa, lowerings, tables, modulegraphs, msgs, + strutils, options, dfa, lowerings, tables, modulegraphs, lineinfos, parampatterns const @@ -127,8 +127,7 @@ type owner: PSym g: ControlFlowGraph jumpTargets: IntSet - topLevelVars: PNode - destroys: PNode + destroys, topLevelVars: PNode graph: ModuleGraph emptyNode: PNode otherRead: PNode @@ -616,8 +615,8 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode = echo "injecting into ", n var c: Con c.owner = owner - c.topLevelVars = newNodeI(nkVarSection, n.info) c.destroys = newNodeI(nkStmtList, n.info) + c.topLevelVars = newNodeI(nkVarSection, n.info) c.graph = g c.emptyNode = newNodeI(nkEmpty, n.info) let cfg = constructCfg(owner, n) From a65141fc0b85ac5f1b62469aeefb2389b1d67ae5 Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Sat, 8 Dec 2018 13:36:38 -0600 Subject: [PATCH 027/110] daily cruft removal --- compiler/ccgcalls.nim | 20 -------------------- compiler/ccgexprs.nim | 4 ---- 2 files changed, 24 deletions(-) diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index b23cd598e..d177e1f88 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -63,26 +63,6 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, add(pl, ~");$n") line(p, cpsStmts, pl) -proc isInCurrentFrame(p: BProc, n: PNode): bool = - # checks if `n` is an expression that refers to the current frame; - # this does not work reliably because of forwarding + inlining can break it - case n.kind - of nkSym: - if n.sym.kind in {skVar, skResult, skTemp, skLet} and p.prc != nil: - result = p.prc.id == n.sym.owner.id - of nkDotExpr, nkBracketExpr: - if skipTypes(n.sons[0].typ, abstractInst).kind notin {tyVar,tyLent,tyPtr,tyRef}: - result = isInCurrentFrame(p, n.sons[0]) - of nkHiddenStdConv, nkHiddenSubConv, nkConv: - result = isInCurrentFrame(p, n.sons[1]) - of nkHiddenDeref, nkDerefExpr: - # what about: var x = addr(y); callAsOpenArray(x[])? - # *shrug* ``addr`` is unsafe anyway. - result = false - of nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr: - result = isInCurrentFrame(p, n.sons[0]) - else: discard - proc genBoundsCheck(p: BProc; arr, a, b: TLoc) proc openArrayLoc(p: BProc, n: PNode): Rope = diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 59ef05f9c..cab2c78f5 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -850,7 +850,6 @@ proc genUncheckedArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) = var a, b: TLoc initLocExpr(p, x, a) initLocExpr(p, y, b) - var ty = skipTypes(a.t, abstractVarRange + abstractPtrs + tyUserTypeClasses) d.inheritLocation(a) putIntoDest(p, d, n, ropecg(p.module, "$1[$2]", rdLoc(a), rdCharLoc(b)), a.storage) @@ -884,7 +883,6 @@ proc genCStringElem(p: BProc, n, x, y: PNode, d: var TLoc) = var a, b: TLoc initLocExpr(p, x, a) initLocExpr(p, y, b) - var ty = skipTypes(a.t, abstractVarRange) inheritLocation(d, a) putIntoDest(p, d, n, ropecg(p.module, "$1[$2]", rdLoc(a), rdCharLoc(b)), a.storage) @@ -1402,7 +1400,6 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) = else: var i: TLoc getTemp(p, getSysType(p.module.g.graph, unknownLineInfo(), tyInt), i) - let oldCode = p.s(cpsStmts) linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n", i.r, L.rope) initLoc(elem, locExpr, lodeTyp elemType(skipTypes(n.typ, abstractInst)), OnHeap) elem.r = ropecg(p.module, "$1$3[$2]", rdLoc(d), rdLoc(i), dataField(p)) @@ -2576,7 +2573,6 @@ proc genConstObjConstr(p: BProc; n: PNode): Rope = proc genConstSimpleList(p: BProc, n: PNode): Rope = var length = sonsLen(n) result = rope("{") - let t = n.typ.skipTypes(abstractInst) for i in countup(0, length - 2): addf(result, "$1,$n", [genNamedConstExpr(p, n.sons[i])]) if length > 0: From f838b1e6c14c8c505eea6e2107295f166c67f346 Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Wed, 5 Dec 2018 21:27:40 -0800 Subject: [PATCH 028/110] fix #9872: setLen now works properly at CT [backport] --- compiler/vm.nim | 18 ++---------------- tests/vm/tsetlen.nim | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 16 deletions(-) create mode 100644 tests/vm/tsetlen.nim diff --git a/compiler/vm.nim b/compiler/vm.nim index 7e7ec8903..c8784c3e7 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -413,26 +413,12 @@ proc recSetFlagIsRef(arg: PNode) = arg.sons[i].recSetFlagIsRef proc setLenSeq(c: PCtx; node: PNode; newLen: int; info: TLineInfo) = - # FIXME: this doesn't attempt to solve incomplete - # support of tyPtr, tyRef in VM. let typ = node.typ.skipTypes(abstractInst+{tyRange}-{tyTypeDesc}) - let typeEntry = typ.sons[0].skipTypes(abstractInst+{tyRange}-{tyTypeDesc}) - let typeKind = case typeEntry.kind - of tyUInt..tyUInt64: nkUIntLit - of tyRange, tyEnum, tyBool, tyChar, tyInt..tyInt64: nkIntLit - of tyFloat..tyFloat128: nkFloatLit - of tyString: nkStrLit - of tyObject: nkObjConstr - of tySequence: nkNilLit - of tyProc, tyTuple: nkTupleConstr - else: nkEmpty - let oldLen = node.len setLen(node.sons, newLen) if oldLen < newLen: - # TODO: This is still not correct for tyPtr, tyRef default value for i in oldLen ..< newLen: - node.sons[i] = newNodeI(typeKind, info) + node.sons[i] = getNullValue(typ.sons[0], info, c.config) const errIndexOutOfBounds = "index out of bounds" @@ -458,7 +444,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = #if c.traceActive: when traceCode: echo "PC ", pc, " ", c.code[pc].opcode, " ra ", ra, " rb ", instr.regB, " rc ", instr.regC - # message(c.config, c.debug[pc], warnUser, "Trace") + # message(c.config, c.debug[pc], warnUser, "Trace") case instr.opcode of opcEof: return regs[ra] diff --git a/tests/vm/tsetlen.nim b/tests/vm/tsetlen.nim new file mode 100644 index 000000000..9fd30f331 --- /dev/null +++ b/tests/vm/tsetlen.nim @@ -0,0 +1,30 @@ +type Foo = object + index: int + +block: + proc fun[T]() = + var foo: T + var n = 10 + + var foos: seq[T] + foos.setLen n + + n.inc + foos.setLen n + + for i in 0 ..< n: + let temp = foos[i] + when T is object: + doAssert temp.index == 0 + when T is ref object: + doAssert temp == nil + doAssert temp == foo + + static: + fun[Foo]() + fun[int]() + fun[float]() + fun[string]() + fun[(int, string)]() + fun[ref Foo]() + fun[seq[int]]() From 7a66616d741106d4c18ce2e8f843a8b5d31f6025 Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 8 Dec 2018 23:48:10 +0100 Subject: [PATCH 029/110] fixes #9889, fixes #9886 --- compiler/pragmas.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 3d8e5645b..247f6ad54 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -1138,7 +1138,7 @@ proc implicitPragmas*(c: PContext, sym: PSym, n: PNode, internalError(c.config, n.info, "implicitPragmas") inc i popInfoContext(c.config) - if sym.kind in routineKinds: mergePragmas(sym.ast, o) + if sym.kind in routineKinds and sym.ast != nil: mergePragmas(sym.ast, o) if lfExportLib in sym.loc.flags and sfExportc notin sym.flags: localError(c.config, n.info, ".dynlib requires .exportc") From ae24b872191bead0ed2ba456fb78903b9717f107 Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Sat, 8 Dec 2018 23:04:38 +0000 Subject: [PATCH 030/110] Double sink checks --- compiler/destroyer.nim | 66 ++++++++++++++++++++++++++++++++---- tests/destructor/tmatrix.nim | 12 +++---- 2 files changed, 65 insertions(+), 13 deletions(-) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index c5f49984e..bed60a3e0 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -116,7 +116,7 @@ Remarks: Rule 1.2 is not yet implemented because ``sink`` is currently import intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees, - strutils, options, dfa, lowerings, tables, modulegraphs, + strutils, options, dfa, lowerings, tables, modulegraphs, msgs, lineinfos, parampatterns const @@ -128,6 +128,8 @@ type g: ControlFlowGraph jumpTargets: IntSet destroys, topLevelVars: PNode + tracingSinkedParams: bool # we aren't checking double sink for proc args in if, case, loops since they possibly not taken + alreadySinkedParams: Table[int, TLineInfo] graph: ModuleGraph emptyNode: PNode otherRead: PNode @@ -365,6 +367,16 @@ proc destructiveMoveVar(n: PNode; c: var Con): PNode = result.add genWasMoved(n, c) result.add tempAsNode +proc sinkParamConsumed(c: var Con, s: PNode, tracing = true) = + assert s.kind == nkSym + let isConsumed = + if c.tracingSinkedParams and tracing: + c.alreadySinkedParams.hasKeyOrPut(s.sym.id, s.info) + else: c.alreadySinkedParams.hasKey(s.sym.id) + if isConsumed: + localError(c.graph.config, s.info, "sink parameter `" & $s.sym.name.s & + "` is already consumed at " & toFileLineCol(c. graph.config, c.alreadySinkedParams[s.sym.id])) + proc passCopyToSink(n: PNode; c: var Con): PNode = result = newNodeIT(nkStmtListExpr, n.info, n.typ) let tmp = getTemp(c, n.typ, n.info) @@ -399,10 +411,14 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode = elif arg.kind in {nkBracket, nkObjConstr, nkTupleConstr, nkBracket, nkCharLit..nkFloat128Lit}: discard "object construction to sink parameter: nothing to do" result = arg - elif arg.kind == nkSym and (isSinkParam(arg.sym) or - arg.sym.kind in InterestingSyms and isLastRead(arg, c)): - # it is the last read be final consumption. We need to reset the memory - # to disable the destructor which we have not elided: + elif arg.kind == nkSym and isSinkParam(arg.sym): + # Sinked params can be consumed only once. We need to reset the memory + # to disable the destructor which we have not elided + result = destructiveMoveVar(arg, c) + sinkParamConsumed(c, arg) + elif arg.kind == nkSym and arg.sym.kind in InterestingSyms and isLastRead(arg, c): + # it is the last read, can be sinked. We need to reset the memory + # to disable the destructor which we have not elided result = destructiveMoveVar(arg, c) elif arg.kind in {nkBlockExpr, nkBlockStmt}: result = copyNode(arg) @@ -415,6 +431,7 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode = result.add pArg(arg[^1], c, isSink) elif arg.kind in {nkIfExpr, nkIfStmt}: result = copyNode(arg) + c.tracingSinkedParams = false for i in 0.. Date: Sat, 8 Dec 2018 23:05:45 +0000 Subject: [PATCH 031/110] fix --- compiler/destroyer.nim | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index bed60a3e0..b14615e40 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -647,6 +647,7 @@ proc p(n: PNode; c: var Con): PNode = c.tracingSinkedParams = false for i in 1.. Date: Sun, 9 Dec 2018 00:05:57 +0000 Subject: [PATCH 032/110] change approach --- compiler/lookups.nim | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/lookups.nim b/compiler/lookups.nim index 91d6bd745..db03ac2e0 100644 --- a/compiler/lookups.nim +++ b/compiler/lookups.nim @@ -169,8 +169,7 @@ proc ensureNoMissingOrUnusedSymbols(c: PContext; scope: PScope) = getSymRepr(c.config, s)) inc missingImpls elif {sfUsed, sfExported} * s.flags == {}: - if s.kind notin {skForVar, skParam, skMethod, skUnknown, skGenericParam} and - not (s.kind == skEnumField and {sfUsed, sfExported} * s.owner.flags != {}): + if s.kind notin {skForVar, skParam, skMethod, skUnknown, skGenericParam, skEnumField}: # XXX: implicit type params are currently skTypes # maybe they can be made skGenericParam as well. if s.typ != nil and tfImplicitTypeParam notin s.typ.flags and From b0f860d90fefc89219c1e2bc9f8815cde07a7b7c Mon Sep 17 00:00:00 2001 From: Neelesh Chandola Date: Sun, 9 Dec 2018 10:25:04 +0530 Subject: [PATCH 033/110] Fix enum regression --- compiler/semtypes.nim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index a011a8fc8..294cabe47 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -90,6 +90,8 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType = if sonsLen(v) == 2: strVal = v.sons[1] # second tuple part is the string value if skipTypes(strVal.typ, abstractInst).kind in {tyString, tyCString}: + if not isOrdinalType(v.sons[0].typ): + localError(c.config, v.sons[0].info, errOrdinalTypeExpected) x = getOrdValue(v.sons[0]) # first tuple part is the ordinal else: localError(c.config, strVal.info, errStringLiteralExpected) From 93503c18aa8d649a9a128d80d40430d7f9e6aa21 Mon Sep 17 00:00:00 2001 From: Neelesh Chandola Date: Sun, 9 Dec 2018 10:33:20 +0530 Subject: [PATCH 034/110] Add test --- tests/errmsgs/t9908.nim | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/errmsgs/t9908.nim diff --git a/tests/errmsgs/t9908.nim b/tests/errmsgs/t9908.nim new file mode 100644 index 000000000..ca135ed50 --- /dev/null +++ b/tests/errmsgs/t9908.nim @@ -0,0 +1,10 @@ +discard """ +errormsg: "Error: ordinal type expected" +line: 10 +""" + +# https://github.com/nim-lang/Nim/issues/9908 + +type + X = enum + a = ("a", "b") From abdfbd07a5a4c63456c4bfa2823ee3ebc25dda8f Mon Sep 17 00:00:00 2001 From: Neelesh Chandola Date: Sun, 9 Dec 2018 10:35:30 +0530 Subject: [PATCH 035/110] Fixes #9907 --- lib/pure/includes/oserr.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/includes/oserr.nim b/lib/pure/includes/oserr.nim index 72c3f4f49..45066e443 100644 --- a/lib/pure/includes/oserr.nim +++ b/lib/pure/includes/oserr.nim @@ -59,7 +59,7 @@ proc raiseOSError*(errorCode: OSErrorCode; additionalInfo = "") {.noinline.} = e.errorCode = errorCode.int32 e.msg = osErrorMsg(errorCode) if additionalInfo.len > 0: - e.msg.add "; Additional info: " + e.msg.add "Additional info: " e.msg.addQuoted additionalInfo if e.msg == "": e.msg = "unknown OS error" From d977fc6f320ea7aed97de0d883b6da27f7de61c4 Mon Sep 17 00:00:00 2001 From: Neelesh Chandola Date: Sun, 9 Dec 2018 11:20:52 +0530 Subject: [PATCH 036/110] Fix test case expected output --- tests/errmsgs/t9908.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/errmsgs/t9908.nim b/tests/errmsgs/t9908.nim index ca135ed50..fa086517f 100644 --- a/tests/errmsgs/t9908.nim +++ b/tests/errmsgs/t9908.nim @@ -1,5 +1,5 @@ discard """ -errormsg: "Error: ordinal type expected" +errormsg: "ordinal type expected" line: 10 """ From 9aa783624d133efd15e6720b5b59872258ee39fe Mon Sep 17 00:00:00 2001 From: Neelesh Chandola Date: Sun, 9 Dec 2018 12:33:58 +0530 Subject: [PATCH 037/110] `include` now accepts collective arguments --- compiler/semstmts.nim | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 48aa75528..7be4f6f05 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1836,17 +1836,33 @@ proc semMacroDef(c: PContext, n: PNode): PNode = if n.sons[bodyPos].kind == nkEmpty: localError(c.config, n.info, errImplOfXexpected % s.name.s) +proc incMod(c: PContext, n: PNode, it: PNode, includeStmtResult: PNode) = + var f = checkModuleName(c.config, it) + if f != InvalidFileIDX: + if containsOrIncl(c.includedFiles, f.int): + localError(c.config, n.info, errRecursiveDependencyX % toFilename(c.config, f)) + else: + addSon(includeStmtResult, semStmt(c, c.graph.includeFileCallback(c.graph, c.module, f), {})) + excl(c.includedFiles, f.int) + proc evalInclude(c: PContext, n: PNode): PNode = result = newNodeI(nkStmtList, n.info) addSon(result, n) for i in countup(0, sonsLen(n) - 1): - var f = checkModuleName(c.config, n.sons[i]) - if f != InvalidFileIDX: - if containsOrIncl(c.includedFiles, f.int): - localError(c.config, n.info, errRecursiveDependencyX % toFilename(c.config, f)) - else: - addSon(result, semStmt(c, c.graph.includeFileCallback(c.graph, c.module, f), {})) - excl(c.includedFiles, f.int) + var imp: PNode + let it = n.sons[i] + if it.kind == nkInfix and it.len == 3 and it[2].kind == nkBracket: + let sep = it[0] + let dir = it[1] + imp = newNodeI(nkInfix, it.info) + imp.add sep + imp.add dir + imp.add sep # dummy entry, replaced in the loop + for x in it[2]: + imp.sons[2] = x + incMod(c, n, imp, result) + else: + incMod(c, n, it, result) proc setLine(n: PNode, info: TLineInfo) = for i in 0 ..< safeLen(n): setLine(n.sons[i], info) From f77ddccb6c20acd0b8752dbd8d8040184f6460dc Mon Sep 17 00:00:00 2001 From: Neelesh Chandola Date: Sun, 9 Dec 2018 13:56:11 +0530 Subject: [PATCH 038/110] add tests --- tests/modules/t9627.nim | 7 +++++++ tests/modules/t9627/a.nim | 1 + tests/modules/t9627/b.nim | 1 + 3 files changed, 9 insertions(+) create mode 100644 tests/modules/t9627.nim create mode 100644 tests/modules/t9627/a.nim create mode 100644 tests/modules/t9627/b.nim diff --git a/tests/modules/t9627.nim b/tests/modules/t9627.nim new file mode 100644 index 000000000..be82edc45 --- /dev/null +++ b/tests/modules/t9627.nim @@ -0,0 +1,7 @@ +discard """ + output: "109" +""" + +include t9627 / [a, b] + +echo a, b \ No newline at end of file diff --git a/tests/modules/t9627/a.nim b/tests/modules/t9627/a.nim new file mode 100644 index 000000000..ef0c69db1 --- /dev/null +++ b/tests/modules/t9627/a.nim @@ -0,0 +1 @@ +var a = 10 \ No newline at end of file diff --git a/tests/modules/t9627/b.nim b/tests/modules/t9627/b.nim new file mode 100644 index 000000000..e9c9abf87 --- /dev/null +++ b/tests/modules/t9627/b.nim @@ -0,0 +1 @@ +var b = 9 \ No newline at end of file From 81427b535d2bf77755b5767e2ba8ecd61ec02c79 Mon Sep 17 00:00:00 2001 From: Neelesh Chandola Date: Sun, 9 Dec 2018 13:57:17 +0530 Subject: [PATCH 039/110] Add final newlines --- tests/modules/t9627.nim | 2 +- tests/modules/t9627/a.nim | 2 +- tests/modules/t9627/b.nim | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/modules/t9627.nim b/tests/modules/t9627.nim index be82edc45..646f030a1 100644 --- a/tests/modules/t9627.nim +++ b/tests/modules/t9627.nim @@ -4,4 +4,4 @@ discard """ include t9627 / [a, b] -echo a, b \ No newline at end of file +echo a, b diff --git a/tests/modules/t9627/a.nim b/tests/modules/t9627/a.nim index ef0c69db1..0dd32430e 100644 --- a/tests/modules/t9627/a.nim +++ b/tests/modules/t9627/a.nim @@ -1 +1 @@ -var a = 10 \ No newline at end of file +var a = 10 diff --git a/tests/modules/t9627/b.nim b/tests/modules/t9627/b.nim index e9c9abf87..2806a78ed 100644 --- a/tests/modules/t9627/b.nim +++ b/tests/modules/t9627/b.nim @@ -1 +1 @@ -var b = 9 \ No newline at end of file +var b = 9 From e44641b6cb025b689298584418e91844b1ac5a4a Mon Sep 17 00:00:00 2001 From: Neelesh Chandola Date: Sun, 9 Dec 2018 14:20:01 +0530 Subject: [PATCH 040/110] Float values are invalid in enum --- compiler/semtypes.nim | 2 ++ tests/errmsgs/{t9908.nim => t9908_01.nim} | 4 ++-- tests/errmsgs/t9908_02.nim | 10 ++++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) rename tests/errmsgs/{t9908.nim => t9908_01.nim} (75%) create mode 100644 tests/errmsgs/t9908_02.nim diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 294cabe47..4cc759e52 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -100,6 +100,8 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType = of tyString, tyCString: strVal = v x = counter + of tyFloat..tyFloat128: + localError(c.config, v.info, errOrdinalTypeExpected) else: x = getOrdValue(v) if i != 1: diff --git a/tests/errmsgs/t9908.nim b/tests/errmsgs/t9908_01.nim similarity index 75% rename from tests/errmsgs/t9908.nim rename to tests/errmsgs/t9908_01.nim index fa086517f..b9d37b67b 100644 --- a/tests/errmsgs/t9908.nim +++ b/tests/errmsgs/t9908_01.nim @@ -6,5 +6,5 @@ line: 10 # https://github.com/nim-lang/Nim/issues/9908 type - X = enum - a = ("a", "b") + X = enum + a = ("a", "b") diff --git a/tests/errmsgs/t9908_02.nim b/tests/errmsgs/t9908_02.nim new file mode 100644 index 000000000..7ff3d1ff7 --- /dev/null +++ b/tests/errmsgs/t9908_02.nim @@ -0,0 +1,10 @@ +discard """ +errormsg: "ordinal type expected" +line: 10 +""" + +# https://github.com/nim-lang/Nim/pull/9909#issuecomment-445519287 + +type + E = enum + myVal = 80.9 From 96647618c289dc5ed025c141b4f7c8c191d4ab2b Mon Sep 17 00:00:00 2001 From: Neelesh Chandola Date: Sun, 9 Dec 2018 15:44:18 +0530 Subject: [PATCH 041/110] Fix compilation of test on linux and mac --- tests/modules/{t9627 => m9627}/a.nim | 0 tests/modules/{t9627 => m9627}/b.nim | 0 tests/modules/t9627.nim | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) rename tests/modules/{t9627 => m9627}/a.nim (100%) rename tests/modules/{t9627 => m9627}/b.nim (100%) diff --git a/tests/modules/t9627/a.nim b/tests/modules/m9627/a.nim similarity index 100% rename from tests/modules/t9627/a.nim rename to tests/modules/m9627/a.nim diff --git a/tests/modules/t9627/b.nim b/tests/modules/m9627/b.nim similarity index 100% rename from tests/modules/t9627/b.nim rename to tests/modules/m9627/b.nim diff --git a/tests/modules/t9627.nim b/tests/modules/t9627.nim index 646f030a1..daba46374 100644 --- a/tests/modules/t9627.nim +++ b/tests/modules/t9627.nim @@ -2,6 +2,6 @@ discard """ output: "109" """ -include t9627 / [a, b] +include m9627 / [a, b] echo a, b From 04a4ff56715aac0e7bef2abe62fa451c7c42d4e9 Mon Sep 17 00:00:00 2001 From: Neelesh Chandola Date: Sun, 9 Dec 2018 15:54:53 +0530 Subject: [PATCH 042/110] Fixes #9913 --- koch.nim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/koch.nim b/koch.nim index 9a8d38a79..bd10224b6 100644 --- a/koch.nim +++ b/koch.nim @@ -79,6 +79,7 @@ template withDir(dir, body) = finally: setCurrentdir(old) +let origDir = getCurrentDir() setCurrentDir(getAppDir()) proc tryExec(cmd: string): bool = @@ -415,6 +416,7 @@ proc temp(args: string) = let nimexec = findNim() exec(nimexec & " c -d:debug --debugger:native " & bootArgs & " " & (d / "compiler" / "nim"), 125) copyExe(output, finalDest) + setCurrentDir(origDir) if programArgs.len > 0: exec(finalDest & " " & programArgs) proc xtemp(cmd: string) = From dc935f2b4115332d440421485e75189d7b9c7c9e Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Sun, 9 Dec 2018 18:32:43 +0000 Subject: [PATCH 043/110] use control flow graph for sink params --- compiler/destroyer.nim | 55 ++++++++++-------------------------- compiler/dfa.nim | 2 +- tests/destructor/tmatrix.nim | 10 +++++-- 3 files changed, 23 insertions(+), 44 deletions(-) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index b14615e40..1d4cdcc9b 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -128,7 +128,6 @@ type g: ControlFlowGraph jumpTargets: IntSet destroys, topLevelVars: PNode - tracingSinkedParams: bool # we aren't checking double sink for proc args in if, case, loops since they possibly not taken alreadySinkedParams: Table[int, TLineInfo] graph: ModuleGraph emptyNode: PNode @@ -367,15 +366,14 @@ proc destructiveMoveVar(n: PNode; c: var Con): PNode = result.add genWasMoved(n, c) result.add tempAsNode -proc sinkParamConsumed(c: var Con, s: PNode, tracing = true) = - assert s.kind == nkSym - let isConsumed = - if c.tracingSinkedParams and tracing: - c.alreadySinkedParams.hasKeyOrPut(s.sym.id, s.info) - else: c.alreadySinkedParams.hasKey(s.sym.id) - if isConsumed: - localError(c.graph.config, s.info, "sink parameter `" & $s.sym.name.s & - "` is already consumed at " & toFileLineCol(c. graph.config, c.alreadySinkedParams[s.sym.id])) +proc sinkParamIsLastReadCheck(c: var Con, s: PNode) = + assert s.kind == nkSym and s.sym.kind == skParam + discard isLastRead(s, c) + if c.otherRead != nil: + localError(c.graph.config, c.otherRead.info, "sink parameter `" & $s.sym.name.s & + "` is already consumed at " & toFileLineCol(c. graph.config, s.info)) + else: + c.alreadySinkedParams[s.sym.id] = s.info proc passCopyToSink(n: PNode; c: var Con): PNode = result = newNodeIT(nkStmtListExpr, n.info, n.typ) @@ -414,8 +412,8 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode = elif arg.kind == nkSym and isSinkParam(arg.sym): # Sinked params can be consumed only once. We need to reset the memory # to disable the destructor which we have not elided + sinkParamIsLastReadCheck(c, arg) result = destructiveMoveVar(arg, c) - sinkParamConsumed(c, arg) elif arg.kind == nkSym and arg.sym.kind in InterestingSyms and isLastRead(arg, c): # it is the last read, can be sinked. We need to reset the memory # to disable the destructor which we have not elided @@ -431,7 +429,6 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode = result.add pArg(arg[^1], c, isSink) elif arg.kind in {nkIfExpr, nkIfStmt}: result = copyNode(arg) - c.tracingSinkedParams = false for i in 0.. Date: Sun, 9 Dec 2018 18:37:33 +0000 Subject: [PATCH 044/110] remove not used code --- compiler/destroyer.nim | 8 -------- 1 file changed, 8 deletions(-) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index 1d4cdcc9b..32d6c253b 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -128,7 +128,6 @@ type g: ControlFlowGraph jumpTargets: IntSet destroys, topLevelVars: PNode - alreadySinkedParams: Table[int, TLineInfo] graph: ModuleGraph emptyNode: PNode otherRead: PNode @@ -372,8 +371,6 @@ proc sinkParamIsLastReadCheck(c: var Con, s: PNode) = if c.otherRead != nil: localError(c.graph.config, c.otherRead.info, "sink parameter `" & $s.sym.name.s & "` is already consumed at " & toFileLineCol(c. graph.config, s.info)) - else: - c.alreadySinkedParams[s.sym.id] = s.info proc passCopyToSink(n: PNode; c: var Con): PNode = result = newNodeIT(nkStmtListExpr, n.info, n.typ) @@ -625,10 +622,6 @@ proc p(n: PNode; c: var Con): PNode = recurse(n, result) of nkSym: result = n - if c.alreadySinkedParams.hasKey n.sym.id: - # non desctructive use before sink is fine, but after sink it is an error - localError(c.graph.config, n.info, "sink parameter `" & $n.sym.name.s & - "` is already consumed at " & toFileLineCol(c. graph.config, c.alreadySinkedParams[n.sym.id])) of nkNone..pred(nkSym), succ(nkSym) .. nkNilLit, nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef, nkIteratorDef, nkMacroDef, nkTemplateDef, nkLambda, nkDo, nkFuncDef: @@ -644,7 +637,6 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode = c.owner = owner c.destroys = newNodeI(nkStmtList, n.info) c.topLevelVars = newNodeI(nkVarSection, n.info) - c.alreadySinkedParams = initTable[int, TLineInfo](8) c.graph = g c.emptyNode = newNodeI(nkEmpty, n.info) let cfg = constructCfg(owner, n) From 8a690fd5307bc485ad2ac5ef6885d7b4fcfb4507 Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Sun, 9 Dec 2018 18:38:21 +0000 Subject: [PATCH 045/110] Remove not used code --- compiler/destroyer.nim | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index 32d6c253b..a090bead2 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -620,10 +620,7 @@ proc p(n: PNode; c: var Con): PNode = else: result = copyNode(n) recurse(n, result) - of nkSym: - result = n - - of nkNone..pred(nkSym), succ(nkSym) .. nkNilLit, nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef, + of nkNone .. nkNilLit, nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef, nkIteratorDef, nkMacroDef, nkTemplateDef, nkLambda, nkDo, nkFuncDef: result = n else: From 8b7f416c37d88599fd8fb9f88480584f191562de Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Sun, 9 Dec 2018 18:40:46 +0000 Subject: [PATCH 046/110] reduce changes --- compiler/destroyer.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index a090bead2..7d2bb7221 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -620,7 +620,7 @@ proc p(n: PNode; c: var Con): PNode = else: result = copyNode(n) recurse(n, result) - of nkNone .. nkNilLit, nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef, + of nkNone..nkNilLit, nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef, nkIteratorDef, nkMacroDef, nkTemplateDef, nkLambda, nkDo, nkFuncDef: result = n else: From f3ecc15a94c12b149f0665d250af1d71dd128721 Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Thu, 6 Dec 2018 15:42:44 -0800 Subject: [PATCH 047/110] refs #9880 show index and bound in lots of `index out of bounds` errors --- compiler/ccgexprs.nim | 12 ++++++------ compiler/cgen.nim | 2 ++ compiler/semfold.nim | 8 +++++--- lib/pure/collections/sharedstrings.nim | 6 ++++-- lib/pure/subexes.nim | 4 ++-- lib/system/chcks.nim | 9 ++++++++- lib/system/helpers2.nim | 5 +++++ tests/misc/tinvalidarrayaccess.nim | 25 ++++++++++++++++--------- tests/misc/tinvalidarrayaccess2.nim | 16 ++++++++++++++++ 9 files changed, 64 insertions(+), 23 deletions(-) create mode 100644 lib/system/helpers2.nim create mode 100644 tests/misc/tinvalidarrayaccess2.nim diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 59ef05f9c..6b3b9b63f 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -867,15 +867,15 @@ proc genArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) = # semantic pass has already checked for const index expressions if firstOrd(p.config, ty) == 0: if (firstOrd(p.config, b.t) < firstOrd(p.config, ty)) or (lastOrd(p.config, b.t) > lastOrd(p.config, ty)): - linefmt(p, cpsStmts, "if ((NU)($1) > (NU)($2)) #raiseIndexError();$n", + linefmt(p, cpsStmts, "if ((NU)($1) > (NU)($2)) #raiseIndexError2($1, $2);$n", rdCharLoc(b), intLiteral(lastOrd(p.config, ty))) else: - linefmt(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseIndexError();$n", + linefmt(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseIndexError3($1, $2, $3);$n", rdCharLoc(b), first, intLiteral(lastOrd(p.config, ty))) else: let idx = getOrdValue(y) if idx < firstOrd(p.config, ty) or idx > lastOrd(p.config, ty): - localError(p.config, x.info, "index out of bounds") + localError(p.config, x.info, formatErrorIndexBound(idx, firstOrd(p.config, ty), lastOrd(p.config, ty))) d.inheritLocation(a) putIntoDest(p, d, n, ropecg(p.module, "$1[($2)- $3]", rdLoc(a), rdCharLoc(b), first), a.storage) @@ -915,7 +915,7 @@ proc genOpenArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) = initLocExpr(p, x, a) initLocExpr(p, y, b) # emit range check: if optBoundsCheck in p.options: - linefmt(p, cpsStmts, "if ((NU)($1) >= (NU)($2Len_0)) #raiseIndexError();$n", + linefmt(p, cpsStmts, "if ((NU)($1) >= (NU)($2Len_0)) #raiseIndexError2($1,$2Len_0-1);$n", rdLoc(b), rdLoc(a)) # BUGFIX: ``>=`` and not ``>``! inheritLocation(d, a) putIntoDest(p, d, n, @@ -931,11 +931,11 @@ proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) = if optBoundsCheck in p.options: if ty.kind == tyString and (not defined(nimNoZeroTerminator) or optLaxStrings in p.options): linefmt(p, cpsStmts, - "if ((NU)($1) > (NU)$2) #raiseIndexError();$n", + "if ((NU)($1) > (NU)$2) #raiseIndexError2($1,$2);$n", rdLoc(b), lenExpr(p, a)) else: linefmt(p, cpsStmts, - "if ((NU)($1) >= (NU)$2) #raiseIndexError();$n", + "if ((NU)($1) >= (NU)$2) #raiseIndexError2($1,$2-1);$n", rdLoc(b), lenExpr(p, a)) if d.k == locNone: d.storage = OnHeap if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}: diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 3545edc88..457a6e176 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -16,6 +16,8 @@ import condsyms, rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases, lowerings, tables, sets, ndi, lineinfos, pathutils, transf +import system/helpers2 + when not defined(leanCompiler): import semparallel diff --git a/compiler/semfold.nim b/compiler/semfold.nim index 5ec702257..305ed9bcf 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -15,6 +15,8 @@ import nversion, platform, math, msgs, os, condsyms, idents, renderer, types, commands, magicsys, modulegraphs, strtabs, lineinfos +import system/helpers2 + proc newIntNodeT*(intVal: BiggestInt, n: PNode; g: ModuleGraph): PNode = case skipTypes(n.typ, abstractVarRange).kind of tyInt: @@ -489,11 +491,11 @@ proc foldArrayAccess(m: PSym, n: PNode; g: ModuleGraph): PNode = result = x.sons[int(idx)] if result.kind == nkExprColonExpr: result = result.sons[1] else: - localError(g.config, n.info, "index out of bounds: " & $n) + localError(g.config, n.info, formatErrorIndexBound(idx, sonsLen(x)+1) & $n) of nkBracket: idx = idx - firstOrd(g.config, x.typ) if idx >= 0 and idx < x.len: result = x.sons[int(idx)] - else: localError(g.config, n.info, "index out of bounds: " & $n) + else: localError(g.config, n.info, formatErrorIndexBound(idx, x.len+1) & $n) of nkStrLit..nkTripleStrLit: result = newNodeIT(nkCharLit, x.info, n.typ) if idx >= 0 and idx < len(x.strVal): @@ -501,7 +503,7 @@ proc foldArrayAccess(m: PSym, n: PNode; g: ModuleGraph): PNode = elif idx == len(x.strVal) and optLaxStrings in g.config.options: discard else: - localError(g.config, n.info, "index out of bounds: " & $n) + localError(g.config, n.info, formatErrorIndexBound(idx, len(x.strVal)-1) & $n) else: discard proc foldFieldAccess(m: PSym, n: PNode; g: ModuleGraph): PNode = diff --git a/lib/pure/collections/sharedstrings.nim b/lib/pure/collections/sharedstrings.nim index 7e9de4b73..b283cd4b1 100644 --- a/lib/pure/collections/sharedstrings.nim +++ b/lib/pure/collections/sharedstrings.nim @@ -12,6 +12,8 @@ type UncheckedCharArray = UncheckedArray[char] +import system/helpers2 + type Buffer = ptr object refcount: int @@ -49,11 +51,11 @@ proc len*(s: SharedString): int = s.len proc `[]`*(s: SharedString; i: Natural): char = if i < s.len: result = s.buffer.data[i+s.first] - else: raise newException(IndexError, "index out of bounds") + else: raise newException(IndexError, formatErrorIndexBound(i, s.len-1)) proc `[]=`*(s: var SharedString; i: Natural; value: char) = if i < s.len: s.buffer.data[i+s.first] = value - else: raise newException(IndexError, "index out of bounds") + else: raise newException(IndexError, formatErrorIndexBound(i, s.len-1)) proc `[]`*(s: SharedString; ab: HSlice[int, int]): SharedString = #incRef(src.buffer) diff --git a/lib/pure/subexes.nim b/lib/pure/subexes.nim index d103af710..638e71f04 100644 --- a/lib/pure/subexes.nim +++ b/lib/pure/subexes.nim @@ -17,7 +17,7 @@ from strutils import parseInt, cmpIgnoreStyle, Digits include "system/inclrtl" - +import system/helpers2 proc findNormalized(x: string, inArray: openarray[string]): int = var i = 0 @@ -85,7 +85,7 @@ proc getFormatArg(p: var FormatParser, a: openArray[string]): int = result = parseInt(a[result])-1 else: raiseInvalidFormat("'#', '$', number or identifier expected") - if result >=% a.len: raiseInvalidFormat("index out of bounds: " & $result) + if result >=% a.len: raiseInvalidFormat(formatErrorIndexBound(result, a.len)) p.i = i proc scanDollar(p: var FormatParser, a: openarray[string], s: var string) {. diff --git a/lib/system/chcks.nim b/lib/system/chcks.nim index d3651f659..6f4e8ce37 100644 --- a/lib/system/chcks.nim +++ b/lib/system/chcks.nim @@ -8,6 +8,7 @@ # # Implementation of some runtime checks. +import system/helpers2 proc raiseRangeError(val: BiggestInt) {.compilerproc, noinline.} = when hostOS == "standalone": @@ -15,6 +16,12 @@ proc raiseRangeError(val: BiggestInt) {.compilerproc, noinline.} = else: sysFatal(RangeError, "value out of range: ", $val) +proc raiseIndexError3(i, a, b: int) {.compilerproc, noinline.} = + sysFatal(IndexError, formatErrorIndexBound(i, a, b)) + +proc raiseIndexError2(i, n: int) {.compilerproc, noinline.} = + sysFatal(IndexError, formatErrorIndexBound(i, n)) + proc raiseIndexError() {.compilerproc, noinline.} = sysFatal(IndexError, "index out of bounds") @@ -25,7 +32,7 @@ proc chckIndx(i, a, b: int): int = if i >= a and i <= b: return i else: - raiseIndexError() + raiseIndexError3(i, a, b) proc chckRange(i, a, b: int): int = if i >= a and i <= b: diff --git a/lib/system/helpers2.nim b/lib/system/helpers2.nim new file mode 100644 index 000000000..1c9e7c068 --- /dev/null +++ b/lib/system/helpers2.nim @@ -0,0 +1,5 @@ +template formatErrorIndexBound*[T](i, a, b: T): string = + "index out of bounds: (a:" & $a & ") <= (i:" & $i & ") <= (b:" & $b & ") " + +template formatErrorIndexBound*[T](i, n: T): string = + "index out of bounds: (i:" & $i & ") <= (n:" & $n & ") " diff --git a/tests/misc/tinvalidarrayaccess.nim b/tests/misc/tinvalidarrayaccess.nim index 03105b41b..57ad38b85 100644 --- a/tests/misc/tinvalidarrayaccess.nim +++ b/tests/misc/tinvalidarrayaccess.nim @@ -1,14 +1,21 @@ discard """ - errormsg: "index out of bounds" - line: 11 + errormsg: "index out of bounds: (a:0) <= (i:2) <= (b:1) " + line: 18 """ +block: + try: + let a = @[1,2] + echo a[3] + except Exception as e: + doAssert e.msg == "index out of bounds: (i:3) <= (n:1) " -type TTestArr = array[0..1, int16] -var f: TTestArr -f[0] = 30 -f[1] = 40 -f[2] = 50 -f[3] = 60 +block: + type TTestArr = array[0..1, int16] + var f: TTestArr + f[0] = 30 + f[1] = 40 + f[2] = 50 + f[3] = 60 -echo(repr(f)) + echo(repr(f)) diff --git a/tests/misc/tinvalidarrayaccess2.nim b/tests/misc/tinvalidarrayaccess2.nim new file mode 100644 index 000000000..86d349457 --- /dev/null +++ b/tests/misc/tinvalidarrayaccess2.nim @@ -0,0 +1,16 @@ +discard """ + errormsg: "index out of bounds: (a:0) <= (i:3) <= (b:1) " + line: 9 +""" + +# Note: merge in tinvalidarrayaccess.nim pending https://github.com/nim-lang/Nim/issues/9906 + +let a = [1,2] +echo a[3] + +when false: + # TOOD: this case is not yet handled, giving: "index out of bounds" + proc fun()= + let a = @[1,2] + echo a[3] + static: fun() From daaf50ae0383e4b8250cfca7cfe3cee27a0290d9 Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Sun, 9 Dec 2018 19:11:08 -0800 Subject: [PATCH 048/110] refs #9906; --errorMax:10 allows stopping after 10 errors --- compiler/commands.nim | 5 +++++ doc/advopt.txt | 1 + 2 files changed, 6 insertions(+) diff --git a/compiler/commands.nim b/compiler/commands.nim index fa17e9851..576a7dc7f 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -617,6 +617,11 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; of "run", "r": expectNoArg(conf, switch, arg, pass, info) incl(conf.globalOptions, optRun) + of "errormax": + # Note: `nim check` (etc) can overwrite this; + # `0` is meaningless and has same effect as `1` + expectArg(conf, switch, arg, pass, info) + conf.errorMax = parseInt(arg) of "verbosity": expectArg(conf, switch, arg, pass, info) let verbosity = parseInt(arg) diff --git a/doc/advopt.txt b/doc/advopt.txt index 7cd72f6c3..11af58392 100644 --- a/doc/advopt.txt +++ b/doc/advopt.txt @@ -103,6 +103,7 @@ Advanced options: value = number of processors (0 for auto-detect) --incremental:on|off only recompile the changed modules (experimental!) --verbosity:0|1|2|3 set Nim's verbosity level (1 is default) + --errorMax:int stop after n (>=1) errors in semantic pass --experimental:$1 enable experimental language feature -v, --version show detailed version information From fc7b3a7c2a223b04087426c3b7df9edc12ce1f03 Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Sun, 9 Dec 2018 21:45:15 -0800 Subject: [PATCH 049/110] enhance `dump --dump.format:json` --- compiler/main.nim | 18 +++++++++++++++++- doc/advopt.txt | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/compiler/main.nim b/compiler/main.nim index 6afe57d87..fb8fe8443 100644 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -266,11 +266,27 @@ proc mainCommand*(graph: ModuleGraph) = var libpaths = newJArray() for dir in conf.searchPaths: libpaths.elems.add(%dir.string) + var hints = block: # consider factoring with `listHints` + var ret = newJObject() + for a in hintMin..hintMax: + let key = lineinfos.HintsToStr[ord(a) - ord(hintMin)] + ret[key] = % (a in conf.notes) + ret + var warnings = block: # consider factoring with `listWarnings` + var ret = newJObject() + for a in warnMin..warnMax: + let key = lineinfos.WarningsToStr[ord(a) - ord(warnMin)] + ret[key] = % (a in conf.notes) + ret + var dumpdata = % [ (key: "version", val: %VersionAsString), (key: "project_path", val: %conf.projectFull.string), (key: "defined_symbols", val: definedSymbols), - (key: "lib_paths", val: libpaths) + (key: "lib_paths", val: %libpaths), + (key: "out", val: %conf.outFile.string), + (key: "hints", val: hints), + (key: "warnings", val: warnings), ] msgWriteln(conf, $dumpdata, {msgStdout, msgSkipHook}) diff --git a/doc/advopt.txt b/doc/advopt.txt index 7cd72f6c3..7677ba0d3 100644 --- a/doc/advopt.txt +++ b/doc/advopt.txt @@ -13,6 +13,7 @@ Advanced commands: //genDepend generate a DOT file containing the module dependency graph //dump dump all defined conditionals and search paths + see also: --dump.format:json (useful with: ` | jq`) //check checks the project for syntax and semantic Advanced options: From 9d10278a9ca0d90a5fe82fa6e7dfb7d7dcb0f38a Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Sun, 9 Dec 2018 23:39:57 -0800 Subject: [PATCH 050/110] --errorMax:0 means: unlimited --- compiler/commands.nim | 10 +++++++--- doc/advopt.txt | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/compiler/commands.nim b/compiler/commands.nim index 576a7dc7f..40283489c 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -618,10 +618,14 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; expectNoArg(conf, switch, arg, pass, info) incl(conf.globalOptions, optRun) of "errormax": - # Note: `nim check` (etc) can overwrite this; - # `0` is meaningless and has same effect as `1` expectArg(conf, switch, arg, pass, info) - conf.errorMax = parseInt(arg) + conf.errorMax = block: + # Note: `nim check` (etc) can overwrite this. + # `0` is meaningless, give it a useful meaning as in clang's -ferror-limit + # If user doesn't set this flag and the code doesn't either, it'd + # have the same effect as errorMax = 1 + let ret = parseInt(arg) + if ret == 0: high(int) else: ret of "verbosity": expectArg(conf, switch, arg, pass, info) let verbosity = parseInt(arg) diff --git a/doc/advopt.txt b/doc/advopt.txt index 11af58392..eca7b0a08 100644 --- a/doc/advopt.txt +++ b/doc/advopt.txt @@ -103,7 +103,7 @@ Advanced options: value = number of processors (0 for auto-detect) --incremental:on|off only recompile the changed modules (experimental!) --verbosity:0|1|2|3 set Nim's verbosity level (1 is default) - --errorMax:int stop after n (>=1) errors in semantic pass + --errorMax:int stop after n errors in semantic pass; 0 means unlimited --experimental:$1 enable experimental language feature -v, --version show detailed version information From d22fa090000689c550a644c37aefc21ba4f0dba1 Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Mon, 10 Dec 2018 09:20:43 +0000 Subject: [PATCH 051/110] minor correction --- compiler/destroyer.nim | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index 7d2bb7221..407204e51 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -367,8 +367,7 @@ proc destructiveMoveVar(n: PNode; c: var Con): PNode = proc sinkParamIsLastReadCheck(c: var Con, s: PNode) = assert s.kind == nkSym and s.sym.kind == skParam - discard isLastRead(s, c) - if c.otherRead != nil: + if not isLastRead(s, c): localError(c.graph.config, c.otherRead.info, "sink parameter `" & $s.sym.name.s & "` is already consumed at " & toFileLineCol(c. graph.config, s.info)) From 740c5b13ead2fe02691554ef9b585d7cb4ba19fa Mon Sep 17 00:00:00 2001 From: Charles Blake Date: Mon, 10 Dec 2018 11:40:08 -0500 Subject: [PATCH 052/110] Let handles be seen outside of `memfiles` module so that "updating" operations (like eg., resizing a file and re-mapping) do not need to worry about race conditions of re-opened paths, renamed parent directories and that sort of thing. Operating directly on already open handles is both safer and more efficient than relying upon the stability of filesystem paths. --- lib/pure/memfiles.nim | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim index e5345e645..61eff3295 100644 --- a/lib/pure/memfiles.nim +++ b/lib/pure/memfiles.nim @@ -36,11 +36,11 @@ type size*: int ## size of the memory mapped file when defined(windows): - fHandle: Handle - mapHandle: Handle - wasOpened: bool ## only close if wasOpened + fHandle*: Handle + mapHandle*: Handle + wasOpened*: bool ## only close if wasOpened else: - handle: cint + handle*: cint proc mapMem*(m: var MemFile, mode: FileMode = fmRead, mappedSize = -1, offset = 0): pointer = From 497e8c41e8a32ae96633d7a7e3011980e38f2b69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C8=98tefan=20Talpalaru?= Date: Mon, 10 Dec 2018 17:59:07 +0100 Subject: [PATCH 053/110] replace misleading "stack overflow" message on call depth limit The new error message looks like this: "Error: call depth limit reached in a debug build (2000 function calls). You can change it with -d:nimCallDepthLimit= or switch to a release build with -d:release." --- lib/system/excpt.nim | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim index a6da8f5a3..800b5cd2f 100644 --- a/lib/system/excpt.nim +++ b/lib/system/excpt.nim @@ -454,16 +454,18 @@ when not defined(gcDestructors): shallowCopy(result, e.trace) when defined(nimRequiresNimFrame): - proc stackOverflow() {.noinline.} = + const nimCallDepthLimit {.intdefine.} = 2000 + + proc callDepthLimitReached() {.noinline.} = writeStackTrace() - showErrorMessage("Stack overflow\n") + showErrorMessage("Error: call depth limit reached in a debug build (" & $nimCallDepthLimit & " function calls). You can change it with -d:nimCallDepthLimit= or switch to a release build with -d:release.\n") quitOrDebug() proc nimFrame(s: PFrame) {.compilerRtl, inl, exportc: "nimFrame".} = s.calldepth = if framePtr == nil: 0 else: framePtr.calldepth+1 s.prev = framePtr framePtr = s - if s.calldepth == 2000: stackOverflow() + if s.calldepth == nimCallDepthLimit: callDepthLimitReached() else: proc pushFrame(s: PFrame) {.compilerRtl, inl, exportc: "nimFrame".} = # XXX only for backwards compatibility From a9978db42f4f23c20ee9f87fe6d573907bbe3968 Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Mon, 10 Dec 2018 23:23:46 +0000 Subject: [PATCH 054/110] destructor_hotfix --- compiler/destroyer.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index 407204e51..40af11e70 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -647,7 +647,7 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode = let params = owner.typ.n for i in 1 ..< params.len: let param = params[i].sym - if param.typ.kind == tySink: + if param.typ.kind == tySink and hasDestructor(param.typ): c.destroys.add genDestroy(c, param.typ.skipTypes({tyGenericInst, tyAlias, tySink}), params[i]) let body = p(n, c) From 47c38cb98e6cde435fd38565cd374050955610eb Mon Sep 17 00:00:00 2001 From: Neelesh Chandola Date: Tue, 11 Dec 2018 10:34:10 +0530 Subject: [PATCH 055/110] Better fix --- compiler/semtypes.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 4cc759e52..eed82adeb 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -100,9 +100,9 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType = of tyString, tyCString: strVal = v x = counter - of tyFloat..tyFloat128: - localError(c.config, v.info, errOrdinalTypeExpected) else: + if not isOrdinalType(v.typ): + localError(c.config, v.info, errOrdinalTypeExpected) x = getOrdValue(v) if i != 1: if x != counter: incl(result.flags, tfEnumHasHoles) From 5aba5875dad9bcc52a995139ec7e65b26377c38b Mon Sep 17 00:00:00 2001 From: Neelesh Chandola Date: Tue, 11 Dec 2018 10:44:43 +0530 Subject: [PATCH 056/110] Address Comments --- lib/pure/includes/oserr.nim | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/pure/includes/oserr.nim b/lib/pure/includes/oserr.nim index 45066e443..abd0bf501 100644 --- a/lib/pure/includes/oserr.nim +++ b/lib/pure/includes/oserr.nim @@ -59,6 +59,7 @@ proc raiseOSError*(errorCode: OSErrorCode; additionalInfo = "") {.noinline.} = e.errorCode = errorCode.int32 e.msg = osErrorMsg(errorCode) if additionalInfo.len > 0: + if e.msg[^1] != '\n': e.msg.add '\n' e.msg.add "Additional info: " e.msg.addQuoted additionalInfo if e.msg == "": From 4ec40796e64a6cf9fa34eaaf7de880076f8c2859 Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 11 Dec 2018 10:25:26 +0100 Subject: [PATCH 057/110] fixes #9868 --- compiler/semfold.nim | 8 ++++++++ compiler/semmagic.nim | 2 -- tests/misc/tsizeof2.nim | 2 ++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/compiler/semfold.nim b/compiler/semfold.nim index 5ec702257..df6298eb0 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -626,6 +626,14 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode = # It doesn't matter if the argument is const or not for mLengthArray. # This fixes bug #544. result = newIntNodeT(lengthOrd(g.config, n.sons[1].typ), n, g) + of mSizeOf: + let size = getSize(g.config, n[1].typ) + if size >= 0: + result = newIntNode(nkIntLit, size) + result.info = n.info + result.typ = getSysType(g, n.info, tyInt) + else: + result = nil of mAstToStr: result = newStrNodeT(renderTree(n[1], {renderNoComments}), n, g) of mConStrStr: diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index df2c084a1..7e61854b8 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -321,8 +321,6 @@ proc semOf(c: PContext, n: PNode): PNode = proc magicsAfterOverloadResolution(c: PContext, n: PNode, flags: TExprFlags): PNode = ## This is the preferred code point to implement magics. - ## This function basically works like a macro, with the difference - ## that it is implemented in the compiler and not on the nimvm. ## ``c`` the current module, a symbol table to a very good approximation ## ``n`` the ast like it would be passed to a real macro ## ``flags`` Some flags for more contextual information on how the diff --git a/tests/misc/tsizeof2.nim b/tests/misc/tsizeof2.nim index 4252142d7..130f28e21 100644 --- a/tests/misc/tsizeof2.nim +++ b/tests/misc/tsizeof2.nim @@ -13,3 +13,5 @@ echo i # bug #9868 proc foo(a: SomeInteger): array[sizeof(a), byte] = discard + +discard foo(1) From 685a5544c4f319667c811b04128dc3f8f33a4230 Mon Sep 17 00:00:00 2001 From: Neelesh Chandola Date: Tue, 11 Dec 2018 16:49:36 +0530 Subject: [PATCH 058/110] tyProc does not require copying in JS codegen --- compiler/jsgen.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index a9813f5c5..4d22c4224 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -945,7 +945,7 @@ proc needsNoCopy(p: PProc; y: PNode): bool = else: return (mapType(y.typ) != etyBaseIndex and (skipTypes(y.typ, abstractInst).kind in - {tyRef, tyPtr, tyLent, tyVar, tyCString} + IntegralTypes)) + {tyRef, tyPtr, tyLent, tyVar, tyCString, tyProc} + IntegralTypes)) return true proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) = From 366b6be4fbd9e1ca602cc7a795d1c12a6590e776 Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 11 Dec 2018 12:31:32 +0100 Subject: [PATCH 059/110] compiler refactoring: TSymSeq is gone for good --- compiler/ast.nim | 3 +-- compiler/astalgo.nim | 6 +++--- compiler/cgmeth.nim | 6 +++--- compiler/modulegraphs.nim | 2 +- compiler/semdata.nim | 6 +++--- 5 files changed, 11 insertions(+), 12 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index 0247acb03..5f5f296cb 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -723,10 +723,9 @@ type sons*: TNodeSeq comment*: string - TSymSeq* = seq[PSym] TStrTable* = object # a table[PIdent] of PSym counter*: int - data*: TSymSeq + data*: seq[PSym] # -------------- backend information ------------------------------- TLocKind* = enum diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim index b2671d81e..60eecbdc5 100644 --- a/compiler/astalgo.nim +++ b/compiler/astalgo.nim @@ -507,7 +507,7 @@ proc strTableContains*(t: TStrTable, n: PSym): bool = h = nextTry(h, high(t.data)) result = false -proc strTableRawInsert(data: var TSymSeq, n: PSym) = +proc strTableRawInsert(data: var seq[PSym], n: PSym) = var h: Hash = n.name.h and high(data) if sfImmediate notin n.flags: # fast path: @@ -535,7 +535,7 @@ proc strTableRawInsert(data: var TSymSeq, n: PSym) = data[h] = n if favPos >= 0: swap data[h], data[favPos] -proc symTabReplaceRaw(data: var TSymSeq, prevSym: PSym, newSym: PSym) = +proc symTabReplaceRaw(data: var seq[PSym], prevSym: PSym, newSym: PSym) = assert prevSym.name.h == newSym.name.h var h: Hash = prevSym.name.h and high(data) while data[h] != nil: @@ -549,7 +549,7 @@ proc symTabReplace*(t: var TStrTable, prevSym: PSym, newSym: PSym) = symTabReplaceRaw(t.data, prevSym, newSym) proc strTableEnlarge(t: var TStrTable) = - var n: TSymSeq + var n: seq[PSym] newSeq(n, len(t.data) * GrowthFactor) for i in countup(0, high(t.data)): if t.data[i] != nil: strTableRawInsert(n, t.data[i]) diff --git a/compiler/cgmeth.nim b/compiler/cgmeth.nim index cba07446f..f5014fa8c 100644 --- a/compiler/cgmeth.nim +++ b/compiler/cgmeth.nim @@ -188,7 +188,7 @@ proc methodDef*(g: ModuleGraph; s: PSym, fromCache: bool) = elif sfBase notin s.flags: message(g.config, s.info, warnUseBase) -proc relevantCol(methods: TSymSeq, col: int): bool = +proc relevantCol(methods: seq[PSym], col: int): bool = # returns true iff the position is relevant var t = methods[0].typ.sons[col].skipTypes(skipPtrs) if t.kind == tyObject: @@ -206,7 +206,7 @@ proc cmpSignatures(a, b: PSym, relevantCols: IntSet): int = if (d != high(int)) and d != 0: return d -proc sortBucket(a: var TSymSeq, relevantCols: IntSet) = +proc sortBucket(a: var seq[PSym], relevantCols: IntSet) = # we use shellsort here; fast and simple var n = len(a) var h = 1 @@ -225,7 +225,7 @@ proc sortBucket(a: var TSymSeq, relevantCols: IntSet) = a[j] = v if h == 1: break -proc genDispatcher(g: ModuleGraph; methods: TSymSeq, relevantCols: IntSet): PSym = +proc genDispatcher(g: ModuleGraph; methods: seq[PSym], relevantCols: IntSet): PSym = var base = lastSon(methods[0].ast).sym result = base var paramLen = sonsLen(base.typ) diff --git a/compiler/modulegraphs.nim b/compiler/modulegraphs.nim index d05b301ae..63fa597ff 100644 --- a/compiler/modulegraphs.nim +++ b/compiler/modulegraphs.nim @@ -47,7 +47,7 @@ type doStopCompile*: proc(): bool {.closure.} usageSym*: PSym # for nimsuggest owners*: seq[PSym] - methods*: seq[tuple[methods: TSymSeq, dispatcher: PSym]] # needs serialization! + methods*: seq[tuple[methods: seq[PSym], dispatcher: PSym]] # needs serialization! systemModule*: PSym sysTypes*: array[TTypeKind, PType] compilerprocs*: TStrTable diff --git a/compiler/semdata.nim b/compiler/semdata.nim index bec4a59a4..735c6f6b1 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -100,8 +100,8 @@ type compilesContextId*: int # > 0 if we are in a ``compiles`` magic compilesContextIdGenerator*: int inGenericInst*: int # > 0 if we are instantiating a generic - converters*: TSymSeq # sequence of converters - patterns*: TSymSeq # sequence of pattern matchers + converters*: seq[PSym] + patterns*: seq[PSym] # sequence of pattern matchers optionStack*: seq[POptionEntry] symMapping*: TIdTable # every gensym'ed symbol needs to be mapped # to some new symbol in a generic instantiation @@ -239,7 +239,7 @@ proc newContext*(graph: ModuleGraph; module: PSym): PContext = result.typesWithOps = @[] result.features = graph.config.features -proc inclSym(sq: var TSymSeq, s: PSym) = +proc inclSym(sq: var seq[PSym], s: PSym) = var L = len(sq) for i in countup(0, L - 1): if sq[i].id == s.id: return From 369ac2dd2db036c591983839fcf4e6129a501be8 Mon Sep 17 00:00:00 2001 From: Charles Blake Date: Tue, 11 Dec 2018 10:27:27 -0500 Subject: [PATCH 060/110] Address dom96/Araq opinions in https://github.com/nim-lang/Nim/pull/9922 Updating accessors are also provided since the idea of this change is to allow "updating" operations external to the module which are by their very nature closely tied to module internals (as well as to OS interface details). --- lib/pure/memfiles.nim | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim index 61eff3295..b74242370 100644 --- a/lib/pure/memfiles.nim +++ b/lib/pure/memfiles.nim @@ -36,11 +36,26 @@ type size*: int ## size of the memory mapped file when defined(windows): - fHandle*: Handle - mapHandle*: Handle - wasOpened*: bool ## only close if wasOpened + fHandle: Handle + mapHandle: Handle + wasOpened: bool ## only close if wasOpened else: - handle*: cint + handle: cint + +when defined(windows): + proc fHandle*(m: MemFile): Handle = m.fHandle + proc mapHandle*(m: MemFile): Handle = m.mapHandle + proc wasOpened*(m: MemFile): bool = m.wasOpened + proc `fHandle=`*(m: var MemFile, fHandle: Handle) = + m.fHandle = fHandle + proc `mapHandle=`*(m: var MemFile, mapHandle: Handle) = + m.mapHandle = mapHandle + proc `wasOpened=`*(m: var MemFile, wasOpened: bool) = + m.wasOpened = wasOpened +else: + proc handle*(m: MemFile): cint = m.handle + proc `handle=`*(m: var MemFile, handle: cint) = + m.handle = handle proc mapMem*(m: var MemFile, mode: FileMode = fmRead, mappedSize = -1, offset = 0): pointer = From b92594572e485fabe4bacec500ba4f9409e234c8 Mon Sep 17 00:00:00 2001 From: Charles Blake Date: Tue, 11 Dec 2018 14:57:28 -0500 Subject: [PATCH 061/110] For now just implement `resize` per https://github.com/nim-lang/Nim/pull/9922 discussion (with special mremap usage on Linux, but ordinary munmap, mmap on other POSIX). Someone needs to do the when windows branch. --- lib/pure/memfiles.nim | 44 ++++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim index b74242370..d2beb629a 100644 --- a/lib/pure/memfiles.nim +++ b/lib/pure/memfiles.nim @@ -42,21 +42,6 @@ type else: handle: cint -when defined(windows): - proc fHandle*(m: MemFile): Handle = m.fHandle - proc mapHandle*(m: MemFile): Handle = m.mapHandle - proc wasOpened*(m: MemFile): bool = m.wasOpened - proc `fHandle=`*(m: var MemFile, fHandle: Handle) = - m.fHandle = fHandle - proc `mapHandle=`*(m: var MemFile, mapHandle: Handle) = - m.mapHandle = mapHandle - proc `wasOpened=`*(m: var MemFile, wasOpened: bool) = - m.wasOpened = wasOpened -else: - proc handle*(m: MemFile): cint = m.handle - proc `handle=`*(m: var MemFile, handle: cint) = - m.handle = handle - proc mapMem*(m: var MemFile, mode: FileMode = fmRead, mappedSize = -1, offset = 0): pointer = ## returns a pointer to a mapped portion of MemFile `m` @@ -296,6 +281,35 @@ proc flush*(f: var MemFile; attempts: Natural = 3) = if lastErr != EBUSY.OSErrorCode: raiseOSError(lastErr, "error flushing mapping") +proc resize*(f: var MemFile, newFileSize: int) = + ## resize and re-map the file underlying an ``allowRemap MemFile``. NOTE: + ## this assumes the entire file is mapped read-write at offset zero. Also, + ## the value of ``.mem`` will probably change. + when defined(windows): + discard #TODO This needs to be implemented. + else: + if f.handle == -1: + raise newException(IOError, + "Cannot resize MemFile opened with allowRemap=false") + if ftruncate(f.handle, newFileSize) == -1: + raiseOSError(osLastError()) + when defined(linux): #Maybe NetBSD, too? + #On Linux this can be over 100 times faster than a munmap,mmap cycle. + proc mremap(old: pointer; oldSize,newSize: csize; flags: cint): pointer {. + importc: "mremap", header: "" .} + let newAddr = mremap(f.mem, csize(f.size), csize(newFileSize), cint(1)) + if newAddr == cast[pointer](MAP_FAILED): + raiseOSError(osLastError()) + else: + if munmap(f.mem, f.size) != 0: + raiseOSError(osLastError()) + let newAddr = mmap(nil, newFileSize, PROT_READ or PROT_WRITE, + MAP_SHARED or MAP_POPULATE, f.handle, 0) + if newAddr == cast[pointer](MAP_FAILED): + raiseOSError(osLastError()) + f.mem = newAddr + f.size = newFileSize + proc close*(f: var MemFile) = ## closes the memory mapped file `f`. All changes are written back to the ## file system, if `f` was opened with write access. From fa6a9a21e04a7a4087f8758016932c91230560fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arne=20D=C3=B6ring?= Date: Wed, 21 Nov 2018 14:39:06 +0100 Subject: [PATCH 062/110] WIP --- testament/categories.nim | 2 ++ testament/specs.nim | 17 +++++++++----- testament/tester.nim | 50 +++++++++++++++++++++------------------- 3 files changed, 39 insertions(+), 30 deletions(-) diff --git a/testament/categories.nim b/testament/categories.nim index e1f173c26..6694e3f0e 100644 --- a/testament/categories.nim +++ b/testament/categories.nim @@ -521,6 +521,8 @@ proc processCategory(r: var TResults, cat: Category, options: string) = testNimblePackages(r, cat, pfAll) of "niminaction": testNimInAction(r, cat, options) + of "testament": + testTestament(r, cat, options) of "untestable": # We can't test it because it depends on a third party. discard # TODO: Move untestable tests to someplace else, i.e. nimble repo. diff --git a/testament/specs.nim b/testament/specs.nim index 86fc8bed4..a86544c27 100644 --- a/testament/specs.nim +++ b/testament/specs.nim @@ -25,6 +25,11 @@ type actionReject = "reject" actionRunNoSpec = "runNoSpec" + TOutputCheck* = enum + ocIgnore = "ignore" + ocEqual = "equal" + ocSubstr = "substr" + TResultEnum* = enum reNimcCrash, # nim compiler seems to have crashed reMsgsDiffer, # error messages differ @@ -51,6 +56,8 @@ type action*: TTestAction file*, cmd*: string input*: string + outputCheck*: TOutputCheck + sortoutput*: bool outp*: string line*, column*: int tfile*: string @@ -60,7 +67,6 @@ type ccodeCheck*: string maxCodeSize*: int err*: TResultEnum - substr*, sortoutput*: bool targets*: set[TTarget] nimout*: string @@ -145,14 +151,13 @@ proc parseSpec*(filename: string): TSpec = of "tline": discard parseInt(e.value, result.tline) of "tcolumn": discard parseInt(e.value, result.tcolumn) of "output": - result.action = actionRun - result.outp = e.value + result.outputCheck = ocEqual + result.outp = strip(e.value) of "input": result.input = e.value of "outputsub": - result.action = actionRun - result.outp = e.value - result.substr = true + result.outputCheck = ocSubstr + result.outp = strip(e.value) of "sortoutput": result.sortoutput = parseCfgBool(e.value) of "exitcode": diff --git a/testament/tester.nim b/testament/tester.nim index 59c0171b4..1c105c97f 100644 --- a/testament/tester.nim +++ b/testament/tester.nim @@ -328,11 +328,6 @@ proc nimoutCheck(test: TTest; expectedNimout: string; given: var TSpec) = given.err = reMsgsDiffer return -proc makeDeterministic(s: string): string = - var x = splitLines(s) - sort(x, system.cmp) - result = join(x, "\n") - proc compilerOutputTests(test: TTest, target: TTarget, given: var TSpec, expected: TSpec; r: var TResults) = var expectedmsg: string = "" @@ -350,27 +345,31 @@ proc compilerOutputTests(test: TTest, target: TTarget, given: var TSpec, if given.err == reSuccess: inc(r.passed) r.addResult(test, target, expectedmsg, givenmsg, given.err) -proc testSpec(r: var TResults, test: TTest, target = targetC) = +proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) = let tname = test.name.addFileExt(".nim") var expected: TSpec if test.action != actionRunNoSpec: expected = parseSpec(tname) - if test.action == actionRun and expected.action == actionCompile: - expected.action = actionRun else: specDefaults expected expected.action = actionRunNoSpec + expected.outputCheck = ocIgnore # this is default so it is unnecessary if expected.err == reIgnored: - r.addResult(test, target, "", "", reIgnored) + # targetC is a lie + r.addResult(test, targetC, "", "", reIgnored) inc(r.skipped) inc(r.total) return - if getEnv("NIM_COMPILE_TO_CPP", "false").string == "true" and target == targetC and expected.targets == {}: - expected.targets.incl(targetCpp) - elif expected.targets == {}: - expected.targets.incl(target) + expected.targets.incl targets + + # still no target specified at all + if expected.targets == {}: + if getEnv("NIM_COMPILE_TO_CPP", "false").string == "true": + expected.targets = {targetCpp} + else: + expected.targets = {targetC} for target in expected.targets: inc(r.total) @@ -433,9 +432,13 @@ proc testSpec(r: var TResults, test: TTest, target = targetC) = # to return other codes, but for us it is sufficient to know that it's not 0. if exitCode != 0: exitCode = 1 - let bufB = if expected.sortoutput: makeDeterministic(strip(buf.string)) - else: strip(buf.string) - let expectedOut = strip(expected.outp) + let bufB = + if expected.sortoutput: + var x = splitLines(strip(buf.string)) + sort(x, system.cmp) + join(x, "\n") + else: + strip(buf.string) if exitCode != expected.exitCode: r.addResult(test, target, "exitcode: " & $expected.exitCode, @@ -443,11 +446,11 @@ proc testSpec(r: var TResults, test: TTest, target = targetC) = bufB, reExitCodesDiffer) continue - if bufB != expectedOut and expected.action != actionRunNoSpec: - if not (expected.substr and expectedOut in bufB): - given.err = reOutputsDiffer - r.addResult(test, target, expected.outp, bufB, reOutputsDiffer) - continue + if (expected.outputCheck == ocEqual and bufB != expected.outp) or + (expected.outputCheck == ocSubstr and bufB notin expected.outp): + given.err = reOutputsDiffer + r.addResult(test, target, expected.outp, bufB, reOutputsDiffer) + continue compilerOutputTests(test, target, given, expected, r) continue @@ -495,11 +498,10 @@ proc testExec(r: var TResults, test: TTest) = if given.err == reSuccess: inc(r.passed) r.addResult(test, targetC, "", given.msg, given.err) -proc makeTest(test, options: string, cat: Category, action = actionCompile, +proc makeTest(test, options: string, cat: Category, env: string = ""): TTest = # start with 'actionCompile', will be overwritten in the spec: - result = TTest(cat: cat, name: test, options: options, - action: action, startTime: epochTime()) + result = TTest(cat: cat, name: test, options: options, startTime: epochTime()) when defined(windows): const From ef44c12a3460579bd4ca17111ce942e752c5fda6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arne=20D=C3=B6ring?= Date: Tue, 27 Nov 2018 23:38:44 +0100 Subject: [PATCH 063/110] kick taint mode --- .gitlab-ci.yml | 3 +-- .travis.yml | 2 +- appveyor.yml | 4 ++-- koch.nim | 4 +--- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 70ff59136..9f536e6c9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -53,9 +53,8 @@ test-windows: <<: *win_set_path_def script: - call ci\deps.bat - - nim c --taintMode:on testament\tester + - nim c testament\tester - testament\tester.exe --pedantic all tags: - windows - fast - diff --git a/.travis.yml b/.travis.yml index 4c3c687e2..abd115701 100644 --- a/.travis.yml +++ b/.travis.yml @@ -51,7 +51,7 @@ script: #- nimble install sdl1 #- nimble install jester@#head -y #- nimble install niminst - - nim c --taintMode:on -d:nimCoroutines testament/tester + - nim c -d:nimCoroutines testament/tester - testament/tester --pedantic all -d:nimCoroutines - nim c -o:bin/nimpretty nimpretty/nimpretty.nim - nim c -r nimpretty/tester.nim diff --git a/appveyor.yml b/appveyor.yml index a60831f9d..9c8525d72 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -53,8 +53,8 @@ build_script: # - nimble install opengl -y # - nimble install sdl1 -y # - nimble install jester@#head -y - - nim c --taintMode:on -d:nimCoroutines --os:genode -d:posix --compileOnly testament/tester - - nim c --taintMode:on -d:nimCoroutines testament/tester + - nim c -d:nimCoroutines --os:genode -d:posix --compileOnly testament/tester + - nim c -d:nimCoroutines testament/tester test_script: - testament\tester --pedantic all -d:nimCoroutines diff --git a/koch.nim b/koch.nim index bd10224b6..3f528a1b2 100644 --- a/koch.nim +++ b/koch.nim @@ -379,9 +379,7 @@ proc winRelease*() = template `|`(a, b): string = (if a.len > 0: a else: b) proc tests(args: string) = - # we compile the tester with taintMode:on to have a basic - # taint mode test :-) - nimexec "cc --taintMode:on --opt:speed testament/tester" + nimexec "cc --opt:speed testament/tester" # Since tests take a long time (on my machine), and we want to defy Murhpys # law - lets make sure the compiler really is freshly compiled! nimexec "c --lib:lib -d:release --opt:speed compiler/nim.nim" From 75e4a0098ab1bafff44169bc19ae2b13229b8c8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arne=20D=C3=B6ring?= Date: Tue, 27 Nov 2018 23:47:21 +0100 Subject: [PATCH 064/110] remove caas --- tests/caas/absurd_nesting.nim | 29 -------- tests/caas/absurd_nesting.txt | 29 -------- tests/caas/basic-recompile.txt | 10 --- tests/caas/compile-suggest.txt | 7 -- tests/caas/compile-then-def.txt | 11 --- tests/caas/completion_dot_syntax.txt | 9 --- tests/caas/completion_dot_syntax_dirty.nim | 25 ------- tests/caas/completion_dot_syntax_main.nim | 24 ------- tests/caas/def-def-compile.txt | 12 ---- tests/caas/def-then-compile.txt | 8 --- tests/caas/forward_declarations.nim | 15 ---- tests/caas/forward_declarations.txt | 9 --- tests/caas/forward_usages.txt | 17 ----- tests/caas/idetools_api.nim | 84 ---------------------- tests/caas/idetools_api.txt | 59 --------------- tests/caas/imported.nim | 3 - tests/caas/issue_416_template_shift.nim | 17 ----- tests/caas/issue_416_template_shift.txt | 14 ---- tests/caas/issue_452_export_shift.nim | 8 --- tests/caas/issue_452_export_shift.txt | 11 --- tests/caas/issue_477_dynamic_dispatch.nim | 19 ----- tests/caas/issue_477_dynamic_dispatch.txt | 5 -- tests/caas/its_full_of_procs.nim | 29 -------- tests/caas/its_full_of_procs.txt | 20 ------ tests/caas/main.nim | 7 -- tests/caas/main_dirty.nim | 14 ---- tests/caas/suggest-compile.txt | 13 ---- tests/caas/suggest-invalid-source.txt | 26 ------- 28 files changed, 534 deletions(-) delete mode 100644 tests/caas/absurd_nesting.nim delete mode 100644 tests/caas/absurd_nesting.txt delete mode 100644 tests/caas/basic-recompile.txt delete mode 100644 tests/caas/compile-suggest.txt delete mode 100644 tests/caas/compile-then-def.txt delete mode 100644 tests/caas/completion_dot_syntax.txt delete mode 100644 tests/caas/completion_dot_syntax_dirty.nim delete mode 100644 tests/caas/completion_dot_syntax_main.nim delete mode 100644 tests/caas/def-def-compile.txt delete mode 100644 tests/caas/def-then-compile.txt delete mode 100644 tests/caas/forward_declarations.nim delete mode 100644 tests/caas/forward_declarations.txt delete mode 100644 tests/caas/forward_usages.txt delete mode 100644 tests/caas/idetools_api.nim delete mode 100644 tests/caas/idetools_api.txt delete mode 100644 tests/caas/imported.nim delete mode 100644 tests/caas/issue_416_template_shift.nim delete mode 100644 tests/caas/issue_416_template_shift.txt delete mode 100644 tests/caas/issue_452_export_shift.nim delete mode 100644 tests/caas/issue_452_export_shift.txt delete mode 100644 tests/caas/issue_477_dynamic_dispatch.nim delete mode 100644 tests/caas/issue_477_dynamic_dispatch.txt delete mode 100644 tests/caas/its_full_of_procs.nim delete mode 100644 tests/caas/its_full_of_procs.txt delete mode 100644 tests/caas/main.nim delete mode 100644 tests/caas/main_dirty.nim delete mode 100644 tests/caas/suggest-compile.txt delete mode 100644 tests/caas/suggest-invalid-source.txt diff --git a/tests/caas/absurd_nesting.nim b/tests/caas/absurd_nesting.nim deleted file mode 100644 index 136d65cc7..000000000 --- a/tests/caas/absurd_nesting.nim +++ /dev/null @@ -1,29 +0,0 @@ -# Tries to test the full ownership path generated by idetools. - -proc lev1(t1: string) = - var temp = t1 - for i in 0..len(temp)-1: - temp[i] = chr(int(temp[i]) + 1) - - proc lev2(t2: string) = - var temp = t2 - for i in 0..len(temp)-1: - temp[i] = chr(int(temp[i]) + 1) - - proc lev3(t3: string) = - var temp = t3 - for i in 0..len(temp)-1: - temp[i] = chr(int(temp[i]) + 1) - - proc lev4(t4: string) = - var temp = t4 - for i in 0..len(temp)-1: - temp[i] = chr(int(temp[i]) + 1) - - echo temp & "(lev4)" - lev4(temp & "(lev3)") - lev3(temp & "(lev2)") - lev2(temp & "(lev1)") - -when isMainModule: - lev1("abcd") diff --git a/tests/caas/absurd_nesting.txt b/tests/caas/absurd_nesting.txt deleted file mode 100644 index 986e34836..000000000 --- a/tests/caas/absurd_nesting.txt +++ /dev/null @@ -1,29 +0,0 @@ -absurd_nesting.nim - -> c --verbosity:0 --hints:on -SuccessX - -> idetools --track:$TESTNIM,6,6 --def $SILENT -skVar\tabsurd_nesting.lev1.temp\tstring - -> idetools --track:$TESTNIM,21,13 --def $SILENT -skVar\tabsurd_nesting.lev1.lev2.lev3.lev4.temp\tstring - -> idetools --track:$TESTNIM,6,27 --def $SILENT -skForVar\tabsurd_nesting.lev1.i\tint - -> idetools --track:$TESTNIM,21,33 --def $SILENT -skForVar\tabsurd_nesting.lev1.lev1.lev3.lev4.i\tint - -> idetools --track:$TESTNIM,24,8 --def $SILENT -skProc\tabsurd_nesting.lev1.lev1.lev3.lev4\tproc \(string\) - -> idetools --track:$TESTNIM,4,13 --def $SILENT -skParam\tabsurd_nesting.lev1.t1\tstring - -> idetools --track:$TESTNIM,4,13 --def $SILENT -skParam\tabsurd_nesting.lev1.t1\tstring - -> idetools --track:$TESTNIM,19,19 --def $SILENT -skParam\tabsurd_nesting.lev1.lev2.lev3.lev4.t4\tstring - diff --git a/tests/caas/basic-recompile.txt b/tests/caas/basic-recompile.txt deleted file mode 100644 index 620e0c059..000000000 --- a/tests/caas/basic-recompile.txt +++ /dev/null @@ -1,10 +0,0 @@ -main.nim -> c --verbosity:0 --hints:on -SuccessX -# The "Processing" string will be found always in proc mode since each -# compilation command will generate it. We need to test it only in Caas mode to -# verify the server is not recompiling again the file. -CaasRun > c --verbosity:0 --hints:on -CaasRun ! Processing -CaasRun SuccessX - diff --git a/tests/caas/compile-suggest.txt b/tests/caas/compile-suggest.txt deleted file mode 100644 index 378320014..000000000 --- a/tests/caas/compile-suggest.txt +++ /dev/null @@ -1,7 +0,0 @@ -main.nim -> c --verbosity:0 --hints:on -SuccessX -> idetools --trackDirty:main_dirty.nim,$TESTNIM,12,7 --suggest $SILENT -skField\tx -skField\ty - diff --git a/tests/caas/compile-then-def.txt b/tests/caas/compile-then-def.txt deleted file mode 100644 index 72ba46b04..000000000 --- a/tests/caas/compile-then-def.txt +++ /dev/null @@ -1,11 +0,0 @@ -main.nim -> c --verbosity:0 --hints:on -SuccessX - -> idetools --track:$TESTNIM,5,18 --def --verbosity:0 --hints:on -strutils.toUpper -! SuccessX - -> idetools --track:$TESTNIM,5,18 --def --verbosity:0 --hints:on -strutils.toUpper -! SuccessX diff --git a/tests/caas/completion_dot_syntax.txt b/tests/caas/completion_dot_syntax.txt deleted file mode 100644 index 4a975e5df..000000000 --- a/tests/caas/completion_dot_syntax.txt +++ /dev/null @@ -1,9 +0,0 @@ -completion_dot_syntax_main.nim -> idetools --track:$TESTNIM,24,15 --def -def\tskProc\t$MODULE.echoRemainingDollars -> idetools --trackDirty:completion_dot_syntax_dirty.nim,$TESTNIM,25,12 --suggest -sug\tskProc\techoRemainingDollars -# The suggestion should not mention the other echoRemaining* variants. -!echoRemainingEuros -!echoRemainingBugs - diff --git a/tests/caas/completion_dot_syntax_dirty.nim b/tests/caas/completion_dot_syntax_dirty.nim deleted file mode 100644 index 6237c4e79..000000000 --- a/tests/caas/completion_dot_syntax_dirty.nim +++ /dev/null @@ -1,25 +0,0 @@ -import strutils - -# Verifies if the --suggestion switch differentiates types for dot notation. - -type - TDollar = distinct int - TEuro = distinct int - -proc echoRemainingDollars(amount: TDollar) = - echo "You have $1 dollars" % [$int(amount)] - -proc echoRemainingEuros(amount: TEuro) = - echo "You have $1 euros" % [$int(amount)] - -proc echoRemainingBugs() = - echo "You still have bugs" - -proc main = - var - d: TDollar - e: TEuro - d = TDollar(23) - e = TEuro(32) - d.echoRemainingDollars() - e.echoRemai diff --git a/tests/caas/completion_dot_syntax_main.nim b/tests/caas/completion_dot_syntax_main.nim deleted file mode 100644 index 0be8c7f4f..000000000 --- a/tests/caas/completion_dot_syntax_main.nim +++ /dev/null @@ -1,24 +0,0 @@ -import strutils - -# Verifies if the --suggestion switch differentiates types for dot notation. - -type - TDollar = distinct int - TEuro = distinct int - -proc echoRemainingDollars(amount: TDollar) = - echo "You have $1 dollars" % [$int(amount)] - -proc echoRemainingEuros(amount: TEuro) = - echo "You have $1 euros" % [$int(amount)] - -proc echoRemainingBugs() = - echo "You still have bugs" - -proc main = - var - d: TDollar - e: TEuro - d = TDollar(23) - e = TEuro(32) - d.echoRemainingDollars() diff --git a/tests/caas/def-def-compile.txt b/tests/caas/def-def-compile.txt deleted file mode 100644 index 21d5ea962..000000000 --- a/tests/caas/def-def-compile.txt +++ /dev/null @@ -1,12 +0,0 @@ -main.nim -> idetools --track:$TESTNIM,5,18 --def --verbosity:0 --hints:on -strutils.toUpper -! SuccessX - -> idetools --track:$TESTNIM,5,18 --def --verbosity:0 --hints:on -strutils.toUpper -! SuccessX - -> c --verbosity:0 --hints:on -SuccessX - diff --git a/tests/caas/def-then-compile.txt b/tests/caas/def-then-compile.txt deleted file mode 100644 index 2214bf02c..000000000 --- a/tests/caas/def-then-compile.txt +++ /dev/null @@ -1,8 +0,0 @@ -main.nim -> idetools --track:$TESTNIM,5,18 --def --verbosity:0 --hints:on -strutils.toUpper -! SuccessX - -> c --verbosity:0 --hints:on -SuccessX - diff --git a/tests/caas/forward_declarations.nim b/tests/caas/forward_declarations.nim deleted file mode 100644 index 177d82f20..000000000 --- a/tests/caas/forward_declarations.nim +++ /dev/null @@ -1,15 +0,0 @@ -# This example shows that idetools returns an empty signature for a forward -# declared proc in proc/symproc runs, but correctly returns the full signature -# in caas mode. - -proc echoHello(text: string) - -proc testForward() = - echo "T" - echoHello("T") - -proc echoHello(text: string) = - echo "Hello Mr." & text - -when isMainModule: - testForward() diff --git a/tests/caas/forward_declarations.txt b/tests/caas/forward_declarations.txt deleted file mode 100644 index b1695b9c7..000000000 --- a/tests/caas/forward_declarations.txt +++ /dev/null @@ -1,9 +0,0 @@ -forward_declarations.nim - -> idetools --track:$TESTNIM,9,5 --def $SILENT -skProc -proc \(string\) - -> idetools --track:$TESTNIM,5,9 --def $SILENT -skProc -proc \(string\) diff --git a/tests/caas/forward_usages.txt b/tests/caas/forward_usages.txt deleted file mode 100644 index 05ef517dc..000000000 --- a/tests/caas/forward_usages.txt +++ /dev/null @@ -1,17 +0,0 @@ -forward_declarations.nim - -> c --verbosity:0 --hints:on -SuccessX - -# None of the following return three instances of the echoHello proc, the first -# being the forward declaration, the second being the usage inside testForward, -# and the third being the actual implementation. - -> idetools --track:$TESTNIM,5,5 --usages $SILENT -skProc.*\n.*skProc.*\n.*skProc - -> idetools --track:$TESTNIM,9,5 --usages $SILENT -skProc.*\n.*skProc.*\n.*skProc - -> idetools --track:$TESTNIM,11,5 --usages $SILENT -skProc.*\n.*skProc.*\n.*skProc diff --git a/tests/caas/idetools_api.nim b/tests/caas/idetools_api.nim deleted file mode 100644 index 281e562d7..000000000 --- a/tests/caas/idetools_api.nim +++ /dev/null @@ -1,84 +0,0 @@ -import unicode, sequtils, macros, re - -proc test_enums() = - var o: Tfile - if o.open("files " & "test.txt", fmWrite): - o.write("test") - o.close() - -proc test_iterators(filename = "tests.nim") = - let - input = readFile(filename) - letters = toSeq(runes(string(input))) - for letter in letters: echo int(letter) - -const SOME_SEQUENCE = @[1, 2] -type - bad_string = distinct string - TPerson = object of TObject - name*: bad_string - age: int - -proc adder(a, b: int): int = - result = a + b - -type - PExpr = ref object of TObject ## abstract base class for an expression - PLiteral = ref object of PExpr - x: int - PPlusExpr = ref object of PExpr - a, b: PExpr - -# watch out: 'eval' relies on dynamic binding -method eval(e: PExpr): int = - # override this base method - quit "to override!" - -method eval(e: PLiteral): int = e.x -method eval(e: PPlusExpr): int = eval(e.a) + eval(e.b) - -proc newLit(x: int): PLiteral = PLiteral(x: x) -proc newPlus(a, b: PExpr): PPlusExpr = PPlusExpr(a: a, b: b) - -echo eval(newPlus(newPlus(newLit(1), newLit(2)), newLit(4))) - -proc findVowelPosition(text: string) = - var found = -1 - block loops: - for i, letter in pairs(text): - for j in ['a', 'e', 'i', 'o', 'u']: - if letter == j: - found = i - break loops # leave both for-loops - echo found - -findVowelPosition("Zerg") # should output 1, position of vowel. - -macro expect*(exceptions: varargs[expr], body: stmt): stmt {.immediate.} = - ## Expect docstrings - let exp = callsite() - template expectBody(errorTypes, lineInfoLit: expr, - body: stmt): NimNode {.dirty.} = - try: - body - assert false - except errorTypes: - nil - - var body = exp[exp.len - 1] - - var errorTypes = newNimNode(nnkBracket) - for i in countup(1, exp.len - 2): - errorTypes.add(exp[i]) - - result = getAst(expectBody(errorTypes, exp.lineinfo, body)) - -proc err = - raise newException(EArithmetic, "some exception") - -proc testMacro() = - expect(EArithmetic): - err() - -testMacro() -let notAModule = re"(\w+)=(.*)" diff --git a/tests/caas/idetools_api.txt b/tests/caas/idetools_api.txt deleted file mode 100644 index 035590dc3..000000000 --- a/tests/caas/idetools_api.txt +++ /dev/null @@ -1,59 +0,0 @@ -idetools_api.nim -> c --verbosity:0 --hints:on -SuccessX -> idetools --track:$TESTNIM,4,11 --def $SILENT -def\tskType\tsystem.TFile\tTFile -> idetools --track:$TESTNIM,5,7 --def $SILENT -def\tskProc\tsystem.Open\tproc \(var TFile, string, TFileMode, int\): bool -> idetools --track:$TESTNIM,5,21 --def $SILENT -def\tskProc\tsystem.\&\tproc \(string, string\): string\{.noSideEffect.\} -> idetools --track:$TESTNIM,5,38 --def $SILENT -def\tskEnumField\tsystem.TFileMode.fmWrite\tTFileMode -> idetools --track:$TESTNIM,7,6 --def $SILENT -def\tskProc\tsystem.Close\tproc \(TFile\) -> idetools --track:$TESTNIM,12,23 --def $SILENT -def\tskIterator\tunicode.runes\titerator \(string\): TRune -> idetools --track:$TESTNIM,12,15 --def $SILENT -def\tskTemplate\tsequtils.toSeq\tproc \(expr\): expr -> idetools --track:$TESTNIM,15,7 --def $SILENT - -# ProcRun mode will fail the next line, because the type is returned empty. -def\tskConst\t$MODULE.SOME_SEQUENCE\tseq\[int\]\t -> idetools --track:$TESTNIM,15,23 --def $SILENT -def\tskProc\tsystem.@\tproc \(array\[IDX, T\]\): seq\[T\]\{.noSideEffect.\} -> idetools --track:$TESTNIM,17,3 --def $SILENT - -# ProcRun mode will fail the next line, because the type is returned empty. -def\tskType\t$MODULE.bad_string\tbad_string\t -> idetools --track:$TESTNIM,11,24 --def $SILENT -def\tskParam\t$MODULE.test_iterators.filename\tstring -> idetools --track:$TESTNIM,6,5 --def $SILENT -def\tskVar\t$MODULE.test_enums.o\tTFile -> idetools --track:$TESTNIM,12,34 --def $SILENT -def\tskLet\t$MODULE.test_iterators.input\tTaintedString -> idetools --track:$TESTNIM,13,35 --def $SILENT -def\tskForVar\t$MODULE.test_iterators.letter\tTRune -> idetools --track:$TESTNIM,23,3 --def $SILENT -def\tskResult\t$MODULE.adder.result\tint -> idetools --track:$TESTNIM,19,6 --def $SILENT - -# ProcRun mode will fail the next line, because the type is returned empty. -def\tskField\t$MODULE.TPerson.name\tbad_string\t - -> idetools --track:$TESTNIM,43,7 --def $SILENT -def\tskMethod\t$MODULE.eval\tproc \(PPlusExpr\): int\t - -> idetools --track:$TESTNIM,47,8 --def $SILENT -def\tskLabel\t$MODULE.findVowelPosition.loops\t\t -# For some reason the use of the label with break displaces its position. -> idetools --track:$TESTNIM,52,16 --def $SILENT -def\tskLabel\t$MODULE.findVowelPosition.loops\t\t - -# Displaced macro usage by one character. -> idetools --track:$TESTNIM,80,2 --def $SILENT -def\tskMacro\t$MODULE.expect\tproc \(varargs\[expr\], stmt\): stmt\t - -# The syntax for extended raw string literals should not be returned as module -# but as the proc re() inside the re module. -> idetools --track:$TESTNIM,84,17 --def $SILENT -!def\tskModule diff --git a/tests/caas/imported.nim b/tests/caas/imported.nim deleted file mode 100644 index a4bc5c0e6..000000000 --- a/tests/caas/imported.nim +++ /dev/null @@ -1,3 +0,0 @@ -proc `+++`*(a,b: string): string = - return a & " " & b - diff --git a/tests/caas/issue_416_template_shift.nim b/tests/caas/issue_416_template_shift.nim deleted file mode 100644 index d52f611d6..000000000 --- a/tests/caas/issue_416_template_shift.nim +++ /dev/null @@ -1,17 +0,0 @@ -import unicode, sequtils - -proc test() = - let input = readFile("weird.nim") - for letter in runes(string(input)): - echo int(letter) - -when 1 > 0: - proc failtest() = - let - input = readFile("weird.nim") - letters = toSeq(runes(string(input))) - for letter in letters: - echo int(letter) - -when isMainModule: - test() diff --git a/tests/caas/issue_416_template_shift.txt b/tests/caas/issue_416_template_shift.txt deleted file mode 100644 index e911c1360..000000000 --- a/tests/caas/issue_416_template_shift.txt +++ /dev/null @@ -1,14 +0,0 @@ -issue_416_template_shift.nim -> c --verbosity:0 --hints:on -SuccessX -> idetools --track:$TESTNIM,12,28 --def $SILENT -def\tskType\tsystem.string\tstring -> idetools --track:$TESTNIM,12,35 --def $SILENT -def\tskLet\t$MODULE.failtest.input\tTaintedString - -# The following fail because they seem shifted one column to the right. -> idetools --track:$TESTNIM,12,16 --def $SILENT -def\tskTemplate\tsequtils.toSeq\tproc \(expr\): expr -> idetools --track:$TESTNIM,12,22 --def $SILENT -def\tskIterator\tunicode.runes\titerator \(string\): TRune - diff --git a/tests/caas/issue_452_export_shift.nim b/tests/caas/issue_452_export_shift.nim deleted file mode 100644 index 46cff6241..000000000 --- a/tests/caas/issue_452_export_shift.nim +++ /dev/null @@ -1,8 +0,0 @@ -const - VERSION_STR1* = "0.5.0" ## Idetools shifts this one column. - VERSION_STR2 = "0.5.0" ## This one is ok. - VERSION_STR3* = "0.5.0" ## Bad. - VERSION_STR4 = "0.5.0" ## Ok. - -proc forward1*(): string = result = "" -proc forward2(): string = result = "" diff --git a/tests/caas/issue_452_export_shift.txt b/tests/caas/issue_452_export_shift.txt deleted file mode 100644 index 4676ed71e..000000000 --- a/tests/caas/issue_452_export_shift.txt +++ /dev/null @@ -1,11 +0,0 @@ -issue_452_export_shift.nim -> c --verbosity:0 --hints:on -SuccessX -> idetools --track:$TESTNIM,2,2 --def $SILENT -def\tskConst\t$MODULE.VERSION_STR1\tstring -> idetools --track:$TESTNIM,3,2 --def $SILENT -def\tskConst\t$MODULE.VERSION_STR2\tstring -> idetools --track:$TESTNIM,7,5 --def $SILENT -def\tskProc\t$MODULE.forward1\tproc \(\): string\t -> idetools --track:$TESTNIM,8,5 --def $SILENT -def\tskProc\t$MODULE.forward2\tproc \(\): string\t diff --git a/tests/caas/issue_477_dynamic_dispatch.nim b/tests/caas/issue_477_dynamic_dispatch.nim deleted file mode 100644 index 6e6b21ef0..000000000 --- a/tests/caas/issue_477_dynamic_dispatch.nim +++ /dev/null @@ -1,19 +0,0 @@ -type - TThing = object of TObject - TUnit = object of TThing - x: int - -method collide(a, b: TThing) {.inline.} = - quit "to override!" - -method collide(a: TThing, b: TUnit) {.inline.} = - echo "collide1" - -method collide(a: TUnit, b: TThing) {.inline.} = - echo "collide2" - -var - a, b: TUnit - -when isMainModule: - collide(a, b) # output: 2 diff --git a/tests/caas/issue_477_dynamic_dispatch.txt b/tests/caas/issue_477_dynamic_dispatch.txt deleted file mode 100644 index 12fd750de..000000000 --- a/tests/caas/issue_477_dynamic_dispatch.txt +++ /dev/null @@ -1,5 +0,0 @@ -issue_477_dynamic_dispatch.nim -> c --run -SuccessX -> idetools --track:issue_477_dynamic_dispatch.nim,19,5 --def $SILENT -def\tskMethod\tissue_477_dynamic_dispatch.collide\tproc \(TUnit, TThing\)\{.inline.\} diff --git a/tests/caas/its_full_of_procs.nim b/tests/caas/its_full_of_procs.nim deleted file mode 100644 index 8f8b66764..000000000 --- a/tests/caas/its_full_of_procs.nim +++ /dev/null @@ -1,29 +0,0 @@ -import unicode, sequtils - -# This example shows that idetools returns proc as signature for everything -# which can be called. While a clever person would use the second column to -# differentiate between procs, methods and others, why does the output contain -# incorrect information? - -type - TThing = object of TObject - TUnit = object of TThing - x: int - -method collide(a, b: TThing) {.inline.} = - quit "to override!" - -method collide(a: TThing, b: TUnit) {.inline.} = - echo "1" - -method collide(a: TUnit, b: TThing) {.inline.} = - echo "2" - -var - a, b: TUnit - -let - input = readFile("its_full_of_procs.nim") - letters = toSeq(runes(string(input))) - -collide(a, b) # output: 2 diff --git a/tests/caas/its_full_of_procs.txt b/tests/caas/its_full_of_procs.txt deleted file mode 100644 index 31a2d3baa..000000000 --- a/tests/caas/its_full_of_procs.txt +++ /dev/null @@ -1,20 +0,0 @@ -its_full_of_procs.nim - -> idetools --track:$TESTNIM,26,15 --def $SILENT -skProc -proc \( - -> idetools --track:$TESTNIM,27,21 --def $SILENT -skIterator -iterator \( -!proc \( - -> idetools --track:$TESTNIM,29,0 --def $SILENT -skMethod -method \( -!proc \( - -> idetools --track:$TESTNIM,27,15 --def $SILENT -skTemplate -template \( -!proc \( diff --git a/tests/caas/main.nim b/tests/caas/main.nim deleted file mode 100644 index fafeff93b..000000000 --- a/tests/caas/main.nim +++ /dev/null @@ -1,7 +0,0 @@ -import imported, strutils - -proc main = - var t1 = "text" - var t2 = t1.toUpper - echo(t1 +++ t2) - diff --git a/tests/caas/main_dirty.nim b/tests/caas/main_dirty.nim deleted file mode 100644 index 95fb6c624..000000000 --- a/tests/caas/main_dirty.nim +++ /dev/null @@ -1,14 +0,0 @@ -import imported, strutils - -type - TFoo = object - x: int - y: string - -proc main = - var t1 = "text" - var t2 = t1.toUpper - var foo = TFoo(x: 10, y: "test") - foo. - echo(t1 +++ t2) - diff --git a/tests/caas/suggest-compile.txt b/tests/caas/suggest-compile.txt deleted file mode 100644 index a322908ac..000000000 --- a/tests/caas/suggest-compile.txt +++ /dev/null @@ -1,13 +0,0 @@ -main.nim -# This example shows how the suggest feature can be used on a partial file -# using the --trackDirty switch. -> idetools --trackDirty:main_dirty.nim,$TESTNIM,12,7 --suggest $SILENT -skField\tx -skField\ty -# Repeating the query in caas should work always and retrieve same output. -CaasRun > idetools --trackDirty:main_dirty.nim,$TESTNIM,12,7 --suggest $SILENT -CaasRun skField\tx -CaasRun skField\ty -> c --verbosity:0 --hints:on -SuccessX - diff --git a/tests/caas/suggest-invalid-source.txt b/tests/caas/suggest-invalid-source.txt deleted file mode 100644 index 7f8f1213d..000000000 --- a/tests/caas/suggest-invalid-source.txt +++ /dev/null @@ -1,26 +0,0 @@ -main_dirty.nim -# A variant of the suggest-compile.txt, instead of using a "base" correct -# source, this one uses the "broken" main_dirty.nim which won't compile. The -# test tries to stress idetools to still provide a valid answer if possible, -# and at least provide the same output with repeated queries rather than dying -# after the first compilation error. - -# The first query should work and provide valid suggestions. -> idetools --track:$TESTNIM,12,6 --suggest $SILENT -skField\tx -skField\ty - -# Repeating the query should work too. -> idetools --track:$TESTNIM,12,6 --suggest $SILENT -skField\tx -skField\ty - -# Expect now a compilation failure. -> c -!SuccessX -invalid indentation - -# Repeating suggestions *after broken compilation* should work too. -> idetools --track:$TESTNIM,12,6 --suggest $SILENT -skField\tx -skField\ty From 7b40c864bc4842f704855188010cea468c89f98c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arne=20D=C3=B6ring?= Date: Wed, 28 Nov 2018 00:04:48 +0100 Subject: [PATCH 065/110] kick unused benchmarks --- tests/benchmark.nim | 47 ----------------------- tests/benchmarks/fannkuch.nim | 69 ---------------------------------- tests/benchmarks/quicksort.nim | 54 -------------------------- 3 files changed, 170 deletions(-) delete mode 100644 tests/benchmark.nim delete mode 100644 tests/benchmarks/fannkuch.nim delete mode 100644 tests/benchmarks/quicksort.nim diff --git a/tests/benchmark.nim b/tests/benchmark.nim deleted file mode 100644 index 69c9a3927..000000000 --- a/tests/benchmark.nim +++ /dev/null @@ -1,47 +0,0 @@ -# -# -# Nim Benchmark tool -# (c) Copyright 2012 Dominik Picheta -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -## This program runs benchmarks -import osproc, os, times, json - -type - TBenchResult = tuple[file: string, success: bool, time: float] - -proc compileBench(file: string) = - ## Compiles ``file``. - doAssert(execCmdEx("nim c -d:release " & file).exitCode == QuitSuccess) - -proc runBench(file: string): TBenchResult = - ## Runs ``file`` and returns info on how long it took to run. - var start = epochTime() - if execCmdEx(file.addFileExt(ExeExt)).exitCode == QuitSuccess: - var t = epochTime() - start - result = (file, true, t) - else: result = (file, false, -1.0) - -proc genOutput(benches: seq[TBenchResult]): PJsonNode = - result = newJObject() - for i in benches: - if i.success: - result[i.file.extractFilename] = newJFloat(i.time) - else: - result[i.file.extractFilename] = newJNull() - -proc doBench(): seq[TBenchResult] = - result = @[] - for i in walkFiles("tests/benchmarks/*.nim"): - echo(i.extractFilename) - compileBench(i) - result.add(runBench(i)) - -when isMainModule: - var b = doBench() - var output = genOutput(b) - writeFile("benchmarkResults.json", pretty(output)) - diff --git a/tests/benchmarks/fannkuch.nim b/tests/benchmarks/fannkuch.nim deleted file mode 100644 index c87295092..000000000 --- a/tests/benchmarks/fannkuch.nim +++ /dev/null @@ -1,69 +0,0 @@ -import os -import strutils - -proc fannkuch(n: int): int = - var - count: seq[int] - maxFlips = 0 - m = n-1 - r = n - check = 0 - perm1: seq[int] - perm: seq[int] - - newSeq(count, n+1) - newSeq(perm1, n) - newSeq(perm, n) - for i in 0 .. n-1: - count[i] = i+1 - perm1[i] = i - perm[i] = i - count[n] = n+1 - - while true: - if check < 30: - for i in items(perm1): - write(stdout, $(i+1)) - echo("") - inc(check) - - while r != 1: - count[r-1] = r - dec (r) - - if perm1[0] != 0 and perm1[m] != m: - # perm = perm1 - # The above line is between 3 and 4 times slower than the loop below! - for i in 0 .. n-1: - perm[i] = perm1[i] - var flipsCount = 0 - var k = perm[0] - while k != 0: - for i in 0 .. (k div 2): - swap(perm[i], perm[k-i]) - inc(flipsCount) - k = perm[0] - - if flipsCount > maxFlips: - maxFlips = flipsCount - - block makePerm: - while r != n: - var tmp = perm1[0] - # # perm1.delete (0) - # # perm1.insert (tmp, r) - # # The above is about twice as slow as the following: - # moveMem (addr (perm1[0]), addr (perm1[1]), r * sizeof (int)) - # The call to moveMem is about 50% slower than the loop below! - for i in 0 .. r-1: - perm1[i] = perm1[i+1] - perm1[r] = tmp - - dec(count[r]) - if count[r] > 0: - break makePerm - inc(r) - return maxFlips - -var n = 10 -echo("Pfannkuchen(" & $n & ") = " & $fannkuch(n)) diff --git a/tests/benchmarks/quicksort.nim b/tests/benchmarks/quicksort.nim deleted file mode 100644 index 114321492..000000000 --- a/tests/benchmarks/quicksort.nim +++ /dev/null @@ -1,54 +0,0 @@ -import os -import strutils - -# Generate some pseudo-random data -var seed: tuple[s1, s2, s3: int32] = (2'i32, 8'i32, 16'i32) - -proc random(): int32 = - seed = (((((((seed[0] and 0x0007_FFFF'i32) shl 13'i32) xor seed[0]) shr - 19'i32) and 0x0000_1FFF'i32) xor - ((seed[0] and 0x000F_FFFE'i32) shl 12'i32)), - - ((((((seed[1] and 0x3FFF_FFFF'i32) shl 2'i32) xor seed[1]) shr - 25'i32) and 0x0000_007F'i32) xor - ((seed[1] and 0x0FFF_FFF8'i32) shl 4'i32)), - - ((((((seed[2] and 0x1FFF_FFFF'i32) shl 3'i32) xor seed[2]) shr - 11'i32) and 0x001F_FFFF'i32) xor - ((seed[2] and 0x0000_7FF0'i32) shl 17'i32))) - return seed[0] xor seed[1] xor seed[2] - -var n = 9999999 - -var data: seq[int32] -newSeq(data, n) -for i in 0 .. data.high(): - data[i] = random() - - -proc `$`(d: seq[int32]): string = - result = "[ " - for i in items(d): - result.addSep(", ", 2) - result.add($(i and 0xFFFF_FFFF'i64)) - result.add(" ]") - -# Sort the data -proc sort(start, stop: int) = - if stop <= start+1: - return - - var j = start - for i in start..stop-2: - if data[i] <% data[stop-1]: - swap(data[i], data[j]) - inc(j) - swap(data[j], data[stop-1]) - - sort(start, j) - sort(j+1, stop) - -sort(0, data.len) -echo(data[n div 2 - 1] and 0xFFFF_FFFF'i64, ", ", - data[n div 2] and 0xFFFF_FFFF'i64, ", ", - data[n div 2 + 1] and 0xFFFF_FFFF'i64) From 7f6feb603441ed08e3c0b55d91dd34234d30ea58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arne=20D=C3=B6ring?= Date: Wed, 28 Nov 2018 00:05:15 +0100 Subject: [PATCH 066/110] minor changes --- testament/tester.nim | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/testament/tester.nim b/testament/tester.nim index 1c105c97f..60cf46423 100644 --- a/testament/tester.nim +++ b/testament/tester.nim @@ -353,7 +353,6 @@ proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) = else: specDefaults expected expected.action = actionRunNoSpec - expected.outputCheck = ocIgnore # this is default so it is unnecessary if expected.err == reIgnored: # targetC is a lie @@ -498,9 +497,7 @@ proc testExec(r: var TResults, test: TTest) = if given.err == reSuccess: inc(r.passed) r.addResult(test, targetC, "", given.msg, given.err) -proc makeTest(test, options: string, cat: Category, - env: string = ""): TTest = - # start with 'actionCompile', will be overwritten in the spec: +proc makeTest(test, options: string, cat: Category, env: string = ""): TTest = result = TTest(cat: cat, name: test, options: options, startTime: epochTime()) when defined(windows): @@ -526,10 +523,8 @@ proc main() = backend.open() var optPrintResults = false var optFailing = false - var targetsStr = "" - var p = initOptParser() p.next() while p.kind == cmdLongoption: @@ -544,16 +539,18 @@ proc main() = of "directory": setCurrentDir(p.val.string) of "colors": - if p.val.string == "on": + case p.val.string: + of "on": useColors = true - elif p.val.string == "off": + of "off": useColors = false else: quit Usage else: quit Usage p.next() - if p.kind != cmdArgument: quit Usage + if p.kind != cmdArgument: + quit Usage var action = p.key.string.normalize p.next() var r = initResults() From b26378a468eeaa08aefe94e683a57246114e721d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arne=20D=C3=B6ring?= Date: Wed, 28 Nov 2018 01:57:13 +0100 Subject: [PATCH 067/110] WIP, most tests are now skipped --- testament/backend.nim | 5 +- testament/categories.nim | 82 ++++++++------- testament/specs.nim | 205 ++++++++++++++++++------------------ testament/tester.nim | 38 ++++--- tests/realtimeGC/shared.nim | 3 +- 5 files changed, 169 insertions(+), 164 deletions(-) diff --git a/testament/backend.nim b/testament/backend.nim index 385f1171c..a1de5859a 100644 --- a/testament/backend.nim +++ b/testament/backend.nim @@ -45,8 +45,7 @@ var currentCategory: string entries: int -proc writeTestResult*(name, category, target, - action, result, expected, given: string) = +proc writeTestResult*(name, category, target, result, expected, given: string) = createDir("testresults") if currentCategory != category: if currentCategory.len > 0: @@ -58,7 +57,7 @@ proc writeTestResult*(name, category, target, entries = 0 let jentry = %*{"name": name, "category": category, "target": target, - "action": action, "result": result, "expected": expected, "given": given, + "result": result, "expected": expected, "given": given, "machine": thisMachine.string, "commit": thisCommit.string, "branch": thisBranch} if entries > 0: results.writeLine(",") diff --git a/testament/categories.nim b/testament/categories.nim index 6694e3f0e..b641430a1 100644 --- a/testament/categories.nim +++ b/testament/categories.nim @@ -27,7 +27,7 @@ proc delNimCache(filename, options: string) = proc runRodFiles(r: var TResults, cat: Category, options: string) = template test(filename: string, clearCacheFirst=false) = if clearCacheFirst: delNimCache(filename, options) - testSpec r, makeTest(rodfilesDir / filename, options, cat, actionRun) + testSpec r, makeTest(rodfilesDir / filename, options, cat) # test basic recompilation scheme: @@ -97,10 +97,12 @@ proc runBasicDLLTest(c, r: var TResults, cat: Category, options: string) = else: "" - testNoSpec c, makeTest("lib/nimrtl.nim", - options & " --app:lib -d:createNimRtl --threads:on", cat, actionCompile) - testNoSpec c, makeTest("tests/dll/server.nim", - options & " --app:lib -d:useNimRtl --threads:on" & rpath, cat, actionCompile) + var test1 = makeTest("lib/nimrtl.nim", options & " --app:lib -d:createNimRtl --threads:on", cat) + test1.spec.action = actionCompile + testSpec c, test1 + var test2 = makeTest("tests/dll/server.nim", options & " --app:lib -d:useNimRtl --threads:on" & rpath, cat) + test2.spec.action = actionCompile + testSpec c, test2 when defined(Windows): # windows looks in the dir of the exe (yay!): @@ -120,7 +122,7 @@ proc runBasicDLLTest(c, r: var TResults, cat: Category, options: string) = safeCopyFile("lib" / nimrtlDll, "tests/dll" / nimrtlDll) testSpec r, makeTest("tests/dll/client.nim", options & " -d:useNimRtl --threads:on" & rpath, - cat, actionRun) + cat) proc dllTests(r: var TResults, cat: Category, options: string) = # dummy compile result: @@ -138,32 +140,32 @@ proc dllTests(r: var TResults, cat: Category, options: string) = proc gcTests(r: var TResults, cat: Category, options: string) = template testWithNone(filename: untyped) = testSpec r, makeTest("tests/gc" / filename, options & - " --gc:none", cat, actionRun) + " --gc:none", cat) testSpec r, makeTest("tests/gc" / filename, options & - " -d:release --gc:none", cat, actionRun) + " -d:release --gc:none", cat) template testWithoutMs(filename: untyped) = - testSpec r, makeTest("tests/gc" / filename, options, cat, actionRun) + testSpec r, makeTest("tests/gc" / filename, options, cat) testSpec r, makeTest("tests/gc" / filename, options & - " -d:release", cat, actionRun) + " -d:release", cat) testSpec r, makeTest("tests/gc" / filename, options & - " -d:release -d:useRealtimeGC", cat, actionRun) + " -d:release -d:useRealtimeGC", cat) template testWithoutBoehm(filename: untyped) = testWithoutMs filename testSpec r, makeTest("tests/gc" / filename, options & - " --gc:markAndSweep", cat, actionRun) + " --gc:markAndSweep", cat) testSpec r, makeTest("tests/gc" / filename, options & - " -d:release --gc:markAndSweep", cat, actionRun) + " -d:release --gc:markAndSweep", cat) template test(filename: untyped) = testWithoutBoehm filename when not defined(windows) and not defined(android): # AR: cannot find any boehm.dll on the net, right now, so disabled # for windows: testSpec r, makeTest("tests/gc" / filename, options & - " --gc:boehm", cat, actionRun) + " --gc:boehm", cat) testSpec r, makeTest("tests/gc" / filename, options & - " -d:release --gc:boehm", cat, actionRun) + " -d:release --gc:boehm", cat) testWithoutBoehm "foreign_thr" test "gcemscripten" @@ -196,17 +198,18 @@ proc longGCTests(r: var TResults, cat: Category, options: string) = var c = initResults() # According to ioTests, this should compile the file - testNoSpec c, makeTest("tests/realtimeGC/shared", options, cat, actionCompile) - testC r, makeTest("tests/realtimeGC/cmain", cOptions, cat, actionRun) - testSpec r, makeTest("tests/realtimeGC/nmain", options & "--threads: on", cat, actionRun) + testSpec c, makeTest("tests/realtimeGC/shared", options, cat) + # ^- why is this not appended to r? Should this be discarded? + testC r, makeTest("tests/realtimeGC/cmain", cOptions, cat), actionRun + testSpec r, makeTest("tests/realtimeGC/nmain", options & "--threads: on", cat) # ------------------------- threading tests ----------------------------------- proc threadTests(r: var TResults, cat: Category, options: string) = template test(filename: untyped) = - testSpec r, makeTest(filename, options, cat, actionRun) - testSpec r, makeTest(filename, options & " -d:release", cat, actionRun) - testSpec r, makeTest(filename, options & " --tlsEmulation:on", cat, actionRun) + testSpec r, makeTest(filename, options, cat) + testSpec r, makeTest(filename, options & " -d:release", cat) + testSpec r, makeTest(filename, options & " --tlsEmulation:on", cat) for t in os.walkFiles("tests/threads/t*.nim"): test(t) @@ -235,10 +238,8 @@ proc debuggerTests(r: var TResults, cat: Category, options: string) = proc jsTests(r: var TResults, cat: Category, options: string) = template test(filename: untyped) = - testSpec r, makeTest(filename, options & " -d:nodejs", cat, - actionRun), targetJS - testSpec r, makeTest(filename, options & " -d:nodejs -d:release", cat, - actionRun), targetJS + testSpec r, makeTest(filename, options & " -d:nodejs", cat), {targetJS} + testSpec r, makeTest(filename, options & " -d:nodejs -d:release", cat), {targetJS} for t in os.walkFiles("tests/js/t*.nim"): test(t) @@ -259,14 +260,14 @@ proc jsTests(r: var TResults, cat: Category, options: string) = proc testNimInAction(r: var TResults, cat: Category, options: string) = let options = options & " --nilseqs:on" - template test(filename: untyped, action: untyped) = - testSpec r, makeTest(filename, options, cat, action) + template test(filename: untyped) = + testSpec r, makeTest(filename, options, cat) template testJS(filename: untyped) = - testSpec r, makeTest(filename, options, cat, actionCompile), targetJS + testSpec r, makeTest(filename, options, cat), {targetJS} template testCPP(filename: untyped) = - testSpec r, makeTest(filename, options, cat, actionCompile), targetCPP + testSpec r, makeTest(filename, options, cat), {targetCPP} let tests = [ "niminaction/Chapter1/various1", @@ -318,7 +319,7 @@ proc testNimInAction(r: var TResults, cat: Category, options: string) = # Run the tests. for testfile in tests: - test "tests/" & testfile & ".nim", actionCompile + test "tests/" & testfile & ".nim" let jsFile = "tests/niminaction/Chapter8/canvas/canvas_test.nim" testJS jsFile @@ -361,14 +362,17 @@ proc compileExample(r: var TResults, pattern, options: string, cat: Category) = testNoSpec r, makeTest(test, options, cat) proc testStdlib(r: var TResults, pattern, options: string, cat: Category) = - for test in os.walkFiles(pattern): - let name = extractFilename(test) + for testFile in os.walkFiles(pattern): + let name = extractFilename(testFile) if name notin disabledFiles: - let contents = readFile(test).string - if contents.contains("when isMainModule"): - testSpec r, makeTest(test, options, cat, actionRunNoSpec) - else: - testNoSpec r, makeTest(test, options, cat, actionCompile) + + + let contents = readFile(testFile).string + + var testObj = makeTest(testFile, options, cat) + if "when isMainModule" notin contents: + testObj.spec.action = actionCompile + testSpec r, testObj # ----------------------------- nimble ---------------------------------------- type PackageFilter = enum @@ -472,7 +476,7 @@ proc processSingleTest(r: var TResults, cat: Category, options, test: string) = let test = "tests" & DirSep &.? cat.string / test let target = if cat.string.normalize == "js": targetJS else: targetC - if existsFile(test): testSpec r, makeTest(test, options, cat), target + if existsFile(test): testSpec r, makeTest(test, options, cat), {target} else: echo "[Warning] - ", test, " test does not exist" proc processCategory(r: var TResults, cat: Category, options: string) = @@ -521,8 +525,6 @@ proc processCategory(r: var TResults, cat: Category, options: string) = testNimblePackages(r, cat, pfAll) of "niminaction": testNimInAction(r, cat, options) - of "testament": - testTestament(r, cat, options) of "untestable": # We can't test it because it depends on a third party. discard # TODO: Move untestable tests to someplace else, i.e. nimble repo. diff --git a/testament/specs.nim b/testament/specs.nim index a86544c27..9b2347bf9 100644 --- a/testament/specs.nim +++ b/testament/specs.nim @@ -9,7 +9,6 @@ import parseutils, strutils, os, osproc, streams, parsecfg - var compilerPrefix* = "compiler" / "nim" let isTravis* = existsEnv("TRAVIS") @@ -97,32 +96,8 @@ proc extractSpec(filename: string): string = when not defined(nimhygiene): {.pragma: inject.} -template parseSpecAux(fillResult: untyped) = - var ss = newStringStream(extractSpec(filename)) - var p {.inject.}: CfgParser - open(p, ss, filename, 1) - while true: - var e {.inject.} = next(p) - case e.kind - of cfgEof: break - of cfgSectionStart, cfgOption, cfgError: - echo ignoreMsg(p, e) - of cfgKeyValuePair: - fillResult - close(p) - -proc specDefaults*(result: var TSpec) = - result.msg = "" - result.outp = "" - result.nimout = "" - result.ccodeCheck = "" +proc defaultSpec*(): TSpec = result.cmd = cmdTemplate() - result.line = 0 - result.column = 0 - result.tfile = "" - result.tline = 0 - result.tcolumn = 0 - result.maxCodeSize = 0 proc parseTargets*(value: string): set[TTarget] = for v in value.normalize.splitWhitespace: @@ -134,79 +109,109 @@ proc parseTargets*(value: string): set[TTarget] = else: echo "target ignored: " & v proc parseSpec*(filename: string): TSpec = - specDefaults(result) + result = defaultSpec() result.file = filename - parseSpecAux: - case normalize(e.key) - of "action": - case e.value.normalize - of "compile": result.action = actionCompile - of "run": result.action = actionRun - of "reject": result.action = actionReject - else: echo ignoreMsg(p, e) - of "file": result.file = e.value - of "line": discard parseInt(e.value, result.line) - of "column": discard parseInt(e.value, result.column) - of "tfile": result.tfile = e.value - of "tline": discard parseInt(e.value, result.tline) - of "tcolumn": discard parseInt(e.value, result.tcolumn) - of "output": - result.outputCheck = ocEqual - result.outp = strip(e.value) - of "input": - result.input = e.value - of "outputsub": - result.outputCheck = ocSubstr - result.outp = strip(e.value) - of "sortoutput": - result.sortoutput = parseCfgBool(e.value) - of "exitcode": - discard parseInt(e.value, result.exitCode) - result.action = actionRun - of "msg": - result.msg = e.value - if result.action != actionRun: - result.action = actionCompile - of "errormsg", "errmsg": - result.msg = e.value - result.action = actionReject - of "nimout": - result.nimout = e.value - of "disabled": - case e.value.normalize - of "y", "yes", "true", "1", "on": result.err = reIgnored - of "n", "no", "false", "0", "off": discard - of "win", "windows": - when defined(windows): result.err = reIgnored - of "linux": - when defined(linux): result.err = reIgnored - of "bsd": - when defined(bsd): result.err = reIgnored - of "macosx": - when defined(macosx): result.err = reIgnored - of "unix": - when defined(unix): result.err = reIgnored - of "posix": - when defined(posix): result.err = reIgnored - of "travis": - if isTravis: result.err = reIgnored - of "appveyor": - if isAppVeyor: result.err = reIgnored + var ss = newStringStream(extractSpec(filename)) + var p {.inject.}: CfgParser + open(p, ss, filename, 1) + while true: + var e = next(p) + case e.kind + of cfgKeyValuePair: + case normalize(e.key) + of "action": + case e.value.normalize + of "compile": + result.action = actionCompile + of "run": + result.action = actionRun + of "reject": + result.action = actionReject + else: + echo ignoreMsg(p, e) + of "file": + result.file = e.value + of "line": + discard parseInt(e.value, result.line) + of "column": + discard parseInt(e.value, result.column) + of "tfile": + result.tfile = e.value + of "tline": + discard parseInt(e.value, result.tline) + of "tcolumn": + discard parseInt(e.value, result.tcolumn) + of "output": + result.outputCheck = ocEqual + result.outp = strip(e.value) + of "input": + result.input = e.value + of "outputsub": + result.outputCheck = ocSubstr + result.outp = strip(e.value) + of "sortoutput": + result.sortoutput = parseCfgBool(e.value) + of "exitcode": + discard parseInt(e.value, result.exitCode) + result.action = actionRun + of "msg": + result.msg = e.value + if result.action != actionRun: + result.action = actionCompile + of "errormsg", "errmsg": + result.msg = e.value + result.action = actionReject + of "nimout": + result.nimout = e.value + of "disabled": + case e.value.normalize + of "y", "yes", "true", "1", "on": result.err = reIgnored + of "n", "no", "false", "0", "off": discard + of "win", "windows": + when defined(windows): result.err = reIgnored + of "linux": + when defined(linux): result.err = reIgnored + of "bsd": + when defined(bsd): result.err = reIgnored + of "macosx": + when defined(macosx): result.err = reIgnored + of "unix": + when defined(unix): result.err = reIgnored + of "posix": + when defined(posix): result.err = reIgnored + of "travis": + if isTravis: result.err = reIgnored + of "appveyor": + if isAppVeyor: result.err = reIgnored + else: + raise newException(ValueError, "cannot interpret as a bool: " & e.value) + of "cmd": + if e.value.startsWith("nim "): + result.cmd = compilerPrefix & e.value[3..^1] + else: + result.cmd = e.value + of "ccodecheck": + result.ccodeCheck = e.value + of "maxcodesize": + discard parseInt(e.value, result.maxCodeSize) + of "target", "targets": + for v in e.value.normalize.splitWhitespace: + case v + of "c": + result.targets.incl(targetC) + of "cpp", "c++": + result.targets.incl(targetCpp) + of "objc": + result.targets.incl(targetObjC) + of "js": + result.targets.incl(targetJS) + else: + echo ignoreMsg(p, e) else: - raise newException(ValueError, "cannot interpret as a bool: " & e.value) - of "cmd": - if e.value.startsWith("nim "): - result.cmd = compilerPrefix & e.value[3..^1] - else: - result.cmd = e.value - of "ccodecheck": result.ccodeCheck = e.value - of "maxcodesize": discard parseInt(e.value, result.maxCodeSize) - of "target", "targets": - for v in e.value.normalize.splitWhitespace: - case v - of "c": result.targets.incl(targetC) - of "cpp", "c++": result.targets.incl(targetCpp) - of "objc": result.targets.incl(targetObjC) - of "js": result.targets.incl(targetJS) - else: echo ignoreMsg(p, e) - else: echo ignoreMsg(p, e) + echo ignoreMsg(p, e) + + of cfgSectionStart, cfgOption, cfgError: + echo ignoreMsg(p, e) + of cfgEof: + break + close(p) diff --git a/testament/tester.nim b/testament/tester.nim index 60cf46423..d8c0f2e11 100644 --- a/testament/tester.nim +++ b/testament/tester.nim @@ -48,7 +48,7 @@ type name: string cat: Category options: string - action: TTestAction + spec: TSpec startTime: float # ---------------------------------------------------------------------------- @@ -113,7 +113,7 @@ proc nimcacheDir(filename, options: string, target: TTarget): string = proc callCompiler(cmdTemplate, filename, options: string, target: TTarget, extraOptions=""): TSpec = let nimcache = nimcacheDir(filename, options, target) - let options = options & " " & ("--nimCache:" & nimcache).quoteShell & extraOptions + let options = options & " " & quoteShell("--nimCache:" & nimcache) & extraOptions let c = parseCmdLine(cmdTemplate % ["target", targetToCmd[target], "options", options, "file", filename.quoteShell, "filedir", filename.getFileDir()]) @@ -222,7 +222,6 @@ proc addResult(r: var TResults, test: TTest, target: TTarget, backend.writeTestResult(name = name, category = test.cat.string, target = $target, - action = $test.action, result = $success, expected = expected, given = given) @@ -346,15 +345,10 @@ proc compilerOutputTests(test: TTest, target: TTarget, given: var TSpec, r.addResult(test, target, expectedmsg, givenmsg, given.err) proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) = - let tname = test.name.addFileExt(".nim") - var expected: TSpec - if test.action != actionRunNoSpec: - expected = parseSpec(tname) - else: - specDefaults expected - expected.action = actionRunNoSpec + var expected = test.spec if expected.err == reIgnored: + echo expected # targetC is a lie r.addResult(test, targetC, "", "", reIgnored) inc(r.skipped) @@ -401,10 +395,10 @@ proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) = let isJsTarget = target == targetJS var exeFile: string if isJsTarget: - let (_, file, _) = splitFile(tname) - exeFile = nimcacheDir(test.name, test.options, target) / file & ".js" + let file = addFileExt(test.name, "js") + exeFile = nimcacheDir(test.name, test.options, target) / file else: - exeFile = changeFileExt(tname, ExeExt) + exeFile = addFileExt(test.name, ExeExt) if not existsFile(exeFile): r.addResult(test, target, expected.outp, "executable not found", reExeNotFound) @@ -468,7 +462,7 @@ proc testNoSpec(r: var TResults, test: TTest, target = targetC) = r.addResult(test, target, "", given.msg, given.err) if given.err == reSuccess: inc(r.passed) -proc testC(r: var TResults, test: TTest) = +proc testC(r: var TResults, test: TTest, action: TTestAction) = # runs C code. Doesn't support any specs, just goes by exit code. let tname = test.name.addFileExt(".c") inc(r.total) @@ -476,7 +470,7 @@ proc testC(r: var TResults, test: TTest) = var given = callCCompiler(cmdTemplate(), test.name & ".c", test.options, targetC) if given.err != reSuccess: r.addResult(test, targetC, "", given.msg, given.err) - elif test.action == actionRun: + elif action == actionRun: let exeFile = changeFileExt(test.name, ExeExt) var (_, exitCode) = execCmdEx(exeFile, options = {poStdErrToStdOut, poUsePath}) if exitCode != 0: given.err = reExitCodesDiffer @@ -486,8 +480,7 @@ proc testExec(r: var TResults, test: TTest) = # runs executable or script, just goes by exit code inc(r.total) let (outp, errC) = execCmdEx(test.options.strip()) - var given: TSpec - specDefaults(given) + var given: TSpec = defaultSpec() if errC == 0: given.err = reSuccess else: @@ -497,8 +490,12 @@ proc testExec(r: var TResults, test: TTest) = if given.err == reSuccess: inc(r.passed) r.addResult(test, targetC, "", given.msg, given.err) -proc makeTest(test, options: string, cat: Category, env: string = ""): TTest = - result = TTest(cat: cat, name: test, options: options, startTime: epochTime()) +proc makeTest(test, options: string, cat: Category): TTest = + result.cat = cat + result.name = test + result.options = options + result.spec = parseSpec(addFileExt(test, ".nim")) + result.startTime = epochTime() when defined(windows): const @@ -535,7 +532,8 @@ proc main() = of "targets": targetsStr = p.val.string targets = parseTargets(targetsStr) - of "nim": compilerPrefix = p.val.string + of "nim": + compilerPrefix = p.val.string of "directory": setCurrentDir(p.val.string) of "colors": diff --git a/tests/realtimeGC/shared.nim b/tests/realtimeGC/shared.nim index 2d1dd6c3c..1abe42089 100644 --- a/tests/realtimeGC/shared.nim +++ b/tests/realtimeGC/shared.nim @@ -1,5 +1,6 @@ discard """ - cmd: "nim $target --debuginfo --hints:on --app:lib $options $file" +cmd: "nim $target --debuginfo --hints:on --app:lib $options $file" +action: compile """ import strutils From da78c3d04de166866354b9e8126863d9bf91e94f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arne=20D=C3=B6ring?= Date: Wed, 28 Nov 2018 02:33:39 +0100 Subject: [PATCH 068/110] one error less --- testament/categories.nim | 3 ++- testament/specs.nim | 8 ++++++-- testament/tester.nim | 15 ++------------- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/testament/categories.nim b/testament/categories.nim index b641430a1..38f61ce33 100644 --- a/testament/categories.nim +++ b/testament/categories.nim @@ -476,7 +476,8 @@ proc processSingleTest(r: var TResults, cat: Category, options, test: string) = let test = "tests" & DirSep &.? cat.string / test let target = if cat.string.normalize == "js": targetJS else: targetC - if existsFile(test): testSpec r, makeTest(test, options, cat), {target} + if existsFile(test): + testSpec r, makeTest(test, options, cat), {target} else: echo "[Warning] - ", test, " test does not exist" proc processCategory(r: var TResults, cat: Category, options: string) = diff --git a/testament/specs.nim b/testament/specs.nim index 9b2347bf9..3cfddc414 100644 --- a/testament/specs.nim +++ b/testament/specs.nim @@ -111,8 +111,9 @@ proc parseTargets*(value: string): set[TTarget] = proc parseSpec*(filename: string): TSpec = result = defaultSpec() result.file = filename - var ss = newStringStream(extractSpec(filename)) - var p {.inject.}: CfgParser + let specStr = extractSpec(filename) + var ss = newStringStream(specStr) + var p: CfgParser open(p, ss, filename, 1) while true: var e = next(p) @@ -215,3 +216,6 @@ proc parseSpec*(filename: string): TSpec = of cfgEof: break close(p) + + if result.err == reIgnored: + echo specStr diff --git a/testament/tester.nim b/testament/tester.nim index d8c0f2e11..111b701be 100644 --- a/testament/tester.nim +++ b/testament/tester.nim @@ -348,7 +348,6 @@ proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) = var expected = test.spec if expected.err == reIgnored: - echo expected # targetC is a lie r.addResult(test, targetC, "", "", reIgnored) inc(r.skipped) @@ -366,10 +365,6 @@ proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) = for target in expected.targets: inc(r.total) - if target notin targets: - r.addResult(test, target, "", "", reIgnored) - inc(r.skipped) - continue case expected.action of actionCompile: @@ -382,12 +377,6 @@ proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) = var given = callCompiler(expected.cmd, test.name, test.options, target) - # echo "expected.cmd: ", expected.cmd - # echo "nimout: ", given.nimout - # echo "outp: ", given.outp - # echo "msg: ", given.msg - # echo "err: ", given.err - if given.err != reSuccess: r.addResult(test, target, "", given.msg, given.err) continue @@ -395,10 +384,10 @@ proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) = let isJsTarget = target == targetJS var exeFile: string if isJsTarget: - let file = addFileExt(test.name, "js") + let file = changeFileExt(test.name, "js") exeFile = nimcacheDir(test.name, test.options, target) / file else: - exeFile = addFileExt(test.name, ExeExt) + exeFile = changeFileExt(test.name, ExeExt) if not existsFile(exeFile): r.addResult(test, target, expected.outp, "executable not found", reExeNotFound) From e9ea8fb6b032702de982c59b8391c4419efc3c46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arne=20D=C3=B6ring?= Date: Wed, 28 Nov 2018 08:34:15 +0100 Subject: [PATCH 069/110] remove echo --- testament/specs.nim | 3 --- 1 file changed, 3 deletions(-) diff --git a/testament/specs.nim b/testament/specs.nim index 3cfddc414..d4f4a7371 100644 --- a/testament/specs.nim +++ b/testament/specs.nim @@ -216,6 +216,3 @@ proc parseSpec*(filename: string): TSpec = of cfgEof: break close(p) - - if result.err == reIgnored: - echo specStr From 465e7421827e752d94d1f283b6ce23f6b4125306 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arne=20D=C3=B6ring?= Date: Wed, 28 Nov 2018 09:43:22 +0100 Subject: [PATCH 070/110] fix js category --- testament/tester.nim | 6 +++--- tests/js/t7224.nim | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/testament/tester.nim b/testament/tester.nim index 111b701be..27a3ec089 100644 --- a/testament/tester.nim +++ b/testament/tester.nim @@ -384,7 +384,7 @@ proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) = let isJsTarget = target == targetJS var exeFile: string if isJsTarget: - let file = changeFileExt(test.name, "js") + let file = test.name.lastPathPart.changeFileExt("js") exeFile = nimcacheDir(test.name, test.options, target) / file else: exeFile = changeFileExt(test.name, ExeExt) @@ -428,8 +428,8 @@ proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) = bufB, reExitCodesDiffer) continue - if (expected.outputCheck == ocEqual and bufB != expected.outp) or - (expected.outputCheck == ocSubstr and bufB notin expected.outp): + if (expected.outputCheck == ocEqual and expected.outp != bufB) or + (expected.outputCheck == ocSubstr and expected.outp notin bufB): given.err = reOutputsDiffer r.addResult(test, target, expected.outp, bufB, reOutputsDiffer) continue diff --git a/tests/js/t7224.nim b/tests/js/t7224.nim index 2d7ee1336..be9d0ae9c 100644 --- a/tests/js/t7224.nim +++ b/tests/js/t7224.nim @@ -7,7 +7,7 @@ t7224.ccc, line: 15 t7224.ddd, line: 12 ''' """ - + proc ddd() = raise newException(IOError, "didn't do stuff") @@ -22,5 +22,6 @@ proc aaa() = try: aaa() + except IOError as e: echo getStackTrace(e) From dec863a85a8bc7ffeaec5ed55e36394b9392016c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arne=20D=C3=B6ring?= Date: Wed, 28 Nov 2018 11:09:55 +0100 Subject: [PATCH 071/110] kill testnospec --- testament/categories.nim | 10 +++++++--- testament/tester.nim | 8 -------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/testament/categories.nim b/testament/categories.nim index 38f61ce33..3d7b6a7d7 100644 --- a/testament/categories.nim +++ b/testament/categories.nim @@ -232,7 +232,7 @@ proc asyncTests(r: var TResults, cat: Category, options: string) = # ------------------------- debugger tests ------------------------------------ proc debuggerTests(r: var TResults, cat: Category, options: string) = - testNoSpec r, makeTest("tools/nimgrep", options & " --debugger:on", cat) + testSpec r, makeTest("tools/nimgrep", options & " --debugger:on", cat) # ------------------------- JS tests ------------------------------------------ @@ -355,11 +355,15 @@ proc manyLoc(r: var TResults, cat: Category, options: string) = if dir.endsWith"named_argument_bug": continue let mainfile = findMainFile(dir) if mainfile != "": - testNoSpec r, makeTest(mainfile, options, cat) + var test = makeTest(mainfile, options, cat) + test.spec.action = actionCompile + testSpec r, test proc compileExample(r: var TResults, pattern, options: string, cat: Category) = for test in os.walkFiles(pattern): - testNoSpec r, makeTest(test, options, cat) + var test = makeTest(test, options, cat) + test.spec.action = actionCompile + testSpec r, test proc testStdlib(r: var TResults, pattern, options: string, cat: Category) = for testFile in os.walkFiles(pattern): diff --git a/testament/tester.nim b/testament/tester.nim index 27a3ec089..a82467df7 100644 --- a/testament/tester.nim +++ b/testament/tester.nim @@ -443,14 +443,6 @@ proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) = cmpMsgs(r, expected, given, test, target) continue -proc testNoSpec(r: var TResults, test: TTest, target = targetC) = - # does not extract the spec because the file is not supposed to have any - #let tname = test.name.addFileExt(".nim") - inc(r.total) - let given = callCompiler(cmdTemplate(), test.name, test.options, target) - r.addResult(test, target, "", given.msg, given.err) - if given.err == reSuccess: inc(r.passed) - proc testC(r: var TResults, test: TTest, action: TTestAction) = # runs C code. Doesn't support any specs, just goes by exit code. let tname = test.name.addFileExt(".c") From a22bf14bb6614d763a50e8fd2dba4a7d7d48c9c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arne=20D=C3=B6ring?= Date: Wed, 28 Nov 2018 11:42:44 +0100 Subject: [PATCH 072/110] fix htmlgen, that I broke --- testament/backend.nim | 17 +++++++---------- testament/tester.nim | 1 + 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/testament/backend.nim b/testament/backend.nim index a1de5859a..c2658d6a0 100644 --- a/testament/backend.nim +++ b/testament/backend.nim @@ -20,14 +20,11 @@ var thisCommit: CommitId thisBranch: string -{.experimental.} -proc `()`(cmd: string{lit}): string = cmd.execProcess.string.strip - proc getMachine*(): MachineId = - var name = "hostname"() + var name = execProcess("hostname").string.strip if name.len == 0: - name = when defined(posix): getenv"HOSTNAME".string - else: getenv"COMPUTERNAME".string + name = when defined(posix): getenv("HOSTNAME").string + else: getenv("COMPUTERNAME").string if name.len == 0: quit "cannot determine the machine name" @@ -35,8 +32,8 @@ proc getMachine*(): MachineId = proc getCommit(): CommitId = const commLen = "commit ".len - let hash = "git log -n 1"()[commLen..commLen+10] - thisBranch = "git symbolic-ref --short HEAD"() + let hash = execProcess("git log -n 1").string.strip[commLen..commLen+10] + thisBranch = execProcess("git symbolic-ref --short HEAD").string.strip if hash.len == 0 or thisBranch.len == 0: quit "cannot determine git HEAD" result = CommitId(hash) @@ -45,7 +42,7 @@ var currentCategory: string entries: int -proc writeTestResult*(name, category, target, result, expected, given: string) = +proc writeTestResult*(name, category, target, action, result, expected, given: string) = createDir("testresults") if currentCategory != category: if currentCategory.len > 0: @@ -57,7 +54,7 @@ proc writeTestResult*(name, category, target, result, expected, given: string) = entries = 0 let jentry = %*{"name": name, "category": category, "target": target, - "result": result, "expected": expected, "given": given, + "action": action, "result": result, "expected": expected, "given": given, "machine": thisMachine.string, "commit": thisCommit.string, "branch": thisBranch} if entries > 0: results.writeLine(",") diff --git a/testament/tester.nim b/testament/tester.nim index a82467df7..6a6b73507 100644 --- a/testament/tester.nim +++ b/testament/tester.nim @@ -222,6 +222,7 @@ proc addResult(r: var TResults, test: TTest, target: TTarget, backend.writeTestResult(name = name, category = test.cat.string, target = $target, + action = $test.spec.action, result = $success, expected = expected, given = given) From 199018ef2eb640cb3a5f5736220a752482d69e9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arne=20D=C3=B6ring?= Date: Wed, 28 Nov 2018 12:51:41 +0100 Subject: [PATCH 073/110] test can fail because of invalid spec --- lib/pure/parsecfg.nim | 11 ----------- testament/specs.nim | 35 ++++++++++++++++++++++++++++------- testament/tester.nim | 7 ++++++- 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/lib/pure/parsecfg.nim b/lib/pure/parsecfg.nim index b991dd57f..efe679d67 100644 --- a/lib/pure/parsecfg.nim +++ b/lib/pure/parsecfg.nim @@ -386,17 +386,6 @@ proc warningStr*(c: CfgParser, msg: string): string {.rtl, extern: "npc$1".} = result = `%`("$1($2, $3) Warning: $4", [c.filename, $getLine(c), $getColumn(c), msg]) -proc ignoreMsg*(c: CfgParser, e: CfgEvent): string {.rtl, extern: "npc$1".} = - ## returns a properly formatted warning message containing that - ## an entry is ignored. - case e.kind - of cfgSectionStart: result = c.warningStr("section ignored: " & e.section) - of cfgKeyValuePair: result = c.warningStr("key ignored: " & e.key) - of cfgOption: - result = c.warningStr("command ignored: " & e.key & ": " & e.value) - of cfgError: result = e.msg - of cfgEof: result = "" - proc getKeyValPair(c: var CfgParser, kind: CfgEventKind): CfgEvent = if c.tok.kind == tkSymbol: result.kind = kind diff --git a/testament/specs.nim b/testament/specs.nim index d4f4a7371..3583166fe 100644 --- a/testament/specs.nim +++ b/testament/specs.nim @@ -44,6 +44,7 @@ type reBuildFailed # package building failed reIgnored, # test is ignored reSuccess # test was successful + reInvalidSpec # test had problems to parse the spec TTarget* = enum targetC = "C" @@ -68,6 +69,7 @@ type err*: TResultEnum targets*: set[TTarget] nimout*: string + parseErrors*: string # when the spec definition is invalid, this is not empty. const targetToExt*: array[TTarget, string] = ["c", "cpp", "m", "js"] @@ -108,6 +110,16 @@ proc parseTargets*(value: string): set[TTarget] = of "js": result.incl(targetJS) else: echo "target ignored: " & v + +proc addLine(self: var string; a: string) = + self.add a + self.add "\n" + +proc addLine(self: var string; a,b: string) = + self.add a + self.add b + self.add "\n" + proc parseSpec*(filename: string): TSpec = result = defaultSpec() result.file = filename @@ -129,7 +141,7 @@ proc parseSpec*(filename: string): TSpec = of "reject": result.action = actionReject else: - echo ignoreMsg(p, e) + result.parseErrors.addLine "cannot interpret as action: ", e.value of "file": result.file = e.value of "line": @@ -151,7 +163,10 @@ proc parseSpec*(filename: string): TSpec = result.outputCheck = ocSubstr result.outp = strip(e.value) of "sortoutput": - result.sortoutput = parseCfgBool(e.value) + try: + result.sortoutput = parseCfgBool(e.value) + except: + result.parseErrors.addLine getCurrentExceptionMsg() of "exitcode": discard parseInt(e.value, result.exitCode) result.action = actionRun @@ -185,7 +200,7 @@ proc parseSpec*(filename: string): TSpec = of "appveyor": if isAppVeyor: result.err = reIgnored else: - raise newException(ValueError, "cannot interpret as a bool: " & e.value) + result.parseErrors.addLine "cannot interpret as a bool: ", e.value of "cmd": if e.value.startsWith("nim "): result.cmd = compilerPrefix & e.value[3..^1] @@ -207,12 +222,18 @@ proc parseSpec*(filename: string): TSpec = of "js": result.targets.incl(targetJS) else: - echo ignoreMsg(p, e) + result.parseErrors.addLine "cannot interpret as a target: ", e.value else: - echo ignoreMsg(p, e) + result.parseErrors.addLine "invalid key for test spec: ", e.key - of cfgSectionStart, cfgOption, cfgError: - echo ignoreMsg(p, e) + of cfgSectionStart: + result.parseErrors.addLine "section ignored: ", e.section + of cfgOption: + result.parseErrors.addLine "command ignored: ", e.key & ": " & e.value + of cfgError: + result.parseErrors.addLine e.msg of cfgEof: break + + close(p) diff --git a/testament/tester.nim b/testament/tester.nim index 6a6b73507..448471136 100644 --- a/testament/tester.nim +++ b/testament/tester.nim @@ -347,9 +347,14 @@ proc compilerOutputTests(test: TTest, target: TTarget, given: var TSpec, proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) = var expected = test.spec + if expected.parseErrors.len > 0: + # targetC is a lie, but parameter is required + r.addResult(test, targetC, "", expected.parseErrors, reInvalidSpec) + inc(r.total) + return if expected.err == reIgnored: - # targetC is a lie + # targetC is a lie, but parameter is required r.addResult(test, targetC, "", "", reIgnored) inc(r.skipped) inc(r.total) From ca394ebd9514edd6e5f5e5c3d3145aa868744647 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arne=20D=C3=B6ring?= Date: Thu, 29 Nov 2018 12:43:45 +0100 Subject: [PATCH 074/110] allow to disable backend logging --- testament/tester.nim | 27 +++++++++++++++++++-------- tests/testament/tshouldfail.nim | 2 +- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/testament/tester.nim b/testament/tester.nim index 448471136..7dfcf9d48 100644 --- a/testament/tester.nim +++ b/testament/tester.nim @@ -15,6 +15,7 @@ import algorithm, compiler/nodejs, times, sets, md5 var useColors = true +var backendLogging = true const resultsFile = "testresults.html" @@ -35,7 +36,8 @@ Options: --targets:"c c++ js objc" run tests for specified targets (default: all) --nim:path use a particular nim executable (default: compiler/nim) --directory:dir Change to directory dir before reading the tests or doing anything else. - --colors:on|off turn messagescoloring on|off + --colors:on|off Turn messagescoloring on|off. + --backendLogging:on|off Disable or enable backend logging. By default turned on. """ % resultsFile type @@ -219,13 +221,14 @@ proc addResult(r: var TResults, test: TTest, target: TTarget, let name = test.name.extractFilename & " " & $target & test.options let duration = epochTime() - test.startTime let durationStr = duration.formatFloat(ffDecimal, precision = 8).align(11) - backend.writeTestResult(name = name, - category = test.cat.string, - target = $target, - action = $test.spec.action, - result = $success, - expected = expected, - given = given) + if backendLogging: + backend.writeTestResult(name = name, + category = test.cat.string, + target = $target, + action = $test.spec.action, + result = $success, + expected = expected, + given = given) r.data.addf("$#\t$#\t$#\t$#", name, expected, given, $success) if success == reSuccess: maybeStyledEcho fgGreen, "PASS: ", fgCyan, alignLeft(name, 60), fgBlue, " (", durationStr, " secs)" @@ -531,6 +534,14 @@ proc main() = useColors = false else: quit Usage + of "backendlogging": + case p.val.string: + of "on": + backendLogging = true + of "off": + backendLogging = false + else: + quit Usage else: quit Usage p.next() diff --git a/tests/testament/tshouldfail.nim b/tests/testament/tshouldfail.nim index 02e4bfd80..a8638e236 100644 --- a/tests/testament/tshouldfail.nim +++ b/tests/testament/tshouldfail.nim @@ -1,5 +1,5 @@ discard """ -cmd: "testament/tester --directory:testament --colors:off --nim:../compiler/nim category shouldfail" +cmd: "testament/tester --directory:testament --colors:off --backendLogging:off --nim:../compiler/nim category shouldfail" action: compile nimout: ''' FAIL: tccodecheck.nim C From 1105d0364401226a2d7d479bd89d77a9da9ed787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arne=20D=C3=B6ring?= Date: Thu, 29 Nov 2018 16:07:51 +0100 Subject: [PATCH 075/110] require errormsg to be specified before file. --- testament/categories.nim | 35 +++++++++++++------ testament/specs.nim | 6 ++++ tests/ambsym/tambsym.nim | 4 +-- tests/ambsym/tambsym2.nim | 3 -- tests/ambsym/tambsym3.nim | 4 +-- tests/ambsym/tambsys.nim | 3 -- tests/array/tarray.nim | 4 +-- tests/array/tarraycons.nim | 5 +-- tests/array/tarraycons_ptr_generic2.nim | 2 +- tests/assert/tassert.nim | 3 -- tests/assign/tassign.nim | 1 - tests/assign/tvariantasgn.nim | 4 +-- tests/async/t7758.nim | 6 +--- tests/async/tasyncRecvLine.nim | 3 +- tests/async/tasync_gcunsafe.nim | 2 +- tests/async/tasyncall.nim | 1 - tests/async/tasyncawait.nim | 1 - tests/async/tasyncconnect.nim | 3 +- tests/async/tasyncdial.nim | 1 - tests/async/tasyncexceptions.nim | 3 +- tests/async/tasyncfile.nim | 5 ++- tests/async/tasyncrecursion.nim | 3 +- tests/async/tasyncsend4757.nim | 3 +- tests/async/tasyncssl.nim | 1 - tests/async/tasynctry.nim | 4 +-- tests/async/tawaitsemantics.nim | 4 +-- tests/async/tfuturestream.nim | 6 ++-- tests/async/tioselectors.nim | 1 - tests/async/tnewasyncudp.nim | 1 - tests/async/tpendingcheck.nim | 3 -- tests/async/twinasyncrw.nim | 1 - tests/bind/tbind.nim | 4 +-- tests/bind/tbind2.nim | 5 +-- tests/bind/tinvalidbindtypedesc.nim | 3 +- tests/bind/tnicerrorforsymchoice.nim | 2 +- tests/borrow/tinvalidborrow.nim | 3 +- tests/casestmt/t7699.nim | 2 +- tests/casestmt/tcaseexpr1.nim | 13 ++++--- tests/casestmt/tcaseoverlaprange.nim | 2 +- tests/casestmt/tcaseoverlaprange2.nim | 2 +- tests/casestmt/tcasestmt.nim | 5 ++- tests/ccgbugs/tcgbug.nim | 8 ++--- tests/clearmsg/tconsttypemismatch.nim | 3 +- tests/clearmsg/tmacroerrorproc.nim | 2 +- tests/closure/tinvalidclosure.nim | 2 +- tests/closure/tinvalidclosure2.nim | 2 +- tests/closure/tinvalidclosure3.nim | 4 +-- tests/closure/tnested.nim | 3 +- tests/cnstseq/tcnstseq.nim | 3 +- tests/collections/tcollections.nim | 4 +-- tests/collections/ttables.nim | 5 ++- tests/concepts/tconcepts.nim | 29 ++++++++------- tests/concepts/texplain.nim | 3 +- tests/constr/tconstr1.nim | 4 +-- tests/constr/tconstr2.nim | 4 --- tests/constraints/tconstraints.nim | 4 +-- tests/constructors/t5965_1.nim | 2 +- tests/constructors/t5965_2.nim | 2 +- tests/controlflow/tblock1.nim | 4 +-- tests/controlflow/tstatret.nim | 5 +-- tests/converter/tconverter_unique_ptr.nim | 7 ++-- .../converter/tconverter_with_constraint.nim | 8 ++--- tests/deprecated/tnoannot.nim | 2 +- tests/discard/tillegaldiscard.nim | 2 +- tests/discard/tneedsdiscard.nim | 2 +- tests/discard/tneedsdiscard_in_for.nim | 2 +- tests/distinct/tnil.nim | 4 +-- tests/effects/teffects1.nim | 3 +- tests/effects/teffects2.nim | 3 +- tests/effects/teffects3.nim | 3 +- tests/effects/teffects4.nim | 3 +- tests/effects/tgcsafe.nim | 2 +- tests/effects/tsidee1.nim | 5 +-- tests/effects/tsidee2.nim | 4 --- tests/effects/tsidee3.nim | 4 --- tests/effects/tsidee4.nim | 4 +-- tests/enum/tenumitems.nim | 4 +-- tests/errmsgs/t8339.nim | 2 +- tests/exception/tcontinuexc.nim | 4 --- tests/exception/texceptionbreak.nim | 1 - tests/exception/texcsub.nim | 4 --- tests/exception/tfinally.nim | 6 ++-- tests/exception/tfinally2.nim | 12 +++---- tests/exception/tfinally3.nim | 7 ++-- tests/exception/tfinally4.nim | 1 - tests/exception/tnestedreturn.nim | 1 - tests/exception/tnestedreturn2.nim | 1 - tests/exception/treraise.nim | 4 --- tests/exception/tunhandledexc.nim | 3 +- tests/exception/twrongexc.nim | 5 --- tests/exprs/texprstmt.nim | 2 +- tests/exprs/tstmtexp.nim | 3 +- tests/flags/tgenscript.nim | 1 - tests/float/tfloat1.nim | 3 -- tests/float/tfloat2.nim | 3 -- tests/float/tfloat3.nim | 4 --- tests/float/tfloat4.nim | 3 +- tests/float/tfloat5.nim | 7 ++-- tests/float/tfloat6.nim | 7 ++-- tests/float/tfloat7.nim | 7 ++-- tests/float/tfloatnan.nim | 4 +-- tests/float/tissue5821.nim | 8 +++-- tests/generics/t6137.nim | 3 +- tests/generics/t7141.nim | 3 +- tests/generics/t8270.nim | 2 +- tests/generics/tbintre2.nim | 4 --- tests/generics/tbintree.nim | 3 -- tests/generics/texplicitgeneric1.nim | 4 --- tests/global/t5958.nim | 2 +- tests/iter/tcountup.nim | 4 --- tests/iter/titer11.nim | 4 +-- tests/iter/titer3.nim | 1 - tests/iter/titer4.nim | 4 +-- tests/iter/titer5.nim | 4 --- tests/iter/titer6.nim | 4 --- tests/iter/titervaropenarray.nim | 1 - tests/iter/treciter.nim | 4 +-- tests/iter/twrongiter.nim | 2 +- tests/let/tlet.nim | 3 +- tests/let/tlet2.nim | 3 +- tests/lexer/tind1.nim | 2 +- tests/lexer/tinvalidintegerliteral1.nim | 2 +- tests/lexer/tinvalidintegerliteral2.nim | 2 +- tests/lexer/tinvalidintegerliteral3.nim | 2 +- tests/lexer/tmissingnl.nim | 3 +- tests/lexer/tstrlits.nim | 4 --- tests/lexer/tunderscores.nim | 5 +-- tests/macros/tmacrogenerics.nim | 1 - tests/macros/tquotewords.nim | 1 - tests/macros/trecmacro.nim | 2 +- tests/macros/tstringinterp.nim | 1 - tests/metatype/tmatrix.nim | 3 -- tests/metatype/tstaticparams.nim | 4 +-- tests/method/tmethod.nim | 2 +- tests/misc/t99bott.nim | 8 ++--- tests/misc/tack.nim | 3 -- tests/misc/tbug511622.nim | 4 --- tests/misc/temit.nim | 5 --- tests/misc/tevents.nim | 8 ++--- tests/misc/tgenconstraints.nim | 3 +- tests/misc/thintoff.nim | 12 ------- tests/misc/tinc.nim | 6 +--- tests/misc/tinit.nim | 3 -- tests/misc/tinout.nim | 4 +-- tests/misc/tinvalidnewseq.nim | 5 +-- tests/misc/tissue710.nim | 2 +- tests/misc/tnoinst.nim | 3 +- tests/misc/tnolen.nim | 3 +- tests/misc/tnot.nim | 2 +- tests/misc/tparseopt.nim | 1 - tests/misc/tpos.nim | 3 -- tests/misc/trawstr.nim | 4 +-- tests/misc/tsimtych.nim | 4 +-- tests/misc/tslices.nim | 5 ++- tests/misc/tstrange.nim | 8 ++--- tests/misc/tvarious1.nim | 4 +-- tests/misc/tvarnums.nim | 3 -- tests/modules/timportexcept.nim | 3 +- tests/modules/tmismatchedvisibility.nim | 2 +- tests/modules/tnamspc.nim | 4 +-- tests/modules/tnotuniquename.nim | 2 +- tests/modules/tnotuniquename2.nim | 2 +- tests/modules/topaque.nim | 4 +-- tests/modules/trecinca.nim | 4 +-- tests/modules/trecincb.nim | 4 +-- tests/modules/trecmod.nim | 2 +- tests/modules/tselfimport.nim | 3 +- tests/namedparams/tnamedparams.nim | 5 +-- .../niminaction/Chapter2/explicit_discard.nim | 4 +-- tests/niminaction/Chapter2/no_def_eq.nim | 4 +-- tests/niminaction/Chapter2/no_iterator.nim | 4 +-- tests/niminaction/Chapter2/no_seq_type.nim | 4 +-- tests/niminaction/Chapter2/resultreject.nim | 8 ++--- tests/notnil/tnotnil.nim | 2 +- tests/objects/tobjpragma.nim | 9 ++--- tests/objects/toop1.nim | 1 - tests/objvariant/tadrdisc.nim | 2 +- tests/objvariant/temptycaseobj.nim | 4 +-- tests/objvariant/tvariantstack.nim | 3 +- tests/openarray/t8259.nim | 2 +- tests/openarray/topena1.nim | 5 +-- tests/openarray/topenarrayrepr.nim | 4 --- tests/openarray/topenlen.nim | 3 -- tests/openarray/tptrarrayderef.nim | 9 +++-- tests/osproc/texecps.nim | 1 - tests/osproc/texitcode.nim | 1 - tests/osproc/tstdin.nim | 1 - tests/osproc/tworkingdir.nim | 1 - tests/overflw/toverflw.nim | 2 -- tests/overflw/toverflw2.nim | 3 -- tests/overflw/tovfint.nim | 3 -- tests/overload/toverl.nim | 4 +-- tests/parallel/tgc_unsafe2.nim | 2 +- tests/parallel/tsysspawnbadarg.nim | 2 +- tests/parser/tdomulttest.nim | 4 +-- tests/parser/tinvcolonlocation1.nim | 2 +- tests/parser/tinvcolonlocation2.nim | 2 +- tests/parser/tinvcolonlocation3.nim | 2 +- tests/parser/tinvwhen.nim | 4 +-- tests/parser/toprprec.nim | 1 - tests/parser/ttupleunpack.nim | 6 ---- tests/pragmas/t6448.nim | 4 +-- tests/pragmas/t8741.nim | 2 +- tests/pragmas/tuserpragma2.nim | 2 +- tests/proc/tprocredef.nim | 3 +- tests/range/tsubrange.nim | 3 +- tests/range/tsubrange2.nim | 2 -- tests/range/tsubrange3.nim | 1 - tests/rational/trat_float.nim | 2 +- tests/sets/t2669.nim | 2 +- tests/sets/tsets.nim | 7 ++-- tests/stdlib/t8925.nim | 2 +- tests/stdlib/tbitops.nim | 1 - tests/stdlib/tbitops2.nim | 1 - tests/stdlib/tcgi.nim | 6 ---- tests/stdlib/tjsonmacro.nim | 1 - tests/stdlib/tjsonmacro_reject.nim | 4 +-- tests/stdlib/tjsonmacro_reject2.nim | 4 +-- tests/stdlib/tmemfiles1.nim | 4 --- tests/stdlib/tmemmapstreams.nim | 4 +-- tests/stdlib/tospaths.nim | 1 - tests/stdlib/tosproc.nim | 1 - tests/stdlib/tparsesql.nim | 4 --- tests/stdlib/tregex.nim | 3 -- tests/stdlib/trepr.nim | 2 -- tests/stdlib/tstreams2.nim | 1 - tests/stdlib/tstreams3.nim | 1 - tests/stdlib/tstring.nim | 1 - tests/stdlib/tstrutil.nim | 1 - tests/stdlib/tsugar.nim | 1 - tests/stdlib/ttimes.nim | 11 +++--- tests/template/ttempl2.nim | 3 +- tests/threads/tthreadanalysis2.nim | 3 +- tests/threads/tthreadheapviolation1.nim | 4 +-- tests/trmacros/tdisallowif.nim | 2 +- tests/tuples/twrongtupleaccess.nim | 3 +- tests/typerel/t8172.nim | 2 +- tests/typerel/temptynode.nim | 2 +- tests/typerel/tno_int_in_bool_context.nim | 3 +- tests/typerel/tnocontains.nim | 2 +- tests/typerel/trefs.nim | 5 +-- tests/typerel/tregionptrs.nim | 2 +- tests/typerel/ttypedesc_as_genericparam1.nim | 2 +- tests/typerel/ttypedesc_as_genericparam2.nim | 2 +- tests/typerel/ttypenoval.nim | 4 +-- tests/typerel/typredef.nim | 3 +- tests/types/t6456.nim | 2 +- tests/types/tassignemptytuple.nim | 2 +- tests/types/tillrec.nim | 3 +- tests/types/tparameterizedparent0.nim | 2 +- tests/types/tparameterizedparent1.nim | 2 +- tests/types/tparameterizedparent3.nim | 2 +- tests/types/tparameterizedparent4.nim | 2 +- tests/usingstmt/tusingstatement.nim | 1 - tests/varres/tnewseq_on_result_vart.nim | 2 +- .../varres/tprevent_forloopvar_mutations.nim | 2 +- tests/varres/tvarres1.nim | 3 +- tests/varres/tvarres2.nim | 3 +- tests/varres/tvarres_via_forwarding.nim | 2 +- tests/varres/tvartup.nim | 3 -- tests/varres/twrong_parameter.nim | 2 +- tests/varstmt/tvardecl.nim | 3 -- tests/vm/t2574.nim | 2 +- tests/vm/tcastint.nim | 5 ++- 264 files changed, 305 insertions(+), 623 deletions(-) delete mode 100644 tests/misc/thintoff.nim diff --git a/testament/categories.nim b/testament/categories.nim index 3d7b6a7d7..6ab14a2cf 100644 --- a/testament/categories.nim +++ b/testament/categories.nim @@ -299,17 +299,28 @@ proc testNimInAction(r: var TResults, cat: Category, options: string) = # edit when making a conscious breaking change, also please try to make your # commit message clear and notify me so I can easily compile an errata later. const refHashes = @[ - "51afdfa84b3ca3d810809d6c4e5037ba", "30f07e4cd5eaec981f67868d4e91cfcf", - "d14e7c032de36d219c9548066a97e846", "2e40bfd5daadb268268727da91bb4e81", - "c5d3853ed0aba04bf6d35ba28a98dca0", "058603145ff92d46c009006b06e5b228", - "7b94a029b94ddb7efafddd546c965ff6", "586d74514394e49f2370dfc01dd9e830", - "13febc363ed82585f2a60de40ddfefda", "c11a013db35e798f44077bc0763cc86d", - "3e32e2c5e9a24bd13375e1cd0467079c", "0b9fe7ba159623d49ae60db18a15037c", - "b2dd5293d7f784824bbf9792c6fb51ad", "4c19d8d9026bfe151b31d7007fa3c237", - "9415c6a568cfceed08da8378e95b5cd5", "da520038c153f4054cb8cc5faa617714", - "e6c6e061b6f77b2475db6fec7abfb7f4", "9a8fe78c588d08018843b64b57409a02", - "8b5d28e985c0542163927d253a3e4fc9", "783299b98179cc725f9c46b5e3b5381f", - "bc523f9a9921299090bac1af6c958e73", "80f9c3e594a798225046e8a42e990daf" + "51afdfa84b3ca3d810809d6c4e5037ba", + "30f07e4cd5eaec981f67868d4e91cfcf", + "d14e7c032de36d219c9548066a97e846", + "b335635562ff26ec0301bdd86356ac0c", + "6c4add749fbf50860e2f523f548e6b0e", + "76de5833a7cc46f96b006ce51179aeb1", + "705eff79844e219b47366bd431658961", + "a1e87b881c5eb161553d119be8b52f64", + "13febc363ed82585f2a60de40ddfefda", + "c11a013db35e798f44077bc0763cc86d", + "3e32e2c5e9a24bd13375e1cd0467079c", + "0b9fe7ba159623d49ae60db18a15037c", + "b2dd5293d7f784824bbf9792c6fb51ad", + "4c19d8d9026bfe151b31d7007fa3c237", + "9415c6a568cfceed08da8378e95b5cd5", + "da520038c153f4054cb8cc5faa617714", + "e6c6e061b6f77b2475db6fec7abfb7f4", + "9a8fe78c588d08018843b64b57409a02", + "8b5d28e985c0542163927d253a3e4fc9", + "783299b98179cc725f9c46b5e3b5381f", + "bc523f9a9921299090bac1af6c958e73", + "80f9c3e594a798225046e8a42e990daf", ] for i, test in tests: @@ -317,6 +328,8 @@ proc testNimInAction(r: var TResults, cat: Category, options: string) = let testHash = getMD5(readFile(filename).string) doAssert testHash == refHashes[i], "Nim in Action test " & filename & " was changed." + + # Run the tests. for testfile in tests: test "tests/" & testfile & ".nim" diff --git a/testament/specs.nim b/testament/specs.nim index 3583166fe..6c9fafa13 100644 --- a/testament/specs.nim +++ b/testament/specs.nim @@ -143,10 +143,16 @@ proc parseSpec*(filename: string): TSpec = else: result.parseErrors.addLine "cannot interpret as action: ", e.value of "file": + if result.msg.len == 0 and result.nimout.len == 0: + result.parseErrors.addLine "errormsg or msg needs to be specified before file" result.file = e.value of "line": + if result.msg.len == 0 and result.nimout.len == 0: + result.parseErrors.addLine "errormsg, msg or nimout needs to be specified before line" discard parseInt(e.value, result.line) of "column": + if result.msg.len == 0 and result.nimout.len == 0: + result.parseErrors.addLine "errormsg or msg needs to be specified before column" discard parseInt(e.value, result.column) of "tfile": result.tfile = e.value diff --git a/tests/ambsym/tambsym.nim b/tests/ambsym/tambsym.nim index d9115e16d..bd0f41717 100644 --- a/tests/ambsym/tambsym.nim +++ b/tests/ambsym/tambsym.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "ambiguous identifier" file: "tambsym.nim" line: 11 - errormsg: "ambiguous identifier" """ # Test ambiguous symbols @@ -11,5 +11,3 @@ var v: TExport #ERROR_MSG ambiguous identifier v = y - - diff --git a/tests/ambsym/tambsym2.nim b/tests/ambsym/tambsym2.nim index 8e288e73a..747f1a086 100644 --- a/tests/ambsym/tambsym2.nim +++ b/tests/ambsym/tambsym2.nim @@ -1,5 +1,4 @@ discard """ - file: "tambsym2.nim" output: "7" """ # Test overloading of procs with locals @@ -20,5 +19,3 @@ m.len = 7 m.data = "1234" x(m, 5) #OUT 7 - - diff --git a/tests/ambsym/tambsym3.nim b/tests/ambsym/tambsym3.nim index b25dadfd6..0558517bd 100644 --- a/tests/ambsym/tambsym3.nim +++ b/tests/ambsym/tambsym3.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "ambiguous identifier" file: "tambsym3.nim" line: 11 - errormsg: "ambiguous identifier" """ # Test ambiguous symbols @@ -11,5 +11,3 @@ var v = mDec #ERROR_MSG ambiguous identifier writeLine(stdout, ord(v)) - - diff --git a/tests/ambsym/tambsys.nim b/tests/ambsym/tambsys.nim index 67522d7c9..aa740c38f 100644 --- a/tests/ambsym/tambsys.nim +++ b/tests/ambsym/tambsys.nim @@ -1,5 +1,4 @@ discard """ - file: "tambsys.nim" output: "" """ # Test ambiguous symbols @@ -9,5 +8,3 @@ import mambsys1, mambsys2 var v: mambsys1.TExport mambsys2.foo(3) #OUT - - diff --git a/tests/array/tarray.nim b/tests/array/tarray.nim index 8551d324c..d12808668 100644 --- a/tests/array/tarray.nim +++ b/tests/array/tarray.nim @@ -1,7 +1,5 @@ discard """ - file: "tarray.nim" - output: -''' +output: ''' [4, 5, 6] [16, 25, 36] diff --git a/tests/array/tarraycons.nim b/tests/array/tarraycons.nim index 9f09fd405..b6ebe55c8 100644 --- a/tests/array/tarraycons.nim +++ b/tests/array/tarraycons.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "invalid order in array constructor" file: "tarraycons.nim" line: 14 - errormsg: "invalid order in array constructor" """ type @@ -19,6 +19,3 @@ const ] echo myMapping[eC][1] - - - diff --git a/tests/array/tarraycons_ptr_generic2.nim b/tests/array/tarraycons_ptr_generic2.nim index fce7af669..f6ed32b58 100644 --- a/tests/array/tarraycons_ptr_generic2.nim +++ b/tests/array/tarraycons_ptr_generic2.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "type mismatch: got but expected 'Book[system.string]'" file: "tarraycons_ptr_generic2.nim" line: 17 - errormsg: "type mismatch: got but expected 'Book[system.string]'" """ type diff --git a/tests/assert/tassert.nim b/tests/assert/tassert.nim index b5f2fb715..99929f080 100644 --- a/tests/assert/tassert.nim +++ b/tests/assert/tassert.nim @@ -1,5 +1,4 @@ discard """ - file: "tassert.nim" outputsub: "assertion failure!this shall be always written" exitcode: "1" """ @@ -19,5 +18,3 @@ finally: system.write(stdout, "this shall be always written") assert(false) #OUT assertion failure!this shall be always written - - diff --git a/tests/assign/tassign.nim b/tests/assign/tassign.nim index cb03b5004..b421802ae 100644 --- a/tests/assign/tassign.nim +++ b/tests/assign/tassign.nim @@ -1,5 +1,4 @@ discard """ - file: "tassign.nim" output: ''' TEMP=C:\Programs\xyz\bin diff --git a/tests/assign/tvariantasgn.nim b/tests/assign/tvariantasgn.nim index 46cc23dd1..2278957ac 100644 --- a/tests/assign/tvariantasgn.nim +++ b/tests/assign/tvariantasgn.nim @@ -1,7 +1,7 @@ discard """ - file: "tvariantasgn.nim" output: "came here" """ + #BUG type TAnyKind = enum @@ -26,5 +26,3 @@ nr.intVal = 78 # s = nr # works nr = s # fails! echo "came here" - - diff --git a/tests/async/t7758.nim b/tests/async/t7758.nim index 102a4ce4c..ce4df1fc9 100644 --- a/tests/async/t7758.nim +++ b/tests/async/t7758.nim @@ -1,7 +1,3 @@ -discard """ - file: "t7758.nim" - exitcode: 0 -""" import asyncdispatch proc task() {.async.} = @@ -16,4 +12,4 @@ proc main() = doAssert counter <= 4 -for i in 0 .. 10: main() \ No newline at end of file +for i in 0 .. 10: main() diff --git a/tests/async/tasyncRecvLine.nim b/tests/async/tasyncRecvLine.nim index 679831b27..a13a171c3 100644 --- a/tests/async/tasyncRecvLine.nim +++ b/tests/async/tasyncRecvLine.nim @@ -1,6 +1,5 @@ discard """ - file: "tasyncRecvLine.nim" - output: ''' +output: ''' Hello World Hello World ''' diff --git a/tests/async/tasync_gcunsafe.nim b/tests/async/tasync_gcunsafe.nim index f4e2cdcf2..55b66aaef 100644 --- a/tests/async/tasync_gcunsafe.nim +++ b/tests/async/tasync_gcunsafe.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "'anotherGCSafeAsyncProcIter' is not GC-safe as it calls 'asyncGCUnsafeProc'" cmd: "nim c --threads:on $file" file: "asyncmacro.nim" - errormsg: "'anotherGCSafeAsyncProcIter' is not GC-safe as it calls 'asyncGCUnsafeProc'" """ assert compileOption("threads"), "this test will not do anything useful without --threads:on" diff --git a/tests/async/tasyncall.nim b/tests/async/tasyncall.nim index 3e30e8ba8..3c318dbf7 100644 --- a/tests/async/tasyncall.nim +++ b/tests/async/tasyncall.nim @@ -1,5 +1,4 @@ discard """ - file: "tasyncall.nim" exitcode: 0 """ import times, sequtils diff --git a/tests/async/tasyncawait.nim b/tests/async/tasyncawait.nim index e7a2ec1d9..fcb48a1f5 100644 --- a/tests/async/tasyncawait.nim +++ b/tests/async/tasyncawait.nim @@ -1,5 +1,4 @@ discard """ - file: "tasyncawait.nim" output: "5000" """ import asyncdispatch, nativesockets, net, strutils, os diff --git a/tests/async/tasyncconnect.nim b/tests/async/tasyncconnect.nim index 3dac379b2..f63a87990 100644 --- a/tests/async/tasyncconnect.nim +++ b/tests/async/tasyncconnect.nim @@ -1,7 +1,6 @@ discard """ - file: "tasyncconnect.nim" - exitcode: 1 outputsub: "Error: unhandled exception: Connection refused" + exitcode: 1 """ import diff --git a/tests/async/tasyncdial.nim b/tests/async/tasyncdial.nim index fa81235fe..815520294 100644 --- a/tests/async/tasyncdial.nim +++ b/tests/async/tasyncdial.nim @@ -1,5 +1,4 @@ discard """ - file: "tasyncdial.nim" output: ''' OK AF_INET OK AF_INET6 diff --git a/tests/async/tasyncexceptions.nim b/tests/async/tasyncexceptions.nim index 7aa1d7fb0..3a34478ca 100644 --- a/tests/async/tasyncexceptions.nim +++ b/tests/async/tasyncexceptions.nim @@ -1,7 +1,6 @@ discard """ - file: "tasyncexceptions.nim" - exitcode: 1 outputsub: "Error: unhandled exception: foobar" + exitcode: 1 """ import asyncdispatch diff --git a/tests/async/tasyncfile.nim b/tests/async/tasyncfile.nim index c7b71a2f7..3043b680a 100644 --- a/tests/async/tasyncfile.nim +++ b/tests/async/tasyncfile.nim @@ -1,10 +1,9 @@ discard """ - output: '''13 +output: ''' +13 hello humans! 13 ''' - file: "tasyncfile.nim" - exitcode: 0 """ import asyncfile, asyncdispatch, os diff --git a/tests/async/tasyncrecursion.nim b/tests/async/tasyncrecursion.nim index 1aeebe9b4..c038be640 100644 --- a/tests/async/tasyncrecursion.nim +++ b/tests/async/tasyncrecursion.nim @@ -1,6 +1,5 @@ discard """ - file: "tasyncrecursion.nim" - output: "50005000" +output: "50005000" """ import asyncdispatch diff --git a/tests/async/tasyncsend4757.nim b/tests/async/tasyncsend4757.nim index 752bb3e75..a87c5df95 100644 --- a/tests/async/tasyncsend4757.nim +++ b/tests/async/tasyncsend4757.nim @@ -1,6 +1,5 @@ discard """ - file: "tasyncsend4754.nim" - output: "Finished" +output: "Finished" """ import asyncdispatch, asyncnet diff --git a/tests/async/tasyncssl.nim b/tests/async/tasyncssl.nim index 212260922..88a5eb32e 100644 --- a/tests/async/tasyncssl.nim +++ b/tests/async/tasyncssl.nim @@ -1,5 +1,4 @@ discard """ - file: "tasyncssl.nim" cmd: "nim $target --hints:on --define:ssl $options $file" output: "500" disabled: "windows" diff --git a/tests/async/tasynctry.nim b/tests/async/tasynctry.nim index 0fe9efdc1..b13c57951 100644 --- a/tests/async/tasynctry.nim +++ b/tests/async/tasynctry.nim @@ -1,7 +1,5 @@ discard """ - file: "tasynctry.nim" - exitcode: 0 - output: ''' +output: ''' Generic except: Test Specific except Multiple idents in except diff --git a/tests/async/tawaitsemantics.nim b/tests/async/tawaitsemantics.nim index 98fb5dfd5..67903cc5e 100644 --- a/tests/async/tawaitsemantics.nim +++ b/tests/async/tawaitsemantics.nim @@ -1,7 +1,5 @@ discard """ - file: "tawaitsemantics.nim" - exitcode: 0 - output: ''' +output: ''' Error can be caught using yield Infix `or` raises Infix `and` raises diff --git a/tests/async/tfuturestream.nim b/tests/async/tfuturestream.nim index 69ad80f47..b5772d5ac 100644 --- a/tests/async/tfuturestream.nim +++ b/tests/async/tfuturestream.nim @@ -1,7 +1,5 @@ discard """ - file: "tfuturestream.nim" - exitcode: 0 - output: ''' +output: ''' 0 1 2 @@ -70,4 +68,4 @@ waitFor testCompletion() # echo("Finished") -# waitFor omega() \ No newline at end of file +# waitFor omega() diff --git a/tests/async/tioselectors.nim b/tests/async/tioselectors.nim index 7a8986644..be6d3a167 100644 --- a/tests/async/tioselectors.nim +++ b/tests/async/tioselectors.nim @@ -1,5 +1,4 @@ discard """ - file: "tioselectors.nim" output: "All tests passed!" """ import selectors diff --git a/tests/async/tnewasyncudp.nim b/tests/async/tnewasyncudp.nim index b442c0524..7dbd5a3d0 100644 --- a/tests/async/tnewasyncudp.nim +++ b/tests/async/tnewasyncudp.nim @@ -1,5 +1,4 @@ discard """ - file: "tnewasyncudp.nim" output: "5000" """ import asyncdispatch, nativesockets, net, strutils, os diff --git a/tests/async/tpendingcheck.nim b/tests/async/tpendingcheck.nim index 825acb613..a5537d8cb 100644 --- a/tests/async/tpendingcheck.nim +++ b/tests/async/tpendingcheck.nim @@ -1,6 +1,4 @@ discard """ - file: "tpendingcheck.nim" - exitcode: 0 output: "" """ @@ -18,4 +16,3 @@ while not f.finished: f.read doAssert(not hasPendingOperations()) - diff --git a/tests/async/twinasyncrw.nim b/tests/async/twinasyncrw.nim index 94193e921..64c5d6c26 100644 --- a/tests/async/twinasyncrw.nim +++ b/tests/async/twinasyncrw.nim @@ -1,5 +1,4 @@ discard """ - file: "twinasyncrw.nim" output: "5000" """ when defined(windows): diff --git a/tests/bind/tbind.nim b/tests/bind/tbind.nim index 6fcf95433..49c37ae2e 100644 --- a/tests/bind/tbind.nim +++ b/tests/bind/tbind.nim @@ -1,7 +1,5 @@ discard """ - file: "tbind.nim" - output: -''' +output: ''' 3 1 1 diff --git a/tests/bind/tbind2.nim b/tests/bind/tbind2.nim index 799b14381..fc2eeda1a 100644 --- a/tests/bind/tbind2.nim +++ b/tests/bind/tbind2.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "ambiguous call" file: "tbind2.nim" line: 12 - errormsg: "ambiguous call" """ # Test the new ``bind`` keyword for templates @@ -12,6 +12,3 @@ template tempBind(x, y): untyped = (bind p1(x, y)) #ERROR_MSG ambiguous call echo tempBind(1'i8, 2'i8) - - - diff --git a/tests/bind/tinvalidbindtypedesc.nim b/tests/bind/tinvalidbindtypedesc.nim index ecdd12603..4bcd4e39d 100644 --- a/tests/bind/tinvalidbindtypedesc.nim +++ b/tests/bind/tinvalidbindtypedesc.nim @@ -1,6 +1,6 @@ discard """ - line: 10 errormsg: "type mismatch: got " + line: 10 """ proc foo(T: typedesc; some: T) = @@ -8,4 +8,3 @@ proc foo(T: typedesc; some: T) = foo int, 4 foo float, "bad" - diff --git a/tests/bind/tnicerrorforsymchoice.nim b/tests/bind/tnicerrorforsymchoice.nim index 8c3a99c97..f16b323de 100644 --- a/tests/bind/tnicerrorforsymchoice.nim +++ b/tests/bind/tnicerrorforsymchoice.nim @@ -1,6 +1,6 @@ discard """ - line: 18 errormsg: "type mismatch: got " + line: 18 """ #bug #442 diff --git a/tests/borrow/tinvalidborrow.nim b/tests/borrow/tinvalidborrow.nim index 9ab9e8d64..89aa4e2e8 100644 --- a/tests/borrow/tinvalidborrow.nim +++ b/tests/borrow/tinvalidborrow.nim @@ -1,6 +1,6 @@ discard """ - line: 11 errormsg: "no symbol to borrow from found" + line: 11 """ # bug #516 @@ -14,4 +14,3 @@ var d, e: TAtom echo( $(d == e) ) - diff --git a/tests/casestmt/t7699.nim b/tests/casestmt/t7699.nim index ea08388eb..1354551c1 100644 --- a/tests/casestmt/t7699.nim +++ b/tests/casestmt/t7699.nim @@ -1,6 +1,6 @@ discard """ - line: 13 errormsg: "case statement cannot work on enums with holes for computed goto" + line: 13 """ type diff --git a/tests/casestmt/tcaseexpr1.nim b/tests/casestmt/tcaseexpr1.nim index 24543f1b8..4fdac8191 100644 --- a/tests/casestmt/tcaseexpr1.nim +++ b/tests/casestmt/tcaseexpr1.nim @@ -1,13 +1,17 @@ discard """ + errormsg: "type mismatch: got but expected 'int'" + line: 33 file: "tcaseexpr1.nim" - line: 29 - errormsg: "type mismatch: got but expected 'int'" - - line: 23 errormsg: "not all cases are covered" + line: 27 + file: "tcaseexpr1.nim" """ +# NOTE: This spec is wrong. Spec doesn't support multiple error +# messages. The first one is simply overridden by the second one. +# This just has never been noticed. + type E = enum A, B, C @@ -27,4 +31,3 @@ var t1 = case x: var t2 = case x: of A: 10 of B, C: "23" - diff --git a/tests/casestmt/tcaseoverlaprange.nim b/tests/casestmt/tcaseoverlaprange.nim index 3527c9385..e9651c69f 100644 --- a/tests/casestmt/tcaseoverlaprange.nim +++ b/tests/casestmt/tcaseoverlaprange.nim @@ -1,6 +1,6 @@ discard """ - line: 13 errormsg: "duplicate case label" + line: 13 """ type diff --git a/tests/casestmt/tcaseoverlaprange2.nim b/tests/casestmt/tcaseoverlaprange2.nim index 4a9479a5f..4a1cb3ea6 100644 --- a/tests/casestmt/tcaseoverlaprange2.nim +++ b/tests/casestmt/tcaseoverlaprange2.nim @@ -1,6 +1,6 @@ discard """ - line: 13 errormsg: "duplicate case label" + line: 13 """ diff --git a/tests/casestmt/tcasestmt.nim b/tests/casestmt/tcasestmt.nim index 333700197..465080e84 100644 --- a/tests/casestmt/tcasestmt.nim +++ b/tests/casestmt/tcasestmt.nim @@ -1,6 +1,5 @@ discard """ - file: "tcasestmt.nim" - output: +output: ''' Not found! Found! @@ -226,4 +225,4 @@ block tcasestm: "invalid Y".quit(3) true else: raise newException(ValueError, "Invalid") - )) \ No newline at end of file + )) diff --git a/tests/ccgbugs/tcgbug.nim b/tests/ccgbugs/tcgbug.nim index ffaa91ff3..eda475d4f 100644 --- a/tests/ccgbugs/tcgbug.nim +++ b/tests/ccgbugs/tcgbug.nim @@ -1,6 +1,6 @@ discard """ - file: "tcgbug.nim" - output: '''success +output: ''' +success M1 M2 ''' """ @@ -74,5 +74,5 @@ proc newMyObjectRef(kind: MyKind, val: string): MyObjectRef = of M2: result.b = parseFloat(val) of M3: result.c = val - -echo newMyObject(M1, "2").kind, " ", newMyObjectRef(M2, "3").kind \ No newline at end of file + +echo newMyObject(M1, "2").kind, " ", newMyObjectRef(M2, "3").kind diff --git a/tests/clearmsg/tconsttypemismatch.nim b/tests/clearmsg/tconsttypemismatch.nim index edf480348..727bfbffb 100644 --- a/tests/clearmsg/tconsttypemismatch.nim +++ b/tests/clearmsg/tconsttypemismatch.nim @@ -1,8 +1,7 @@ discard """ + errormsg: "type mismatch" file: "tconsttypemismatch.nim" line: 7 - errormsg: "type mismatch" """ # bug #2252 const foo: int = 1000 / 30 - diff --git a/tests/clearmsg/tmacroerrorproc.nim b/tests/clearmsg/tmacroerrorproc.nim index cd9b15e25..86726af72 100644 --- a/tests/clearmsg/tmacroerrorproc.nim +++ b/tests/clearmsg/tmacroerrorproc.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "Expected a node of kind nnkCharLit, got nnkCommand" file: "tmacroerrorproc.nim" line: 13 - errormsg: "Expected a node of kind nnkCharLit, got nnkCommand" """ # issue #4915 import macros diff --git a/tests/closure/tinvalidclosure.nim b/tests/closure/tinvalidclosure.nim index 4e5f61f06..b2d8bd28d 100644 --- a/tests/closure/tinvalidclosure.nim +++ b/tests/closure/tinvalidclosure.nim @@ -1,6 +1,6 @@ discard """ - line: 12 errormsg: "type mismatch: got " + line: 12 """ proc ugh[T](x: T) {.nimcall.} = diff --git a/tests/closure/tinvalidclosure2.nim b/tests/closure/tinvalidclosure2.nim index 845559309..2d58f0215 100644 --- a/tests/closure/tinvalidclosure2.nim +++ b/tests/closure/tinvalidclosure2.nim @@ -1,6 +1,6 @@ discard """ - line: 10 errormsg: "illegal capture 'A'" + line: 10 """ proc outer() = diff --git a/tests/closure/tinvalidclosure3.nim b/tests/closure/tinvalidclosure3.nim index 31c4976f8..0cbdaf39e 100644 --- a/tests/closure/tinvalidclosure3.nim +++ b/tests/closure/tinvalidclosure3.nim @@ -1,6 +1,6 @@ discard """ - line: 9 errormsg: "illegal capture 'x'" + line: 9 """ proc outer(arg: string) = @@ -9,4 +9,4 @@ proc outer(arg: string) = echo "inner", x inner() -outer("abc") \ No newline at end of file +outer("abc") diff --git a/tests/closure/tnested.nim b/tests/closure/tnested.nim index f8d69011a..dbbe9ba58 100644 --- a/tests/closure/tnested.nim +++ b/tests/closure/tnested.nim @@ -1,6 +1,5 @@ discard """ - file: "tnested.nim" - output: ''' +output: ''' foo88 23 24foo 88 foo88 diff --git a/tests/cnstseq/tcnstseq.nim b/tests/cnstseq/tcnstseq.nim index e044b9f3f..5679a6e37 100644 --- a/tests/cnstseq/tcnstseq.nim +++ b/tests/cnstseq/tcnstseq.nim @@ -1,6 +1,5 @@ discard """ - file: "tcnstseq.nim" - output: ''' +output: ''' AngelikaAnneAnnaAnkaAnja AngelikaAnneAnnaAnkaAnja AngelikaAnneAnnaAnkaAnja diff --git a/tests/collections/tcollections.nim b/tests/collections/tcollections.nim index ff6673bba..2f8cfece7 100644 --- a/tests/collections/tcollections.nim +++ b/tests/collections/tcollections.nim @@ -1,7 +1,5 @@ discard """ - file: "tcollections.nim" - output: ''' -''' + output: "" """ import deques, sequtils diff --git a/tests/collections/ttables.nim b/tests/collections/ttables.nim index 4d11f56f2..f1355e747 100644 --- a/tests/collections/ttables.nim +++ b/tests/collections/ttables.nim @@ -1,6 +1,5 @@ discard """ - file: "ttables.nim" - output: ''' +output: ''' done And we get here 1 @@ -142,7 +141,7 @@ block tindexby: tbl2.add("bar", elem1) tbl2.add("baz", elem2) doAssert indexBy(@[elem1,elem2], proc(x: TElem): string = x.bar) == tbl2, "element table" - + block tableconstr: # Test if the new table constructor syntax works: diff --git a/tests/concepts/tconcepts.nim b/tests/concepts/tconcepts.nim index dec1dafe0..d0bc76c20 100644 --- a/tests/concepts/tconcepts.nim +++ b/tests/concepts/tconcepts.nim @@ -1,6 +1,5 @@ discard """ - file: "tconcepts.nim" - output: ''' +output: ''' 10 20 int @@ -378,53 +377,53 @@ block tvectorspace: block tstack: template reject(e) = static: assert(not compiles(e)) - + type ArrayStack = object data: seq[int] - + proc push(s: var ArrayStack, item: int) = s.data.add item - + proc pop(s: var ArrayStack): int = return s.data.pop() - + type Stack[T] = concept var s s.push(T) s.pop() is T - + type ValueType = T const ValueTypeName = T.name.toUpperAscii - + proc genericAlgorithm[T](s: var Stack[T], y: T) = static: echo "INFERRED ", T.name echo "VALUE TYPE ", s.ValueType.name echo "VALUE TYPE NAME ", s.ValueTypeName - + s.push(y) echo s.pop - + proc implicitGeneric(s: var Stack): auto = static: echo "IMPLICIT INFERRED ", s.T.name, " ", Stack.T.name echo "IMPLICIT VALUE TYPE ", s.ValueType.name, " ", Stack.ValueType.name echo "IMPLICIT VALUE TYPE NAME ", s.ValueTypeName, " ", Stack.ValueTypeName - + return s.pop() - + var s = ArrayStack(data: @[]) - + s.push 10 s.genericAlgorithm 20 echo s.implicitGeneric - + reject s.genericAlgorithm "x" reject s.genericAlgorithm 1.0 reject "str".implicitGeneric reject implicitGeneric(10) - + import libs/[trie_database, trie] diff --git a/tests/concepts/texplain.nim b/tests/concepts/texplain.nim index 5c8e02440..ac0c972f5 100644 --- a/tests/concepts/texplain.nim +++ b/tests/concepts/texplain.nim @@ -63,8 +63,8 @@ texplain.nim(92, 5) NestedConcept: concept predicate failed expression: f(y) ''' - line: 138 errormsg: "type mismatch: got " + line: 138 """ @@ -136,4 +136,3 @@ static: # finally, provide multiple nested explanations for failed matching # of regular concepts, even when the explain pragma is not used f(y) - diff --git a/tests/constr/tconstr1.nim b/tests/constr/tconstr1.nim index b9cf5d00b..a169bf453 100644 --- a/tests/constr/tconstr1.nim +++ b/tests/constr/tconstr1.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "type mismatch" file: "tconstr1.nim" line: 25 - errormsg: "type mismatch" """ # Test array, record constructors @@ -26,5 +26,3 @@ const otherThings = [ # the same (s: "hi", x: 69, y: 45, z: 0.0, chars: {'a', 'b', 'c'}), (s: "hi", x: 69, y: 45, z: 1.0, chars: {'a'})] - - diff --git a/tests/constr/tconstr2.nim b/tests/constr/tconstr2.nim index b16be6c50..b911de548 100644 --- a/tests/constr/tconstr2.nim +++ b/tests/constr/tconstr2.nim @@ -1,5 +1,4 @@ discard """ - file: "tconstr2.nim" output: "69" """ # Test array, record constructors @@ -21,6 +20,3 @@ const write(stdout, things[0].x) #OUT 69 - - - diff --git a/tests/constraints/tconstraints.nim b/tests/constraints/tconstraints.nim index 3c9fdc354..3ca01cfd5 100644 --- a/tests/constraints/tconstraints.nim +++ b/tests/constraints/tconstraints.nim @@ -1,6 +1,6 @@ discard """ - line: 16 errormsg: "type mismatch: got " + line: 16 """ proc myGenericProc[T: object|tuple|ptr|ref|distinct](x: T): string = @@ -14,5 +14,3 @@ var assert myGenericProc(x) == "(x: 0, y: 0)" assert myGenericProc(232) == "232" - - diff --git a/tests/constructors/t5965_1.nim b/tests/constructors/t5965_1.nim index 9f947f859..abf07b21c 100644 --- a/tests/constructors/t5965_1.nim +++ b/tests/constructors/t5965_1.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "incorrect object construction syntax" file: "t5965_1.nim" line: 10 - errormsg: "incorrect object construction syntax" """ type Foo = object diff --git a/tests/constructors/t5965_2.nim b/tests/constructors/t5965_2.nim index a3f7174c9..e04f1b715 100644 --- a/tests/constructors/t5965_2.nim +++ b/tests/constructors/t5965_2.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "incorrect object construction syntax" file: "t5965_2.nim" line: 10 - errormsg: "incorrect object construction syntax" """ type Foo = object diff --git a/tests/controlflow/tblock1.nim b/tests/controlflow/tblock1.nim index e3a780dfe..70c844513 100644 --- a/tests/controlflow/tblock1.nim +++ b/tests/controlflow/tblock1.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "undeclared identifier: \'ha\'" file: "tblock1.nim" line: 14 - errormsg: "undeclared identifier: \'ha\'" """ # check for forward label and # for failure when label is not declared @@ -14,5 +14,3 @@ proc main = break ha #ERROR main() - - diff --git a/tests/controlflow/tstatret.nim b/tests/controlflow/tstatret.nim index 8f43c5d8f..e0f816c7d 100644 --- a/tests/controlflow/tstatret.nim +++ b/tests/controlflow/tstatret.nim @@ -1,12 +1,9 @@ discard """ + errormsg: "unreachable statement after 'return' statement or '{.noReturn.}' proc" file: "tstatret.nim" line: 9 - errormsg: "unreachable statement after 'return' statement or '{.noReturn.}' proc" """ # no statement after return proc main() = return echo("huch?") #ERROR_MSG statement not allowed after - - - diff --git a/tests/converter/tconverter_unique_ptr.nim b/tests/converter/tconverter_unique_ptr.nim index 25b001d52..23c1a3d96 100644 --- a/tests/converter/tconverter_unique_ptr.nim +++ b/tests/converter/tconverter_unique_ptr.nim @@ -1,6 +1,5 @@ discard """ - file: "tconverter_unique_ptr.nim" targets: "c cpp" output: "" """ @@ -34,7 +33,7 @@ proc `=`*(m: var MySeq, m2: MySeq) = `=destroy`(m) m.len = m2.len - let bytes = m.len.int * sizeof(float) + let bytes = m.len.int * sizeof(float) if bytes > 0: m.data = cast[ptr UncheckedArray[float]](allocShared(bytes)) copyMem(m.data, m2.data, bytes) @@ -59,7 +58,7 @@ proc `[]`*(m: var MySeq; i: MyLen): var float {.inline.} = proc `[]=`*(m: var MySeq; i: MyLen, val: float) {.inline.} = m.data[i.int] = val -proc setTo(s: var MySeq, val: float) = +proc setTo(s: var MySeq, val: float) = for i in 0.." file: "tconverter_with_constraint.nim" line: 20 - errormsg: "type mismatch: got " """ type @@ -10,11 +10,11 @@ type converter to_mytype(m: int{lit}): MyType = m.MyType - + proc myproc(m: MyType) = echo m.int, ".MyType" -myproc(1) # call by literal is ok +myproc(1) # call by literal is ok var x: int = 12 -myproc(x) # should fail \ No newline at end of file +myproc(x) # should fail diff --git a/tests/deprecated/tnoannot.nim b/tests/deprecated/tnoannot.nim index 9cc5c7e06..ac168952e 100644 --- a/tests/deprecated/tnoannot.nim +++ b/tests/deprecated/tnoannot.nim @@ -1,6 +1,6 @@ discard """ - line: 7 errormsg: "annotation to deprecated not supported here" + line: 7 """ var foo* {.deprecated.} = 42 diff --git a/tests/discard/tillegaldiscard.nim b/tests/discard/tillegaldiscard.nim index 5e1a3f03e..757f4e727 100644 --- a/tests/discard/tillegaldiscard.nim +++ b/tests/discard/tillegaldiscard.nim @@ -1,6 +1,6 @@ discard """ - line: 9 errormsg: "illegal discard" + line: 9 """ proc pop[T](arg: T): T = diff --git a/tests/discard/tneedsdiscard.nim b/tests/discard/tneedsdiscard.nim index 8d59e7fec..7d2997b3f 100644 --- a/tests/discard/tneedsdiscard.nim +++ b/tests/discard/tneedsdiscard.nim @@ -1,6 +1,6 @@ discard """ - line: 10 errormsg: '''expression 'open(f, "arg.txt", fmRead, -1)' is of type 'bool' and has to be discarded; start of expression here: tneedsdiscard.nim(7, 2)''' + line: 10 """ proc p = diff --git a/tests/discard/tneedsdiscard_in_for.nim b/tests/discard/tneedsdiscard_in_for.nim index 5658f4ba2..499b06009 100644 --- a/tests/discard/tneedsdiscard_in_for.nim +++ b/tests/discard/tneedsdiscard_in_for.nim @@ -1,6 +1,6 @@ discard """ - line: 22 errormsg: '''expression 'premultiply(app.gradient[i])' is of type 'Rgba8' and has to be discarded''' + line: 22 """ # bug #9076 diff --git a/tests/distinct/tnil.nim b/tests/distinct/tnil.nim index 16de38f60..5bdb97f37 100644 --- a/tests/distinct/tnil.nim +++ b/tests/distinct/tnil.nim @@ -1,6 +1,6 @@ discard """ - file: "tnil.nim" - output: '''1 +output: ''' +1 0 0 ''' diff --git a/tests/effects/teffects1.nim b/tests/effects/teffects1.nim index ef76c9130..767845cb4 100644 --- a/tests/effects/teffects1.nim +++ b/tests/effects/teffects1.nim @@ -1,6 +1,6 @@ discard """ - file: "system.nim" errormsg: "can raise an unlisted exception: ref IOError" + file: "system.nim" """ type @@ -17,4 +17,3 @@ proc lier(): int {.raises: [IO2Error].} = proc forw: int = raise newException(IOError, "arg") - diff --git a/tests/effects/teffects2.nim b/tests/effects/teffects2.nim index 0fa789869..e4b50aba5 100644 --- a/tests/effects/teffects2.nim +++ b/tests/effects/teffects2.nim @@ -1,6 +1,6 @@ discard """ - line: 19 errormsg: "can raise an unlisted exception: ref IOError" + line: 19 """ type @@ -17,4 +17,3 @@ proc lier(): int {.raises: [IOError].} = proc forw: int = raise newException(IOError, "arg") - diff --git a/tests/effects/teffects3.nim b/tests/effects/teffects3.nim index cbd11f722..ee5470c47 100644 --- a/tests/effects/teffects3.nim +++ b/tests/effects/teffects3.nim @@ -1,6 +1,6 @@ discard """ - line: 18 errormsg: "type mismatch" + line: 18 """ type @@ -16,4 +16,3 @@ proc raiser(): int {.tags: [TObj, WriteIoEffect].} = var o: TObjB o.fn = raiser - diff --git a/tests/effects/teffects4.nim b/tests/effects/teffects4.nim index 0025c10c5..88cc0efa9 100644 --- a/tests/effects/teffects4.nim +++ b/tests/effects/teffects4.nim @@ -1,6 +1,6 @@ discard """ - line: 23 errormsg: "type mismatch" + line: 23 """ type @@ -21,4 +21,3 @@ proc raiser(): int = var o: TObjB o.fn = raiser - diff --git a/tests/effects/tgcsafe.nim b/tests/effects/tgcsafe.nim index d146794b6..ff207df59 100644 --- a/tests/effects/tgcsafe.nim +++ b/tests/effects/tgcsafe.nim @@ -1,6 +1,6 @@ discard """ - line: 17 errormsg: "'mainUnsafe' is not GC-safe" + line: 17 cmd: "nim $target --hints:on --threads:on $options $file" """ diff --git a/tests/effects/tsidee1.nim b/tests/effects/tsidee1.nim index e486d32e7..ca6816561 100644 --- a/tests/effects/tsidee1.nim +++ b/tests/effects/tsidee1.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "\'SideEffectLyer\' can have side effects" file: "tsidee1.nim" line: 12 - errormsg: "\'SideEffectLyer\' can have side effects" """ var @@ -13,6 +13,3 @@ proc SideEffectLyer(x, y: int): int {.noSideEffect.} = #ERROR_MSG 'SideEffectLye return x + y + dontcare(x) echo SideEffectLyer(1, 3) - - - diff --git a/tests/effects/tsidee2.nim b/tests/effects/tsidee2.nim index 5ed541300..b2e5f3379 100644 --- a/tests/effects/tsidee2.nim +++ b/tests/effects/tsidee2.nim @@ -1,5 +1,4 @@ discard """ - file: "tsidee2.nim" output: "5" """ @@ -12,6 +11,3 @@ proc SideEffectLyer(x, y: int): int {.noSideEffect.} = return x + y + dontcare(x) echo SideEffectLyer(1, 3) #OUT 5 - - - diff --git a/tests/effects/tsidee3.nim b/tests/effects/tsidee3.nim index e15fbc3d1..c3801ba28 100644 --- a/tests/effects/tsidee3.nim +++ b/tests/effects/tsidee3.nim @@ -1,5 +1,4 @@ discard """ - file: "tsidee3.nim" output: "5" """ @@ -12,6 +11,3 @@ proc noSideEffect(x, y: int, p: proc (a: int): int {.noSideEffect.}): int {.noSi return x + y + dontcare(x) echo noSideEffect(1, 3, dontcare) #OUT 5 - - - diff --git a/tests/effects/tsidee4.nim b/tests/effects/tsidee4.nim index ecc79580c..d6c192cbf 100644 --- a/tests/effects/tsidee4.nim +++ b/tests/effects/tsidee4.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "'noSideEffect' can have side effects" file: "tsidee4.nim" line: 12 - errormsg: "'noSideEffect' can have side effects" """ var @@ -13,5 +13,3 @@ proc noSideEffect(x, y: int, p: proc (a: int): int {.noSideEffect.}): int {.noSi return x + y + dontcare(x) echo noSideEffect(1, 3, dontcare) #ERROR_MSG type mismatch - - diff --git a/tests/enum/tenumitems.nim b/tests/enum/tenumitems.nim index 6d13dd162..76f368f8a 100644 --- a/tests/enum/tenumitems.nim +++ b/tests/enum/tenumitems.nim @@ -1,9 +1,7 @@ discard """ - line: 7 errormsg: "attempting to call routine: 'items'" + line: 7 """ type a = enum b,c,d a.items() - - diff --git a/tests/errmsgs/t8339.nim b/tests/errmsgs/t8339.nim index f0a97658a..720e080c0 100644 --- a/tests/errmsgs/t8339.nim +++ b/tests/errmsgs/t8339.nim @@ -1,6 +1,6 @@ discard """ - line: 8 errormsg: "type mismatch: got but expected 'seq[float]'" + line: 8 """ import sequtils diff --git a/tests/exception/tcontinuexc.nim b/tests/exception/tcontinuexc.nim index 2a05da9c0..b7560a605 100644 --- a/tests/exception/tcontinuexc.nim +++ b/tests/exception/tcontinuexc.nim @@ -1,5 +1,4 @@ discard """ - file: "tcontinuexc.nim" outputsub: "ECcaught" exitcode: "1" """ @@ -25,6 +24,3 @@ finally: echo "caught" #OUT ECcaught - - - diff --git a/tests/exception/texceptionbreak.nim b/tests/exception/texceptionbreak.nim index 00dd8ed9f..6548192c6 100644 --- a/tests/exception/texceptionbreak.nim +++ b/tests/exception/texceptionbreak.nim @@ -1,5 +1,4 @@ discard """ - file: "tnestedbreak.nim" output: "1\n2\n3\n4" """ diff --git a/tests/exception/texcsub.nim b/tests/exception/texcsub.nim index 02125d2c0..463e95613 100644 --- a/tests/exception/texcsub.nim +++ b/tests/exception/texcsub.nim @@ -1,5 +1,4 @@ discard """ - file: "texcsub.nim" output: "caught!" """ # Test inheritance for exception matching: @@ -12,6 +11,3 @@ except: echo "wtf!?" #OUT caught! - - - diff --git a/tests/exception/tfinally.nim b/tests/exception/tfinally.nim index 7a218b444..c5b1dd841 100644 --- a/tests/exception/tfinally.nim +++ b/tests/exception/tfinally.nim @@ -1,6 +1,6 @@ discard """ - file: "tfinally.nim" - output: '''came + output: ''' +came here 3 msg1 @@ -59,4 +59,4 @@ try: except: echo "except2" finally: - echo "finally2" \ No newline at end of file + echo "finally2" diff --git a/tests/exception/tfinally2.nim b/tests/exception/tfinally2.nim index f1acf2774..dae1a468a 100644 --- a/tests/exception/tfinally2.nim +++ b/tests/exception/tfinally2.nim @@ -1,9 +1,10 @@ discard """ - file: "tfinally2.nim" - output: '''A +output: ''' +A B C -D''' +D +''' """ # Test break in try statement: @@ -24,7 +25,4 @@ proc main: int = finally: echo("D") -discard main() #OUT ABCD - - - +discard main() diff --git a/tests/exception/tfinally3.nim b/tests/exception/tfinally3.nim index 6098672a2..9053d397d 100644 --- a/tests/exception/tfinally3.nim +++ b/tests/exception/tfinally3.nim @@ -1,7 +1,8 @@ discard """ - file: "tfinally3.nim" - outputsub: '''false -Within finally->try''' + outputsub: ''' +false +Within finally->try +''' exitCode: 1 """ # Test break in try statement: diff --git a/tests/exception/tfinally4.nim b/tests/exception/tfinally4.nim index 3aa707ff6..feaf1bc96 100644 --- a/tests/exception/tfinally4.nim +++ b/tests/exception/tfinally4.nim @@ -1,5 +1,4 @@ discard """ - file: "tfinally4.nim" output: "B1\nA1\n1\nB1\nB2\ncatch\nA1\n1\nB1\nA1\nA2\n2\nB1\nB2\ncatch\nA1\nA2\n0\nB1\nA1\n1\nB1\nB2\nA1\n1\nB1\nA1\nA2\n2\nB1\nB2\nA1\nA2\n3" """ diff --git a/tests/exception/tnestedreturn.nim b/tests/exception/tnestedreturn.nim index bf26f4903..acb83d2c8 100644 --- a/tests/exception/tnestedreturn.nim +++ b/tests/exception/tnestedreturn.nim @@ -1,6 +1,5 @@ discard """ targets: "c cpp" - file: "tnestedreturn.nim" output: "A\nB\nC\n" """ diff --git a/tests/exception/tnestedreturn2.nim b/tests/exception/tnestedreturn2.nim index 79523a883..167d09b96 100644 --- a/tests/exception/tnestedreturn2.nim +++ b/tests/exception/tnestedreturn2.nim @@ -1,5 +1,4 @@ discard """ - file: "tnestedreturn2.nim" outputsub: "Error: unhandled exception: Problem [OSError]" exitcode: "1" """ diff --git a/tests/exception/treraise.nim b/tests/exception/treraise.nim index b2a11d34f..17a38aa53 100644 --- a/tests/exception/treraise.nim +++ b/tests/exception/treraise.nim @@ -1,5 +1,4 @@ discard """ - file: "treraise.nim" outputsub: "Error: unhandled exception: bla [ESomeOtherErr]" exitcode: "1" """ @@ -19,6 +18,3 @@ except ESomething: echo("Error happened") except: raise - - - diff --git a/tests/exception/tunhandledexc.nim b/tests/exception/tunhandledexc.nim index f0fa2bf27..6ca311d38 100644 --- a/tests/exception/tunhandledexc.nim +++ b/tests/exception/tunhandledexc.nim @@ -1,7 +1,6 @@ discard """ - file: "tunhandledexc.nim" cmd: "nim $target -d:release $options $file" - outputsub: '''tunhandledexc.nim(16) genErrors + outputsub: '''tunhandledexc.nim(15) genErrors Error: unhandled exception: bla [ESomeOtherErr]''' exitcode: "1" """ diff --git a/tests/exception/twrongexc.nim b/tests/exception/twrongexc.nim index b224d4c83..9c656f3d9 100644 --- a/tests/exception/twrongexc.nim +++ b/tests/exception/twrongexc.nim @@ -1,5 +1,4 @@ discard """ - file: "twrongexc.nim" outputsub: "Error: unhandled exception: [ValueError]" exitcode: "1" """ @@ -7,7 +6,3 @@ try: raise newException(ValueError, "") except OverflowError: echo("Error caught") - - - - diff --git a/tests/exprs/texprstmt.nim b/tests/exprs/texprstmt.nim index 6c9759cf5..742670cc1 100644 --- a/tests/exprs/texprstmt.nim +++ b/tests/exprs/texprstmt.nim @@ -1,6 +1,6 @@ discard """ - line: 10 errormsg: "expression 'result[1 .. BackwardsIndex(1)]' is of type 'string' and has to be discarded" + line: 10 """ # bug #578 diff --git a/tests/exprs/tstmtexp.nim b/tests/exprs/tstmtexp.nim index 0fb835bc6..75d8dd081 100644 --- a/tests/exprs/tstmtexp.nim +++ b/tests/exprs/tstmtexp.nim @@ -1,9 +1,8 @@ discard """ + errormsg: "expression '5' is of type 'int literal(5)' and has to be discarded" file: "tstmtexp.nim" line: 8 - errormsg: "expression '5' is of type 'int literal(5)' and has to be discarded" """ # Test 3 1+4 - diff --git a/tests/flags/tgenscript.nim b/tests/flags/tgenscript.nim index 989ca8bcb..bf83ab972 100644 --- a/tests/flags/tgenscript.nim +++ b/tests/flags/tgenscript.nim @@ -1,5 +1,4 @@ discard """ - file: "tgenscript.nim" target: "c" action: compile """ diff --git a/tests/float/tfloat1.nim b/tests/float/tfloat1.nim index ed99260ea..54d49a7c1 100644 --- a/tests/float/tfloat1.nim +++ b/tests/float/tfloat1.nim @@ -1,5 +1,4 @@ discard """ - file: "tfloat1.nim" outputsub: "Error: unhandled exception: FPU operation caused an overflow [FloatOverflowError]" exitcode: "1" """ @@ -11,5 +10,3 @@ var x = 0.8 var y = 0.0 echo x / y #OUT Error: unhandled exception: FPU operation caused an overflow - - diff --git a/tests/float/tfloat2.nim b/tests/float/tfloat2.nim index b84120fba..130c71087 100644 --- a/tests/float/tfloat2.nim +++ b/tests/float/tfloat2.nim @@ -1,5 +1,4 @@ discard """ - file: "tfloat2.nim" outputsub: "Error: unhandled exception: FPU operation caused a NaN result [FloatInvalidOpError]" exitcode: "1" """ @@ -11,5 +10,3 @@ var x = 0.0 var y = 0.0 echo x / y #OUT Error: unhandled exception: FPU operation caused a NaN result - - diff --git a/tests/float/tfloat3.nim b/tests/float/tfloat3.nim index a14c6c396..01f3cb9df 100644 --- a/tests/float/tfloat3.nim +++ b/tests/float/tfloat3.nim @@ -1,5 +1,4 @@ discard """ - file: "tfloat3.nim" output: "Nim 3.4368930843, 0.3299290698 C double: 3.4368930843, 0.3299290698" """ @@ -19,6 +18,3 @@ proc printFloats {.importc, nodecl.} var x: float = 1.234567890123456789 c_printf("Nim %.10f, %.10f ", exp(x), cos(x)) printFloats() - - - diff --git a/tests/float/tfloat4.nim b/tests/float/tfloat4.nim index 68df56be8..56280111c 100644 --- a/tests/float/tfloat4.nim +++ b/tests/float/tfloat4.nim @@ -1,8 +1,7 @@ discard """ - file: "tfloat4.nim" output: "passed all tests." - exitcode: 0 """ + import math, strutils proc c_sprintf(buf, fmt: cstring) {.importc:"sprintf", header: "", varargs.} diff --git a/tests/float/tfloat5.nim b/tests/float/tfloat5.nim index aa7dc6c53..0708838fc 100644 --- a/tests/float/tfloat5.nim +++ b/tests/float/tfloat5.nim @@ -1,9 +1,10 @@ discard """ - file: "tfloat5.nim" - output: '''0 : 0.0 +output: ''' 0 : 0.0 0 : 0.0 -0 : 0.0''' +0 : 0.0 +0 : 0.0 +''' """ import parseutils diff --git a/tests/float/tfloat6.nim b/tests/float/tfloat6.nim index 8e043a658..c4cd6e932 100644 --- a/tests/float/tfloat6.nim +++ b/tests/float/tfloat6.nim @@ -1,12 +1,13 @@ discard """ - file: "tfloat6.nim" - output: '''1e-06 : 1e-06 + output: ''' +1e-06 : 1e-06 1e-06 : 1e-06 0.001 : 0.001 1e-06 : 1e-06 1e-06 : 1e-06 10.000001 : 10.000001 -100.000001 : 100.000001''' +100.000001 : 100.000001 +''' disabled: "windows" """ diff --git a/tests/float/tfloat7.nim b/tests/float/tfloat7.nim index 5fd0d43d9..a6d7af10b 100644 --- a/tests/float/tfloat7.nim +++ b/tests/float/tfloat7.nim @@ -1,12 +1,13 @@ discard """ - file: "tfloat6.nim" - output: '''passed. +output: ''' passed. passed. passed. passed. passed. -passed.''' +passed. +passed. +''' """ import strutils diff --git a/tests/float/tfloatnan.nim b/tests/float/tfloatnan.nim index aa288d342..29937a862 100644 --- a/tests/float/tfloatnan.nim +++ b/tests/float/tfloatnan.nim @@ -1,6 +1,6 @@ discard """ - file: "tfloatnan.nim" - output: '''Nim: nan +output: ''' +Nim: nan Nim: nan (float) Nim: nan (double) ''' diff --git a/tests/float/tissue5821.nim b/tests/float/tissue5821.nim index e8aa4a1d9..c4f561f09 100644 --- a/tests/float/tissue5821.nim +++ b/tests/float/tissue5821.nim @@ -1,7 +1,7 @@ discard """ - file: "tissue5821.nim" - output: '''''' +output: "ok" """ + proc main(): void = let a: float32 = 47.11'f32 doAssert a == 47.11'f32 @@ -10,4 +10,6 @@ proc main(): void = doAssert b != 10.123402823e+38'f64 doAssert b == 10.234402823e+38'f64 -main() \ No newline at end of file + echo "ok" + +main() diff --git a/tests/generics/t6137.nim b/tests/generics/t6137.nim index 639675f35..abf02a756 100644 --- a/tests/generics/t6137.nim +++ b/tests/generics/t6137.nim @@ -1,7 +1,6 @@ discard """ - action: "reject" - line: 29 errormsg: "\'vectFunc\' doesn't have a concrete type, due to unspecified generic parameters." + line: 28 """ type diff --git a/tests/generics/t7141.nim b/tests/generics/t7141.nim index 8a128d828..b1e9cbf43 100644 --- a/tests/generics/t7141.nim +++ b/tests/generics/t7141.nim @@ -1,7 +1,6 @@ discard """ - action: "reject" - line: 7 errormsg: "cannot instantiate: \'T\'" + line: 6 """ proc foo[T](x: T) = diff --git a/tests/generics/t8270.nim b/tests/generics/t8270.nim index 707e981fa..1e731d1d4 100644 --- a/tests/generics/t8270.nim +++ b/tests/generics/t8270.nim @@ -1,6 +1,6 @@ discard """ - line: 6 errormsg: "cannot instantiate: \'T\'" + line: 6 """ proc m[T](x: T): int = discard diff --git a/tests/generics/tbintre2.nim b/tests/generics/tbintre2.nim index eb46b5157..4f63cc5f5 100644 --- a/tests/generics/tbintre2.nim +++ b/tests/generics/tbintre2.nim @@ -1,5 +1,4 @@ discard """ - file: "tbintre2.nim" output: "helloworld99110223" """ # Same test, but check module boundaries @@ -26,6 +25,3 @@ for y in items(r2): stdout.write(y) #OUT helloworld99110223 - - - diff --git a/tests/generics/tbintree.nim b/tests/generics/tbintree.nim index 13163f764..b4507e298 100644 --- a/tests/generics/tbintree.nim +++ b/tests/generics/tbintree.nim @@ -1,5 +1,4 @@ discard """ - file: "tbintree.nim" output: "helloworld99110223" """ type @@ -103,5 +102,3 @@ when isMainModule: stdout.write(y) #OUT helloworld99110223 - - diff --git a/tests/generics/texplicitgeneric1.nim b/tests/generics/texplicitgeneric1.nim index ac0197c1a..f093e54d4 100644 --- a/tests/generics/texplicitgeneric1.nim +++ b/tests/generics/texplicitgeneric1.nim @@ -1,5 +1,4 @@ discard """ - file: "texplicitgeneric1.nim" output: "Key: 12 value: 12Key: 13 value: 13 Key: A value: 12 Key: B value: 13" """ # test explicit type instantiation @@ -33,6 +32,3 @@ c.add('A', "12") c.add('B', "13") for k, v in items(c): stdout.write(" Key: ", $k, " value: ", v) - - - diff --git a/tests/global/t5958.nim b/tests/global/t5958.nim index 5abcad4a9..9b7642363 100644 --- a/tests/global/t5958.nim +++ b/tests/global/t5958.nim @@ -1,6 +1,6 @@ discard """ - line: 9 errormsg: "undeclared identifier: 'a'" + line: 9 """ static: diff --git a/tests/iter/tcountup.nim b/tests/iter/tcountup.nim index 1559041aa..83d800c82 100644 --- a/tests/iter/tcountup.nim +++ b/tests/iter/tcountup.nim @@ -1,5 +1,4 @@ discard """ - file: "tcountup.nim" output: "0123456789" """ @@ -9,6 +8,3 @@ for i in 0 .. < 10'i64: stdout.write(i) #OUT 0123456789 - - - diff --git a/tests/iter/titer11.nim b/tests/iter/titer11.nim index 6c410e945..c4c7d4a16 100644 --- a/tests/iter/titer11.nim +++ b/tests/iter/titer11.nim @@ -1,6 +1,6 @@ discard """ - file: "titer11.nim" - output: '''[ +output: ''' +[ 1 2 3 diff --git a/tests/iter/titer3.nim b/tests/iter/titer3.nim index cc603fd85..9dcfd7be5 100644 --- a/tests/iter/titer3.nim +++ b/tests/iter/titer3.nim @@ -1,5 +1,4 @@ discard """ - file: "titer3.nim" output: '''1231 4 6 diff --git a/tests/iter/titer4.nim b/tests/iter/titer4.nim index 9b52f8055..912883a63 100644 --- a/tests/iter/titer4.nim +++ b/tests/iter/titer4.nim @@ -1,10 +1,8 @@ discard """ + errormsg: "iterator within for loop context expected" file: "titer4.nim" line: 7 - errormsg: "iterator within for loop context expected" """ # implicit items/pairs, but not if we have 3 for loop vars: for x, y, z in {'a'..'z'}: #ERROR_MSG iterator within for loop context expected nil - - diff --git a/tests/iter/titer5.nim b/tests/iter/titer5.nim index bbd50fcb1..3c508dca7 100644 --- a/tests/iter/titer5.nim +++ b/tests/iter/titer5.nim @@ -1,5 +1,4 @@ discard """ - file: "titer5.nim" output: "abcxyz" """ # Test method call syntax for iterators: @@ -11,6 +10,3 @@ for x in lines.split(): stdout.write(x) #OUT abcxyz - - - diff --git a/tests/iter/titer6.nim b/tests/iter/titer6.nim index b7c8fee80..b8c2f7c66 100644 --- a/tests/iter/titer6.nim +++ b/tests/iter/titer6.nim @@ -1,5 +1,4 @@ discard """ - file: "titer6.nim" output: "000" """ # Test iterator with more than 1 yield statement @@ -32,6 +31,3 @@ proc wordWrap2(s: string, maxLineWidth = 80, result = "" for word, isSep in tokenize2(s, seps): var w = 0 - - - diff --git a/tests/iter/titervaropenarray.nim b/tests/iter/titervaropenarray.nim index 9eea085e3..b9aa2cbca 100644 --- a/tests/iter/titervaropenarray.nim +++ b/tests/iter/titervaropenarray.nim @@ -1,5 +1,4 @@ discard """ - file: "titer2.nim" output: "123" """ # Try to break the transformation pass: diff --git a/tests/iter/treciter.nim b/tests/iter/treciter.nim index dacdbdfd7..7b61326f4 100644 --- a/tests/iter/treciter.nim +++ b/tests/iter/treciter.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "recursive dependency: \'myrec\'" file: "treciter.nim" line: 9 - errormsg: "recursive dependency: \'myrec\'" """ # Test that an error message occurs for a recursive iterator @@ -10,5 +10,3 @@ iterator myrec(n: int): int = yield x for x in myrec(10): echo x - - diff --git a/tests/iter/twrongiter.nim b/tests/iter/twrongiter.nim index 33394219b..577b8c4f1 100644 --- a/tests/iter/twrongiter.nim +++ b/tests/iter/twrongiter.nim @@ -1,6 +1,6 @@ discard """ -line: 12 errormsg: "type mismatch" +line: 12 """ proc first(it: iterator(): int): seq[int] = diff --git a/tests/let/tlet.nim b/tests/let/tlet.nim index 6703ba254..25d7b9bf7 100644 --- a/tests/let/tlet.nim +++ b/tests/let/tlet.nim @@ -1,6 +1,6 @@ discard """ - line: "10" errormsg: "'name' cannot be assigned to" + line: "10" """ echo("What's your name? ") @@ -8,4 +8,3 @@ let name = readLine(stdin) while name == "": echo("Please tell me your name: ") name = readLine(stdin) - diff --git a/tests/let/tlet2.nim b/tests/let/tlet2.nim index 2df15fa5c..63e7d6128 100644 --- a/tests/let/tlet2.nim +++ b/tests/let/tlet2.nim @@ -1,6 +1,6 @@ discard """ - line: "13" errormsg: "type mismatch: got " + line: "13" """ proc divmod(a, b: int, res, remainder: var int) = @@ -13,4 +13,3 @@ let divmod(8, 5, x, y) # modifies x and y echo(x) echo(y) - diff --git a/tests/lexer/tind1.nim b/tests/lexer/tind1.nim index ffbde48fd..2185c3074 100644 --- a/tests/lexer/tind1.nim +++ b/tests/lexer/tind1.nim @@ -1,6 +1,6 @@ discard """ - line: 24 errormsg: "invalid indentation" + line: 24 """ import macros diff --git a/tests/lexer/tinvalidintegerliteral1.nim b/tests/lexer/tinvalidintegerliteral1.nim index 08ab82a22..6bf7624f3 100644 --- a/tests/lexer/tinvalidintegerliteral1.nim +++ b/tests/lexer/tinvalidintegerliteral1.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "invalid number" file: "tinvalidintegerliteral1.nim" line: 7 - errormsg: "invalid number" """ echo 0b diff --git a/tests/lexer/tinvalidintegerliteral2.nim b/tests/lexer/tinvalidintegerliteral2.nim index bc8793e4e..eb6efc131 100644 --- a/tests/lexer/tinvalidintegerliteral2.nim +++ b/tests/lexer/tinvalidintegerliteral2.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "invalid number" file: "tinvalidintegerliteral2.nim" line: 7 - errormsg: "invalid number" """ echo 0x diff --git a/tests/lexer/tinvalidintegerliteral3.nim b/tests/lexer/tinvalidintegerliteral3.nim index 9c2fe69df..e09cda54a 100644 --- a/tests/lexer/tinvalidintegerliteral3.nim +++ b/tests/lexer/tinvalidintegerliteral3.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "0O5 is an invalid int literal; For octal literals use the '0o' prefix." file: "tinvalidintegerliteral3.nim" line: 7 - errormsg: "0O5 is an invalid int literal; For octal literals use the '0o' prefix." """ echo 0O5 diff --git a/tests/lexer/tmissingnl.nim b/tests/lexer/tmissingnl.nim index 095d9570e..dc939bcd2 100644 --- a/tests/lexer/tmissingnl.nim +++ b/tests/lexer/tmissingnl.nim @@ -1,10 +1,9 @@ discard """ + errormsg: "invalid indentation" file: "tmissingnl.nim" line: 7 - errormsg: "invalid indentation" """ import strutils let s: seq[int] = @[0, 1, 2, 3, 4, 5, 6] #s[1..3] = @[] - diff --git a/tests/lexer/tstrlits.nim b/tests/lexer/tstrlits.nim index d13baf7ff..004ebc0a7 100644 --- a/tests/lexer/tstrlits.nim +++ b/tests/lexer/tstrlits.nim @@ -1,5 +1,4 @@ discard """ - file: "tstrlits.nim" output: "a\"\"long string\"\"\"\"\"abc\"def_'2'●𝌆𝌆A" """ # Test the new different string literals @@ -19,6 +18,3 @@ stdout.write(tripleEmpty) stdout.write(raw) stdout.write(escaped) #OUT a""long string"""""abc"def_'2'●𝌆𝌆A - - - diff --git a/tests/lexer/tunderscores.nim b/tests/lexer/tunderscores.nim index f64f36977..1896a2898 100644 --- a/tests/lexer/tunderscores.nim +++ b/tests/lexer/tunderscores.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "invalid token: trailing underscore" file: "tunderscores.nim" line: 8 - errormsg: "invalid token: trailing underscore" """ # Bug #502670 @@ -9,6 +9,3 @@ var ef_ = 3 #ERROR_MSG invalid token: _ var a__b = 1 var c___d = 2 echo(ab, cd, ef_) - - - diff --git a/tests/macros/tmacrogenerics.nim b/tests/macros/tmacrogenerics.nim index e4acdc321..bb562cacb 100644 --- a/tests/macros/tmacrogenerics.nim +++ b/tests/macros/tmacrogenerics.nim @@ -1,5 +1,4 @@ discard """ - file: "tmacrogenerics.nim" nimout: ''' instantiation 1 with None and None instantiation 2 with None and None diff --git a/tests/macros/tquotewords.nim b/tests/macros/tquotewords.nim index fa00ba9de..e718d25f9 100644 --- a/tests/macros/tquotewords.nim +++ b/tests/macros/tquotewords.nim @@ -1,5 +1,4 @@ discard """ - file: "tquotewords.nim" output: "thisanexample" """ # Test an idea I recently had: diff --git a/tests/macros/trecmacro.nim b/tests/macros/trecmacro.nim index 69ebe3da3..d804178bc 100644 --- a/tests/macros/trecmacro.nim +++ b/tests/macros/trecmacro.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "recursive dependency: 'dump'" file: "trecmacro.nim" line: 8 - errormsg: "recursive dependency: 'dump'" """ macro dump(n: untyped): untyped = diff --git a/tests/macros/tstringinterp.nim b/tests/macros/tstringinterp.nim index 305f40ac5..8b8e1c3a9 100644 --- a/tests/macros/tstringinterp.nim +++ b/tests/macros/tstringinterp.nim @@ -1,5 +1,4 @@ discard """ - file: "tstringinterp.nim" output: "Hello Alice, 64 | Hello Bob, 10$" """ diff --git a/tests/metatype/tmatrix.nim b/tests/metatype/tmatrix.nim index 4fd32a932..076009eb9 100644 --- a/tests/metatype/tmatrix.nim +++ b/tests/metatype/tmatrix.nim @@ -1,5 +1,4 @@ discard """ - file: "tmatrix.nim" output: "111" """ # Test overloading of [] with multiple indices @@ -44,5 +43,3 @@ for i in 0..w-1: for i in 0..w-1: stdout.write(m[i,i]) #OUT 111 - - diff --git a/tests/metatype/tstaticparams.nim b/tests/metatype/tstaticparams.nim index ad6aa6589..09d505f94 100644 --- a/tests/metatype/tstaticparams.nim +++ b/tests/metatype/tstaticparams.nim @@ -1,5 +1,4 @@ discard """ - file: "tstaticparams.nim" output: "abracadabra\ntest\n3\n15\n4\n2\nfloat\n3\nfloat\nyin\nyang\n2\n4\n4\n2\n3" """ @@ -140,7 +139,7 @@ dontBind1 bb_2 dontBind2 bb_1 dontBind2 bb_2 -# https://github.com/nim-lang/Nim/issues/4524 +# https://github.com/nim-lang/Nim/issues/4524 const size* = 2 @@ -172,4 +171,3 @@ echo inSize([ [1, 2, 3], [4, 5, 6] ]) - diff --git a/tests/method/tmethod.nim b/tests/method/tmethod.nim index 0cfe24c70..005294d64 100644 --- a/tests/method/tmethod.nim +++ b/tests/method/tmethod.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "\'method\' needs a parameter that has an object type" file: "tmethod.nim" line: 7 - errormsg: "\'method\' needs a parameter that has an object type" """ method m(i: int): int = diff --git a/tests/misc/t99bott.nim b/tests/misc/t99bott.nim index 62ccfbe16..f60023818 100644 --- a/tests/misc/t99bott.nim +++ b/tests/misc/t99bott.nim @@ -1,9 +1,9 @@ discard """ + errormsg: "cannot evaluate at compile time: bn" file: "t99bott.nim" line: 26 - errormsg: "cannot evaluate at compile time: bn" - disabled: false """ + ## 99 Bottles of Beer ## http://www.99-bottles-of-beer.net/ ## Nim version @@ -30,7 +30,3 @@ for bn in countdown(99, 1): echo "No more bottles of beer on the wall, no more bottles of beer." echo "Go to the store and buy some more, 99 bottles of beer on the wall." - - - - diff --git a/tests/misc/tack.nim b/tests/misc/tack.nim index a0afab9e8..fb89dc8b1 100644 --- a/tests/misc/tack.nim +++ b/tests/misc/tack.nim @@ -1,5 +1,4 @@ discard """ - file: "tack.nim" output: "125" """ # the Ackermann function @@ -17,5 +16,3 @@ proc ack(x, y: int): int = # echo(ack(0, 0)) write(stdout, ack(3, 4)) #OUT 125 - - diff --git a/tests/misc/tbug511622.nim b/tests/misc/tbug511622.nim index a5360423d..4b30e96e6 100644 --- a/tests/misc/tbug511622.nim +++ b/tests/misc/tbug511622.nim @@ -1,5 +1,4 @@ discard """ - file: "tbug511622.nim" output: "3" """ import StrUtils, Math @@ -11,6 +10,3 @@ proc FibonacciA(n: int): int64 = return int64((pow(p, fn) + pow(q, fn)) / sqrt(5.0)) echo FibonacciA(4) #OUT 3 - - - diff --git a/tests/misc/temit.nim b/tests/misc/temit.nim index c83235659..ee7455d4c 100644 --- a/tests/misc/temit.nim +++ b/tests/misc/temit.nim @@ -1,5 +1,4 @@ discard """ - file: "temit.nim" output: "509" """ # Test the new ``emit`` pragma: @@ -14,7 +13,3 @@ proc embedsC() = {.emit: """printf("%d\n", cvariable + (int)`nimVar`);""".} embedsC() - - - - diff --git a/tests/misc/tevents.nim b/tests/misc/tevents.nim index caf674084..045c9fc5b 100644 --- a/tests/misc/tevents.nim +++ b/tests/misc/tevents.nim @@ -1,8 +1,9 @@ discard """ -file: "tevents.nim" -output: '''HandlePrintEvent: Output -> Handled print event +output: ''' +HandlePrintEvent: Output -> Handled print event HandlePrintEvent2: Output -> printing for ME -HandlePrintEvent2: Output -> printing for ME''' +HandlePrintEvent2: Output -> printing for ME +''' """ import events @@ -45,4 +46,3 @@ ee.emit(obj.printEvent, eventargs) obj.printEvent.removeHandler(handleprintevent2) ee.emit(obj.printEvent, eventargs) - diff --git a/tests/misc/tgenconstraints.nim b/tests/misc/tgenconstraints.nim index 6e8fdc738..829da5173 100644 --- a/tests/misc/tgenconstraints.nim +++ b/tests/misc/tgenconstraints.nim @@ -1,8 +1,8 @@ discard """ + errormsg: "cannot instantiate T2" file: "tgenconstraints.nim" line: 25 disabled: true - errormsg: "cannot instantiate T2" """ type @@ -29,4 +29,3 @@ proc bar(x: int|TNumber): T1[type(x)] {.discardable.} = bar "test" bar 100 bar 1.1 - diff --git a/tests/misc/thintoff.nim b/tests/misc/thintoff.nim deleted file mode 100644 index 95318ce9b..000000000 --- a/tests/misc/thintoff.nim +++ /dev/null @@ -1,12 +0,0 @@ -discard """ - file: "thintoff.nim" - output: "0" -""" - -{.hint[XDeclaredButNotUsed]: off.} -var - x: int - -echo x #OUT 0 - - diff --git a/tests/misc/tinc.nim b/tests/misc/tinc.nim index 7819775e3..91f6223e2 100644 --- a/tests/misc/tinc.nim +++ b/tests/misc/tinc.nim @@ -1,12 +1,8 @@ discard """ + errormsg: "type mismatch: got " file: "tinc.nim" line: 8 - errormsg: "type mismatch: got " """ var x = 0 inc(x+1) - - - - diff --git a/tests/misc/tinit.nim b/tests/misc/tinit.nim index 02607909b..207cb17e8 100644 --- a/tests/misc/tinit.nim +++ b/tests/misc/tinit.nim @@ -1,5 +1,4 @@ discard """ - file: "tinit.nim" output: "Hello from module! Hello from main module!" """ # Test the new init section in modules @@ -8,5 +7,3 @@ import minit write(stdout, "Hello from main module!\n") #OUT Hello from module! Hello from main module! - - diff --git a/tests/misc/tinout.nim b/tests/misc/tinout.nim index 46af2f5de..bae0fb185 100644 --- a/tests/misc/tinout.nim +++ b/tests/misc/tinout.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "type mismatch: got " file: "tinout.nim" line: 12 - errormsg: "type mismatch: got " """ # Test in out checking for parameters @@ -12,5 +12,3 @@ proc b() = abc(3) #ERROR b() - - diff --git a/tests/misc/tinvalidnewseq.nim b/tests/misc/tinvalidnewseq.nim index 66e9388ef..dec00fd4a 100644 --- a/tests/misc/tinvalidnewseq.nim +++ b/tests/misc/tinvalidnewseq.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "type mismatch: got " file: "tinvalidnewseq.nim" line: 15 - errormsg: "type mismatch: got " """ import re, strutils @@ -22,6 +22,3 @@ var r: TUrl r = parseUrl(r"http://google.com/search?var=bleahdhsad") echo(r.domain) - - - diff --git a/tests/misc/tissue710.nim b/tests/misc/tissue710.nim index e2cca0024..ec125b840 100644 --- a/tests/misc/tissue710.nim +++ b/tests/misc/tissue710.nim @@ -1,7 +1,7 @@ discard """ + errorMsg: "attempting to call routine: '||'" file: "tissue710.nim" line: 8 - errorMsg: "attempting to call routine: '||'" """ var sum = 0 for x in 3..1000: diff --git a/tests/misc/tnoinst.nim b/tests/misc/tnoinst.nim index 25ebe8dfc..85db1e8e7 100644 --- a/tests/misc/tnoinst.nim +++ b/tests/misc/tnoinst.nim @@ -1,6 +1,6 @@ discard """ - line: 12 errormsg: "instantiate 'notConcrete' explicitly" + line: 12 disabled: "true" """ @@ -14,4 +14,3 @@ proc wrap[T]() = wrap[int]() - diff --git a/tests/misc/tnolen.nim b/tests/misc/tnolen.nim index 2831e5048..e0e8025d4 100644 --- a/tests/misc/tnolen.nim +++ b/tests/misc/tnolen.nim @@ -1,9 +1,8 @@ discard """ - line: 8 errormsg: "type mismatch: got " + line: 8 """ # please finally disallow Len(3) echo len(3) - diff --git a/tests/misc/tnot.nim b/tests/misc/tnot.nim index 5c268981e..a3669705b 100644 --- a/tests/misc/tnot.nim +++ b/tests/misc/tnot.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "type mismatch" file: "tnot.nim" line: 14 - errormsg: "type mismatch" """ # BUG: following compiles, but should not: diff --git a/tests/misc/tparseopt.nim b/tests/misc/tparseopt.nim index 651689398..cbed5d476 100644 --- a/tests/misc/tparseopt.nim +++ b/tests/misc/tparseopt.nim @@ -1,5 +1,4 @@ discard """ - file: "tparseopt.nim" output: ''' parseopt first round diff --git a/tests/misc/tpos.nim b/tests/misc/tpos.nim index bedb62e62..0c8efa43d 100644 --- a/tests/misc/tpos.nim +++ b/tests/misc/tpos.nim @@ -1,5 +1,4 @@ discard """ - file: "tpos.nim" output: "6" """ # test this particular function @@ -31,5 +30,3 @@ var sub = "hello" var s = "world hello" write(stdout, mypos(sub, s)) #OUT 6 - - diff --git a/tests/misc/trawstr.nim b/tests/misc/trawstr.nim index 55e508acc..aa41071d5 100644 --- a/tests/misc/trawstr.nim +++ b/tests/misc/trawstr.nim @@ -1,12 +1,10 @@ discard """ + errormsg: "closing \" expected" file: "trawstr.nim" line: 10 - errormsg: "closing \" expected" """ # Test the new raw strings: const xxx = r"This is a raw string!" yyy = "This not\" #ERROR - - diff --git a/tests/misc/tsimtych.nim b/tests/misc/tsimtych.nim index 037172bd5..74a6ad4c0 100644 --- a/tests/misc/tsimtych.nim +++ b/tests/misc/tsimtych.nim @@ -1,12 +1,10 @@ discard """ + errormsg: "type mismatch: got but expected \'string\'" file: "tsimtych.nim" line: 10 - errormsg: "type mismatch: got but expected \'string\'" """ # Test 2 # Simple type checking var a: string a = false #ERROR - - diff --git a/tests/misc/tslices.nim b/tests/misc/tslices.nim index 388a46509..d063c5ebf 100644 --- a/tests/misc/tslices.nim +++ b/tests/misc/tslices.nim @@ -1,6 +1,6 @@ discard """ - file: "tslices.nim" - output: '''456456 +output: ''' +456456 456456 456456 Zugr5nd @@ -56,4 +56,3 @@ echo mystr var s = "abcdef" s[1 .. ^2] = "xyz" assert s == "axyzf" - diff --git a/tests/misc/tstrange.nim b/tests/misc/tstrange.nim index fee0f44e4..82a82d267 100644 --- a/tests/misc/tstrange.nim +++ b/tests/misc/tstrange.nim @@ -1,8 +1,9 @@ discard """ - file: "tstrange.nim" - output: '''hallo40 +output: ''' +hallo40 1 -2''' +2 +''' """ # test for extremely strange bug @@ -25,4 +26,3 @@ write(stdout, ack(5, 4)) let h=3 for x in 0.. " file: "tnamedparams.nim" line: 8 - errormsg: "type mismatch: got " """ import pegs @@ -10,6 +10,3 @@ discard parsePeg( filename = "filename", line = 1, col = 23) - - - diff --git a/tests/niminaction/Chapter2/explicit_discard.nim b/tests/niminaction/Chapter2/explicit_discard.nim index 3e94c335b..9a3b4407e 100644 --- a/tests/niminaction/Chapter2/explicit_discard.nim +++ b/tests/niminaction/Chapter2/explicit_discard.nim @@ -1,7 +1,7 @@ discard """ - line: 7 errormsg: "has to be discarded" + line: 7 """ proc myProc(name: string): string = "Hello " & name -myProc("Dominik") \ No newline at end of file +myProc("Dominik") diff --git a/tests/niminaction/Chapter2/no_def_eq.nim b/tests/niminaction/Chapter2/no_def_eq.nim index 77f0a7dd8..b9d62e036 100644 --- a/tests/niminaction/Chapter2/no_def_eq.nim +++ b/tests/niminaction/Chapter2/no_def_eq.nim @@ -1,6 +1,6 @@ discard """ - line: 16 errormsg: "type mismatch" + line: 16 """ type @@ -13,4 +13,4 @@ type let dog: Dog = Dog(name: "Fluffy") let cat: Cat = Cat(name: "Fluffy") -echo(dog == cat) \ No newline at end of file +echo(dog == cat) diff --git a/tests/niminaction/Chapter2/no_iterator.nim b/tests/niminaction/Chapter2/no_iterator.nim index 331d69480..555fac21a 100644 --- a/tests/niminaction/Chapter2/no_iterator.nim +++ b/tests/niminaction/Chapter2/no_iterator.nim @@ -1,7 +1,7 @@ discard """ - line: 6 errormsg: "type mismatch" + line: 6 """ for i in 5: - echo i \ No newline at end of file + echo i diff --git a/tests/niminaction/Chapter2/no_seq_type.nim b/tests/niminaction/Chapter2/no_seq_type.nim index 493be270a..f1494124b 100644 --- a/tests/niminaction/Chapter2/no_seq_type.nim +++ b/tests/niminaction/Chapter2/no_seq_type.nim @@ -1,6 +1,6 @@ discard """ - line: 6 errormsg: "cannot infer the type of the sequence" + line: 6 """ -var list = @[] \ No newline at end of file +var list = @[] diff --git a/tests/niminaction/Chapter2/resultreject.nim b/tests/niminaction/Chapter2/resultreject.nim index de59af7d9..87c84bf0a 100644 --- a/tests/niminaction/Chapter2/resultreject.nim +++ b/tests/niminaction/Chapter2/resultreject.nim @@ -1,13 +1,13 @@ discard """ - line: 27 errormsg: "has to be discarded" + line: 27 """ # Page 35. proc implicit: string = "I will be returned" - + proc discarded: string = discard "I will not be returned" @@ -16,7 +16,7 @@ proc explicit: string = proc resultVar: string = result = "I will be returned" - + proc resultVar2: string = result = "" result.add("I will be ") @@ -30,4 +30,4 @@ doAssert implicit() == "I will be returned" doAssert discarded() == nil doAssert explicit() == "I will be returned" doAssert resultVar() == "I will be returned" -doAssert resultVar2() == "I will be returned" \ No newline at end of file +doAssert resultVar2() == "I will be returned" diff --git a/tests/notnil/tnotnil.nim b/tests/notnil/tnotnil.nim index aff3f8959..c33b6fcac 100644 --- a/tests/notnil/tnotnil.nim +++ b/tests/notnil/tnotnil.nim @@ -1,6 +1,6 @@ discard """ - line: 13 errormsg: "type mismatch" + line: 13 """ {.experimental: "notnil".} type diff --git a/tests/objects/tobjpragma.nim b/tests/objects/tobjpragma.nim index 0a6cc893b..789b3ec4e 100644 --- a/tests/objects/tobjpragma.nim +++ b/tests/objects/tobjpragma.nim @@ -1,13 +1,14 @@ discard """ - file: "tobjpragma.nim" - output: '''2 + output: ''' +2 3 9 257 1 2 -3''' - disabled: "true" +3 +''' +disabled: "true" """ # Disabled since some versions of GCC ignore the 'packed' attribute diff --git a/tests/objects/toop1.nim b/tests/objects/toop1.nim index f4880e3c6..f22ddaf62 100644 --- a/tests/objects/toop1.nim +++ b/tests/objects/toop1.nim @@ -1,5 +1,4 @@ discard """ - file: "toop1.nim" output: "34[]o 5" """ # Test the stuff in the tutorial diff --git a/tests/objvariant/tadrdisc.nim b/tests/objvariant/tadrdisc.nim index 258fb42f3..a68dddf66 100644 --- a/tests/objvariant/tadrdisc.nim +++ b/tests/objvariant/tadrdisc.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "type mismatch: got " file: "tadrdisc.nim" line: 20 - errormsg: "type mismatch: got " """ # Test that the address of a dicriminants cannot be taken diff --git a/tests/objvariant/temptycaseobj.nim b/tests/objvariant/temptycaseobj.nim index 53171e054..2b2c40514 100644 --- a/tests/objvariant/temptycaseobj.nim +++ b/tests/objvariant/temptycaseobj.nim @@ -1,6 +1,6 @@ discard """ - line: 11 errormsg: "identifier expected, but got 'keyword of'" + line: 11 """ type @@ -10,5 +10,3 @@ type of enA: of enU: x, y: int of enO: a, b: string - - diff --git a/tests/objvariant/tvariantstack.nim b/tests/objvariant/tvariantstack.nim index 0cdde5a20..31a0d8b82 100644 --- a/tests/objvariant/tvariantstack.nim +++ b/tests/objvariant/tvariantstack.nim @@ -1,6 +1,5 @@ discard """ - file: "tvariantstack.nim" - output: "came here" +output: "came here" """ #BUG type diff --git a/tests/openarray/t8259.nim b/tests/openarray/t8259.nim index 40ff2b2f1..c07576997 100644 --- a/tests/openarray/t8259.nim +++ b/tests/openarray/t8259.nim @@ -1,6 +1,6 @@ discard """ - line: 6 errormsg: "invalid type: 'openarray[int]' for result" + line: 6 """ proc foo(a: openArray[int]):auto = a diff --git a/tests/openarray/topena1.nim b/tests/openarray/topena1.nim index 0dbc5506a..ed3a0cedb 100644 --- a/tests/openarray/topena1.nim +++ b/tests/openarray/topena1.nim @@ -1,12 +1,9 @@ discard """ + errormsg: "invalid type" file: "topena1.nim" line: 9 - errormsg: "invalid type" """ # Tests a special bug var x: ref openarray[string] #ERROR_MSG invalid type - - - diff --git a/tests/openarray/topenarrayrepr.nim b/tests/openarray/topenarrayrepr.nim index d276756bc..3784d4bbb 100644 --- a/tests/openarray/topenarrayrepr.nim +++ b/tests/openarray/topenarrayrepr.nim @@ -1,5 +1,4 @@ discard """ - file: "topenarrayrepr.nim" output: "5 - [1]" """ type @@ -12,6 +11,3 @@ proc Bar(n: int, m: openarray[int64]) = echo($n & " - " & repr(m)) Foo(5, Bar) #OUT 5 - [1] - - - diff --git a/tests/openarray/topenlen.nim b/tests/openarray/topenlen.nim index fec8e87b7..83d58ac5c 100644 --- a/tests/openarray/topenlen.nim +++ b/tests/openarray/topenlen.nim @@ -1,5 +1,4 @@ discard """ - file: "topenlen.nim" output: "7" """ # Tests a special bug @@ -14,5 +13,3 @@ proc p(a, b: openarray[string]): int = discard choose(["sh", "-c", $p([""], ["a"])]) echo($p(["", "ha", "abc"], ["xyz"])) #OUT 7 - - diff --git a/tests/openarray/tptrarrayderef.nim b/tests/openarray/tptrarrayderef.nim index 1e73be108..5c63f6f98 100644 --- a/tests/openarray/tptrarrayderef.nim +++ b/tests/openarray/tptrarrayderef.nim @@ -1,5 +1,4 @@ discard """ - file: "tptrarrayderef.nim" output: "OK" """ @@ -15,7 +14,7 @@ var proc mutate[T](arr:openarray[T], brr: openArray[T]) = for i in 0..arr.len-1: doAssert(arr[i] == brr[i]) - + mutate(arr, arr) #bug #2240 @@ -46,9 +45,9 @@ proc getFilledBuffer(sz: int): ref seq[char] = s[] = newSeq[char](sz) fillBuffer(s[]) return s - + let aa = getFilledBuffer(3) for i in 0..aa[].len-1: doAssert(aa[i] == chr(i)) - -echo "OK" \ No newline at end of file + +echo "OK" diff --git a/tests/osproc/texecps.nim b/tests/osproc/texecps.nim index 887d79bfb..780adb7ce 100644 --- a/tests/osproc/texecps.nim +++ b/tests/osproc/texecps.nim @@ -1,5 +1,4 @@ discard """ - file: "texecps.nim" output: "" """ diff --git a/tests/osproc/texitcode.nim b/tests/osproc/texitcode.nim index 6dc5508b5..558017716 100644 --- a/tests/osproc/texitcode.nim +++ b/tests/osproc/texitcode.nim @@ -1,5 +1,4 @@ discard """ - file: "texitcode.nim" output: "" """ diff --git a/tests/osproc/tstdin.nim b/tests/osproc/tstdin.nim index 9b49ed786..8579680ab 100644 --- a/tests/osproc/tstdin.nim +++ b/tests/osproc/tstdin.nim @@ -1,5 +1,4 @@ discard """ - file: "tstdin.nim" output: "10" """ import osproc, os, streams diff --git a/tests/osproc/tworkingdir.nim b/tests/osproc/tworkingdir.nim index 7d58d5ae6..3a3c1b6ab 100644 --- a/tests/osproc/tworkingdir.nim +++ b/tests/osproc/tworkingdir.nim @@ -1,5 +1,4 @@ discard """ - file: "tworkingdir.nim" output: "" """ diff --git a/tests/overflw/toverflw.nim b/tests/overflw/toverflw.nim index 20bc56a53..aef597e6c 100644 --- a/tests/overflw/toverflw.nim +++ b/tests/overflw/toverflw.nim @@ -1,8 +1,6 @@ discard """ - file: "toverflw.nim" output: "ok" cmd: "nim $target -d:release $options $file" - """ # Tests nim's ability to detect overflows diff --git a/tests/overflw/toverflw2.nim b/tests/overflw/toverflw2.nim index 75bd4cdf5..91b900ca4 100644 --- a/tests/overflw/toverflw2.nim +++ b/tests/overflw/toverflw2.nim @@ -1,10 +1,7 @@ discard """ - file: "toverflw2.nim" outputsub: "Error: unhandled exception: over- or underflow [OverflowError]" exitcode: "1" """ var a : int32 = 2147483647 var b : int32 = 2147483647 var c = a + b - - diff --git a/tests/overflw/tovfint.nim b/tests/overflw/tovfint.nim index f775d2e1c..5c440a540 100644 --- a/tests/overflw/tovfint.nim +++ b/tests/overflw/tovfint.nim @@ -1,5 +1,4 @@ discard """ - file: "tovfint.nim" output: "works!" """ # this tests the new overflow literals @@ -19,5 +18,3 @@ else: write(stdout, "broken!\n") #OUT works! - - diff --git a/tests/overload/toverl.nim b/tests/overload/toverl.nim index 807b643a4..64257be77 100644 --- a/tests/overload/toverl.nim +++ b/tests/overload/toverl.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "redefinition of \'TNone\'" file: "toverl.nim" line: 11 - errormsg: "redefinition of \'TNone\'" """ # Test for overloading @@ -9,5 +9,3 @@ type TNone {.exportc: "_NONE", final.} = object proc TNone(a, b: int) = nil #ERROR_MSG attempt to redefine 'TNone' - - diff --git a/tests/parallel/tgc_unsafe2.nim b/tests/parallel/tgc_unsafe2.nim index 40bfbdadb..0a56a23aa 100644 --- a/tests/parallel/tgc_unsafe2.nim +++ b/tests/parallel/tgc_unsafe2.nim @@ -1,10 +1,10 @@ discard """ + errormsg: "'consumer' is not GC-safe as it calls 'track'" line: 28 nimout: '''tgc_unsafe2.nim(22, 6) Warning: 'trick' is not GC-safe as it accesses 'global' which is a global using GC'ed memory [GcUnsafe2] tgc_unsafe2.nim(26, 6) Warning: 'track' is not GC-safe as it calls 'trick' [GcUnsafe2] tgc_unsafe2.nim(28, 6) Error: 'consumer' is not GC-safe as it calls 'track' ''' - errormsg: "'consumer' is not GC-safe as it calls 'track'" """ import threadpool diff --git a/tests/parallel/tsysspawnbadarg.nim b/tests/parallel/tsysspawnbadarg.nim index 2d3ffd241..a8f1ed401 100644 --- a/tests/parallel/tsysspawnbadarg.nim +++ b/tests/parallel/tsysspawnbadarg.nim @@ -1,6 +1,6 @@ discard """ - line: 9 errormsg: "'spawn' takes a call expression" + line: 9 cmd: "nim $target --threads:on $options $file" """ diff --git a/tests/parser/tdomulttest.nim b/tests/parser/tdomulttest.nim index 418192ac8..9e1afd034 100644 --- a/tests/parser/tdomulttest.nim +++ b/tests/parser/tdomulttest.nim @@ -1,14 +1,14 @@ discard """ - file: "tdomulttest.nim" output: "555\ntest\nmulti lines\n99999999\nend" - disabled: true """ + proc foo(bar, baz: proc (x: int): int) = echo bar(555) echo baz(99999999) foo do (x: int) -> int: return x + do (x: int) -> int: echo("test") echo("multi lines") diff --git a/tests/parser/tinvcolonlocation1.nim b/tests/parser/tinvcolonlocation1.nim index 2fddab2f8..7fca5deb7 100644 --- a/tests/parser/tinvcolonlocation1.nim +++ b/tests/parser/tinvcolonlocation1.nim @@ -1,8 +1,8 @@ discard """ + errormsg: "expected: ':', but got: 'echo'" file: "tinvcolonlocation1.nim" line: 8 column: 7 - errormsg: "expected: ':', but got: 'echo'" """ try #<- missing ':' echo "try" diff --git a/tests/parser/tinvcolonlocation2.nim b/tests/parser/tinvcolonlocation2.nim index 4251598b9..e3de393b8 100644 --- a/tests/parser/tinvcolonlocation2.nim +++ b/tests/parser/tinvcolonlocation2.nim @@ -1,8 +1,8 @@ discard """ + errormsg: "expected: ':', but got: 'keyword finally'" file: "tinvcolonlocation2.nim" line: 11 column: 8 - errormsg: "expected: ':', but got: 'keyword finally'" """ try: echo "try" diff --git a/tests/parser/tinvcolonlocation3.nim b/tests/parser/tinvcolonlocation3.nim index a8db658eb..46252f24e 100644 --- a/tests/parser/tinvcolonlocation3.nim +++ b/tests/parser/tinvcolonlocation3.nim @@ -1,8 +1,8 @@ discard """ + errormsg: "expected: ':', but got: 'echo'" file: "tinvcolonlocation3.nim" line: 12 column: 7 - errormsg: "expected: ':', but got: 'echo'" """ try: echo "try" diff --git a/tests/parser/tinvwhen.nim b/tests/parser/tinvwhen.nim index 99701bdf5..7a47f69a4 100644 --- a/tests/parser/tinvwhen.nim +++ b/tests/parser/tinvwhen.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "invalid indentation" file: "tinvwhen.nim" line: 11 - errormsg: "invalid indentation" """ # This was parsed even though it should not! @@ -11,5 +11,3 @@ proc getcwd(buf: cstring, buflen: cint): cstring when defined(unix): {.importc: "getcwd", header: "".} #ERROR_MSG invalid indentation elif defined(windows): {.importc: "getcwd", header: ""} else: {.error: "os library not ported to your OS. Please help!".} - - diff --git a/tests/parser/toprprec.nim b/tests/parser/toprprec.nim index 1acd381e7..363ad1c18 100644 --- a/tests/parser/toprprec.nim +++ b/tests/parser/toprprec.nim @@ -1,5 +1,4 @@ discard """ - file: "toprprec.nim" output: "done" """ # Test operator precedence: diff --git a/tests/parser/ttupleunpack.nim b/tests/parser/ttupleunpack.nim index aaa06f9f4..c7ab9ea15 100644 --- a/tests/parser/ttupleunpack.nim +++ b/tests/parser/ttupleunpack.nim @@ -1,9 +1,3 @@ -discard """ - file: "ttupleunpack.nim" - output: "" - exitcode: 0 -""" - proc returnsTuple(): (int, int, int) = (4, 2, 3) proc main2 = diff --git a/tests/pragmas/t6448.nim b/tests/pragmas/t6448.nim index 61e4a35d9..a1bd747a0 100644 --- a/tests/pragmas/t6448.nim +++ b/tests/pragmas/t6448.nim @@ -1,6 +1,6 @@ discard """ - line: 9 errormsg: '''ambiguous call; both foobar.async''' + line: 9 """ import foobar @@ -9,7 +9,7 @@ import asyncdispatch, macros proc bar() {.async.} = echo 42 -proc foo() {.async.} = +proc foo() {.async.} = await bar() asyncCheck foo() diff --git a/tests/pragmas/t8741.nim b/tests/pragmas/t8741.nim index 41f2f9e8a..c132c3543 100644 --- a/tests/pragmas/t8741.nim +++ b/tests/pragmas/t8741.nim @@ -1,6 +1,6 @@ discard """ - line: 9 errormsg: "cannot attach a custom pragma to 'a'" + line: 9 """ for a {.gensym, inject.} in @[1,2,3]: diff --git a/tests/pragmas/tuserpragma2.nim b/tests/pragmas/tuserpragma2.nim index bf8844e66..ce16c4649 100644 --- a/tests/pragmas/tuserpragma2.nim +++ b/tests/pragmas/tuserpragma2.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "can raise an unlisted exception: ref Exception" file: "tuserpragma2.nim" line: 11 - errormsg: "can raise an unlisted exception: ref Exception" """ # bug #7216 diff --git a/tests/proc/tprocredef.nim b/tests/proc/tprocredef.nim index 4ec771510..0cd6ec770 100644 --- a/tests/proc/tprocredef.nim +++ b/tests/proc/tprocredef.nim @@ -1,9 +1,8 @@ discard """ + errormsg: "redefinition of \'foo\'" file: "tprocredef.nim" line: 8 - errormsg: "redefinition of \'foo\'" """ proc foo(a: int, b: string) = discard proc foo(a: int, b: string) = discard - diff --git a/tests/range/tsubrange.nim b/tests/range/tsubrange.nim index 914e7c6e7..f778c55eb 100644 --- a/tests/range/tsubrange.nim +++ b/tests/range/tsubrange.nim @@ -1,6 +1,6 @@ discard """ - line: 20 errormsg: "cannot convert 60 to TRange" + line: 20 """ type @@ -18,4 +18,3 @@ p y const myConst: TRange = 60 - diff --git a/tests/range/tsubrange2.nim b/tests/range/tsubrange2.nim index 7097faed2..e0fb71c5f 100644 --- a/tests/range/tsubrange2.nim +++ b/tests/range/tsubrange2.nim @@ -1,5 +1,4 @@ discard """ - file: "tsubrange2.nim" outputsub: "value out of range: 50 [RangeError]" exitcode: "1" """ @@ -14,4 +13,3 @@ var r: TRange y = 50 p y - diff --git a/tests/range/tsubrange3.nim b/tests/range/tsubrange3.nim index f5bb2f161..d3aae87df 100644 --- a/tests/range/tsubrange3.nim +++ b/tests/range/tsubrange3.nim @@ -1,5 +1,4 @@ discard """ - file: "tsubrange.nim" outputsub: "value out of range: 50 [RangeError]" exitcode: "1" """ diff --git a/tests/rational/trat_float.nim b/tests/rational/trat_float.nim index 24797c4a0..663973bf9 100644 --- a/tests/rational/trat_float.nim +++ b/tests/rational/trat_float.nim @@ -1,7 +1,7 @@ discard """ + errormsg: '''type mismatch: got''' file: "trat_float.nim" line: "9,19" - errormsg: '''type mismatch: got''' """ import rationals var diff --git a/tests/sets/t2669.nim b/tests/sets/t2669.nim index 6b8eb0f54..0a92818fa 100644 --- a/tests/sets/t2669.nim +++ b/tests/sets/t2669.nim @@ -1,6 +1,6 @@ discard """ -line: 6 errormsg: "cannot convert 6 to range 1..5(int8)" +line: 6 """ var c: set[range[1i8..5i8]] = {1i8, 2i8, 6i8} diff --git a/tests/sets/tsets.nim b/tests/sets/tsets.nim index 13a5f54e6..bde25cf81 100644 --- a/tests/sets/tsets.nim +++ b/tests/sets/tsets.nim @@ -1,7 +1,8 @@ discard """ - file: "tsets.nim" - output: '''Ha ein F ist in s! -false''' +output: ''' +Ha ein F ist in s! +false +''' """ # Test the handling of sets diff --git a/tests/stdlib/t8925.nim b/tests/stdlib/t8925.nim index d3dc1ea86..dbf55fd88 100644 --- a/tests/stdlib/t8925.nim +++ b/tests/stdlib/t8925.nim @@ -1,6 +1,6 @@ discard """ - file: "strscans.nim" errormsg: "type mismatch between pattern '$i' (position: 1) and HourRange var 'hour'" + file: "strscans.nim" """ import strscans diff --git a/tests/stdlib/tbitops.nim b/tests/stdlib/tbitops.nim index 8301256c4..d8c6da1d4 100644 --- a/tests/stdlib/tbitops.nim +++ b/tests/stdlib/tbitops.nim @@ -1,5 +1,4 @@ discard """ - file: "tbitops.nim" output: "OK" """ import bitops diff --git a/tests/stdlib/tbitops2.nim b/tests/stdlib/tbitops2.nim index 31952316c..e8c7318be 100644 --- a/tests/stdlib/tbitops2.nim +++ b/tests/stdlib/tbitops2.nim @@ -1,5 +1,4 @@ discard """ - file: "tbitops.nim" output: "OK" """ import bitops diff --git a/tests/stdlib/tcgi.nim b/tests/stdlib/tcgi.nim index 23b8b82ca..bc177125e 100644 --- a/tests/stdlib/tcgi.nim +++ b/tests/stdlib/tcgi.nim @@ -1,9 +1,3 @@ -discard """ - action: run - file: tcgi.nim - output: "[Suite] Test cgi module" -""" - import unittest import cgi, strtabs diff --git a/tests/stdlib/tjsonmacro.nim b/tests/stdlib/tjsonmacro.nim index bf0bb3ea7..4ba0cdecc 100644 --- a/tests/stdlib/tjsonmacro.nim +++ b/tests/stdlib/tjsonmacro.nim @@ -1,5 +1,4 @@ discard """ - file: "tjsonmacro.nim" output: "" """ import json, strutils, options, tables diff --git a/tests/stdlib/tjsonmacro_reject.nim b/tests/stdlib/tjsonmacro_reject.nim index 00506449f..ada365d7d 100644 --- a/tests/stdlib/tjsonmacro_reject.nim +++ b/tests/stdlib/tjsonmacro_reject.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "Use a named tuple instead of: (string, float)" file: "tjsonmacro_reject.nim" line: 11 - errormsg: "Use a named tuple instead of: (string, float)" """ import json @@ -15,4 +15,4 @@ let j = """ {"engine": {"name": "V8", "capacity": 5.5}, model: "Skyline"} """ let parsed = parseJson(j) -echo(to(parsed, Car)) \ No newline at end of file +echo(to(parsed, Car)) diff --git a/tests/stdlib/tjsonmacro_reject2.nim b/tests/stdlib/tjsonmacro_reject2.nim index b01153553..e13dad307 100644 --- a/tests/stdlib/tjsonmacro_reject2.nim +++ b/tests/stdlib/tjsonmacro_reject2.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "The `to` macro does not support ref objects with cycles." file: "tjsonmacro_reject2.nim" line: 10 - errormsg: "The `to` macro does not support ref objects with cycles." """ import json @@ -18,4 +18,4 @@ let data = """ """ let dataParsed = parseJson(data) -let dataDeser = to(dataParsed, Cycle) \ No newline at end of file +let dataDeser = to(dataParsed, Cycle) diff --git a/tests/stdlib/tmemfiles1.nim b/tests/stdlib/tmemfiles1.nim index a18fba083..21a65369f 100644 --- a/tests/stdlib/tmemfiles1.nim +++ b/tests/stdlib/tmemfiles1.nim @@ -1,7 +1,3 @@ -discard """ - file: "tmemfiles1.nim" - outputsub: "" -""" import memfiles, os var mm: MemFile diff --git a/tests/stdlib/tmemmapstreams.nim b/tests/stdlib/tmemmapstreams.nim index 243574f1a..dd011d777 100644 --- a/tests/stdlib/tmemmapstreams.nim +++ b/tests/stdlib/tmemmapstreams.nim @@ -1,6 +1,6 @@ discard """ - file: "tmemmapstreams.nim" - output: '''Created size: 10 +output: ''' +Created size: 10 Position after writing: 5 Position after writing one char: 6 Peeked data: Hello diff --git a/tests/stdlib/tospaths.nim b/tests/stdlib/tospaths.nim index 9e2a5605c..bee9bab76 100644 --- a/tests/stdlib/tospaths.nim +++ b/tests/stdlib/tospaths.nim @@ -1,5 +1,4 @@ discard """ - file: "tospaths.nim" output: "" """ # test the ospaths module diff --git a/tests/stdlib/tosproc.nim b/tests/stdlib/tosproc.nim index ac129e709..9d57d4574 100644 --- a/tests/stdlib/tosproc.nim +++ b/tests/stdlib/tosproc.nim @@ -1,5 +1,4 @@ discard """ - file: "tospaths.nim" output: "" """ # test the osproc module diff --git a/tests/stdlib/tparsesql.nim b/tests/stdlib/tparsesql.nim index 126020ed6..8cf8fa848 100644 --- a/tests/stdlib/tparsesql.nim +++ b/tests/stdlib/tparsesql.nim @@ -1,7 +1,3 @@ -discard """ - file: "tparsesql.nim" -""" - import parsesql doAssert $parseSQL("SELECT foo FROM table;") == "select foo from table;" diff --git a/tests/stdlib/tregex.nim b/tests/stdlib/tregex.nim index ae6714de1..21f4e6743 100644 --- a/tests/stdlib/tregex.nim +++ b/tests/stdlib/tregex.nim @@ -1,5 +1,4 @@ discard """ - file: "tregex.nim" output: "key: keyAYes!" """ # Test the new regular expression module @@ -27,5 +26,3 @@ else: echo("Bug!") #OUT key: keyAYes! - - diff --git a/tests/stdlib/trepr.nim b/tests/stdlib/trepr.nim index 18fe7e054..33cb581ef 100644 --- a/tests/stdlib/trepr.nim +++ b/tests/stdlib/trepr.nim @@ -1,5 +1,4 @@ discard """ - file: "trepr.nim" output: "{a, b}{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}" """ @@ -26,4 +25,3 @@ when false: # "a", "b", "c", "d", "e" #] #echo(repr(testseq)) - diff --git a/tests/stdlib/tstreams2.nim b/tests/stdlib/tstreams2.nim index 90102d8e3..70f0bac32 100644 --- a/tests/stdlib/tstreams2.nim +++ b/tests/stdlib/tstreams2.nim @@ -1,5 +1,4 @@ discard """ - file: "tstreams2.nim" output: '''fs is: nil''' """ import streams diff --git a/tests/stdlib/tstreams3.nim b/tests/stdlib/tstreams3.nim index b2c9170e3..e3b395e05 100644 --- a/tests/stdlib/tstreams3.nim +++ b/tests/stdlib/tstreams3.nim @@ -1,5 +1,4 @@ discard """ - file: "tstreams3.nim" output: "threw exception" """ import streams diff --git a/tests/stdlib/tstring.nim b/tests/stdlib/tstring.nim index 660746150..852ff4fb7 100644 --- a/tests/stdlib/tstring.nim +++ b/tests/stdlib/tstring.nim @@ -1,5 +1,4 @@ discard """ - file: "tstring.nim" output: "OK" """ const characters = "abcdefghijklmnopqrstuvwxyz" diff --git a/tests/stdlib/tstrutil.nim b/tests/stdlib/tstrutil.nim index 64b8f8ecc..fffa85bd1 100644 --- a/tests/stdlib/tstrutil.nim +++ b/tests/stdlib/tstrutil.nim @@ -1,5 +1,4 @@ discard """ - file: "tstrutil.nim" output: "ha/home/a1xyz/usr/bin" """ # test the new strutils module diff --git a/tests/stdlib/tsugar.nim b/tests/stdlib/tsugar.nim index a870bf6fe..111ca96a4 100644 --- a/tests/stdlib/tsugar.nim +++ b/tests/stdlib/tsugar.nim @@ -1,5 +1,4 @@ discard """ - file: "tsugar.nim" output: "" """ import sugar diff --git a/tests/stdlib/ttimes.nim b/tests/stdlib/ttimes.nim index 7ebbe61d9..ed87b15ac 100644 --- a/tests/stdlib/ttimes.nim +++ b/tests/stdlib/ttimes.nim @@ -1,8 +1,5 @@ discard """ - file: "ttimes.nim" target: "c js" - output: '''[Suite] ttimes -''' """ import times, strutils, unittest @@ -125,7 +122,7 @@ suite "ttimes": when defined(linux) or defined(macosx): let tz_dir = getEnv("TZDIR", "/usr/share/zoneinfo") const f = "yyyy-MM-dd HH:mm zzz" - + let orig_tz = getEnv("TZ") var tz_cnt = 0 for tz_fn in walkFiles(tz_dir & "/**/*"): @@ -152,7 +149,7 @@ suite "ttimes": check initDateTime(29, mOct, 2017, 01, 00, 00).isDst check initDateTime(29, mOct, 2017, 03, 01, 00).format(f) == "2017-10-29 03:01 +01:00" check (not initDateTime(29, mOct, 2017, 03, 01, 00).isDst) - + check initDateTime(21, mOct, 2017, 01, 00, 00).format(f) == "2017-10-21 01:00 +02:00" test "issue #6520": @@ -170,10 +167,10 @@ suite "ttimes": check diff == initDuration(seconds = 2208986872) test "issue #6465": - putEnv("TZ", "Europe/Stockholm") + putEnv("TZ", "Europe/Stockholm") let dt = parse("2017-03-25 12:00", "yyyy-MM-dd hh:mm") check $(dt + initTimeInterval(days = 1)) == "2017-03-26T12:00:00+02:00" - check $(dt + initDuration(days = 1)) == "2017-03-26T13:00:00+02:00" + check $(dt + initDuration(days = 1)) == "2017-03-26T13:00:00+02:00" test "datetime before epoch": check $fromUnix(-2147483648).utc == "1901-12-13T20:45:52Z" diff --git a/tests/template/ttempl2.nim b/tests/template/ttempl2.nim index aaa2f1344..eb67bea0c 100644 --- a/tests/template/ttempl2.nim +++ b/tests/template/ttempl2.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "undeclared identifier: \'b\'" file: "ttempl2.nim" line: 18 - errormsg: "undeclared identifier: \'b\'" """ template declareInScope(x: untyped, t: typeDesc): untyped {.immediate.} = var x: t @@ -16,4 +16,3 @@ a = 42 # works, `a` is known here declareInNewScope(b, int) b = 42 #ERROR_MSG undeclared identifier: 'b' - diff --git a/tests/threads/tthreadanalysis2.nim b/tests/threads/tthreadanalysis2.nim index c1ec3ae39..067e186a8 100644 --- a/tests/threads/tthreadanalysis2.nim +++ b/tests/threads/tthreadanalysis2.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "'threadFunc' is not GC-safe" file: "tthreadanalysis2.nim" line: 37 - errormsg: "'threadFunc' is not GC-safe" cmd: "nim $target --hints:on --threads:on $options $file" """ @@ -49,4 +49,3 @@ proc main = joinThreads(thr) main() - diff --git a/tests/threads/tthreadheapviolation1.nim b/tests/threads/tthreadheapviolation1.nim index 59ecb742c..379bd55e6 100644 --- a/tests/threads/tthreadheapviolation1.nim +++ b/tests/threads/tthreadheapviolation1.nim @@ -1,6 +1,6 @@ discard """ - line: 11 errormsg: "'horrible' is not GC-safe" + line: 11 cmd: "nim $target --hints:on --threads:on $options $file" """ @@ -16,5 +16,3 @@ proc horrible() {.thread.} = createThread[void](t, horrible) joinThread(t) - - diff --git a/tests/trmacros/tdisallowif.nim b/tests/trmacros/tdisallowif.nim index 18dfd1c82..36f60800e 100644 --- a/tests/trmacros/tdisallowif.nim +++ b/tests/trmacros/tdisallowif.nim @@ -1,6 +1,6 @@ discard """ - line: 24 errormsg: "usage of 'disallowIf' is a user-defined error" + line: 24 disabled: true """ diff --git a/tests/tuples/twrongtupleaccess.nim b/tests/tuples/twrongtupleaccess.nim index b1684b097..591716a2e 100644 --- a/tests/tuples/twrongtupleaccess.nim +++ b/tests/tuples/twrongtupleaccess.nim @@ -1,10 +1,9 @@ discard """ + errormsg: "attempting to call undeclared routine: \'setBLAH\'" file: "twrongtupleaccess.nim" line: 9 - errormsg: "attempting to call undeclared routine: \'setBLAH\'" """ # Bugfix var v = (5.0, 10.0) v.setBLAH(10) - diff --git a/tests/typerel/t8172.nim b/tests/typerel/t8172.nim index 8e0b32932..57b788250 100644 --- a/tests/typerel/t8172.nim +++ b/tests/typerel/t8172.nim @@ -1,6 +1,6 @@ discard """ - line: 11 errormsg: "cannot convert array[0..0, string] to varargs[string]" + line: 11 """ proc f(v: varargs[string]) = diff --git a/tests/typerel/temptynode.nim b/tests/typerel/temptynode.nim index df308fbc2..8c71a6092 100644 --- a/tests/typerel/temptynode.nim +++ b/tests/typerel/temptynode.nim @@ -1,6 +1,6 @@ discard """ - line: 16 errormsg: "type mismatch: got " + line: 16 """ # bug #950 diff --git a/tests/typerel/tno_int_in_bool_context.nim b/tests/typerel/tno_int_in_bool_context.nim index a4b4237d2..66e9da58a 100644 --- a/tests/typerel/tno_int_in_bool_context.nim +++ b/tests/typerel/tno_int_in_bool_context.nim @@ -1,8 +1,7 @@ discard """ - line: 6 errormsg: "type mismatch: got but expected 'bool'" + line: 6 """ if 1: echo "wtf?" - diff --git a/tests/typerel/tnocontains.nim b/tests/typerel/tnocontains.nim index a93db2fc3..8bea8aa56 100644 --- a/tests/typerel/tnocontains.nim +++ b/tests/typerel/tnocontains.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "type mismatch: got " file: "tnocontains.nim" line: 10 - errormsg: "type mismatch: got " """ # shouldn't compile since it doesn't do what you think it does without diff --git a/tests/typerel/trefs.nim b/tests/typerel/trefs.nim index d4383c562..e9862bd0f 100644 --- a/tests/typerel/trefs.nim +++ b/tests/typerel/trefs.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "type mismatch" file: "trefs.nim" line: 20 - errormsg: "type mismatch" """ # test for ref types (including refs to procs) @@ -18,6 +18,3 @@ var p: TProc p = foo write(stdout, "success!") p = wrongfoo #ERROR_MSG type mismatch - - - diff --git a/tests/typerel/tregionptrs.nim b/tests/typerel/tregionptrs.nim index 9eeded18b..504ec1011 100644 --- a/tests/typerel/tregionptrs.nim +++ b/tests/typerel/tregionptrs.nim @@ -1,6 +1,6 @@ discard """ - line: 16 errormsg: "type mismatch: got but expected 'APtr = ptr[RegionA, int]'" + line: 16 """ type diff --git a/tests/typerel/ttypedesc_as_genericparam1.nim b/tests/typerel/ttypedesc_as_genericparam1.nim index 9ae464842..b7c3e727d 100644 --- a/tests/typerel/ttypedesc_as_genericparam1.nim +++ b/tests/typerel/ttypedesc_as_genericparam1.nim @@ -1,6 +1,6 @@ discard """ - line: 6 errormsg: "type mismatch: got " + line: 6 """ # bug #3079, #1146 echo repr(int) diff --git a/tests/typerel/ttypedesc_as_genericparam2.nim b/tests/typerel/ttypedesc_as_genericparam2.nim index 0b4281269..ea06606f9 100644 --- a/tests/typerel/ttypedesc_as_genericparam2.nim +++ b/tests/typerel/ttypedesc_as_genericparam2.nim @@ -1,6 +1,6 @@ discard """ - line: 9 errormsg: "'repr' doesn't support 'void' type" + line: 9 """ # bug #2879 diff --git a/tests/typerel/ttypenoval.nim b/tests/typerel/ttypenoval.nim index 720e5d662..c7829f9dd 100644 --- a/tests/typerel/ttypenoval.nim +++ b/tests/typerel/ttypenoval.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "type mismatch: got but expected 'int'" file: "ttypenoval.nim" line: 38 - errormsg: "type mismatch: got but expected 'int'" """ # A min-heap. @@ -51,5 +51,3 @@ var newBinHeap(heap, 256) add(heap, 1, 100) print(heap) - - diff --git a/tests/typerel/typredef.nim b/tests/typerel/typredef.nim index 0b6aed875..c502a834c 100644 --- a/tests/typerel/typredef.nim +++ b/tests/typerel/typredef.nim @@ -1,8 +1,7 @@ discard """ + errormsg: "illegal recursion in type \'Uint8\'" file: "typredef.nim" line: 7 - errormsg: "illegal recursion in type \'Uint8\'" """ type Uint8 = Uint8 #ERROR_MSG illegal recursion in type 'Uint8' - diff --git a/tests/types/t6456.nim b/tests/types/t6456.nim index 2d2aad370..19bbc2c02 100644 --- a/tests/types/t6456.nim +++ b/tests/types/t6456.nim @@ -1,6 +1,6 @@ discard """ - line: 6 errormsg: "type \'ptr void\' is not allowed" + line: 6 """ proc foo(x: ptr void) = diff --git a/tests/types/tassignemptytuple.nim b/tests/types/tassignemptytuple.nim index bdfc653a5..9d5a311ba 100644 --- a/tests/types/tassignemptytuple.nim +++ b/tests/types/tassignemptytuple.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "cannot infer the type of the tuple" file: "tassignemptytuple.nim" line: 11 - errormsg: "cannot infer the type of the tuple" """ var diff --git a/tests/types/tillrec.nim b/tests/types/tillrec.nim index 18757140a..7584282b6 100644 --- a/tests/types/tillrec.nim +++ b/tests/types/tillrec.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "illegal recursion in type \'TIllegal\'" file: "tillrec.nim" line: 13 - errormsg: "illegal recursion in type \'TIllegal\'" """ # test illegal recursive types @@ -13,4 +13,3 @@ type TIllegal {.final.} = object #ERROR_MSG illegal recursion in type 'TIllegal' y: int x: array[0..3, TIllegal] - diff --git a/tests/types/tparameterizedparent0.nim b/tests/types/tparameterizedparent0.nim index 1b72a4e21..90e7a9c0c 100644 --- a/tests/types/tparameterizedparent0.nim +++ b/tests/types/tparameterizedparent0.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "inheritance only works with non-final objects" file: "tparameterizedparent0.nim" line: 14 - errormsg: "inheritance only works with non-final objects" """ # bug #5264 type diff --git a/tests/types/tparameterizedparent1.nim b/tests/types/tparameterizedparent1.nim index 24fb9a565..5da8189f4 100644 --- a/tests/types/tparameterizedparent1.nim +++ b/tests/types/tparameterizedparent1.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "inheritance only works with non-final objects" file: "tparameterizedparent1.nim" line: 14 - errormsg: "inheritance only works with non-final objects" """ # bug #5264 type diff --git a/tests/types/tparameterizedparent3.nim b/tests/types/tparameterizedparent3.nim index 58aaf80ea..fcca6453e 100644 --- a/tests/types/tparameterizedparent3.nim +++ b/tests/types/tparameterizedparent3.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "attempt to redefine: 'color'" file: "tparameterizedparent3.nim" line: 13 - errormsg: "attempt to redefine: 'color'" """ # bug #5264 type diff --git a/tests/types/tparameterizedparent4.nim b/tests/types/tparameterizedparent4.nim index a37461bb4..4759d9d9b 100644 --- a/tests/types/tparameterizedparent4.nim +++ b/tests/types/tparameterizedparent4.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "attempt to redefine: 'grain'" file: "tparameterizedparent4.nim" line: 23 - errormsg: "attempt to redefine: 'grain'" """ # bug #5264 type diff --git a/tests/usingstmt/tusingstatement.nim b/tests/usingstmt/tusingstatement.nim index 8585bcc9e..fc050ee5b 100644 --- a/tests/usingstmt/tusingstatement.nim +++ b/tests/usingstmt/tusingstatement.nim @@ -1,5 +1,4 @@ discard """ - file: "tusingstatement.nim" output: "Using test.Closing test." """ diff --git a/tests/varres/tnewseq_on_result_vart.nim b/tests/varres/tnewseq_on_result_vart.nim index 18935a1d1..4a700468f 100644 --- a/tests/varres/tnewseq_on_result_vart.nim +++ b/tests/varres/tnewseq_on_result_vart.nim @@ -1,7 +1,7 @@ discard """ - line: 9 errormsg: "address of 'result' may not escape its stack frame" + line: 9 """ # bug #5113 diff --git a/tests/varres/tprevent_forloopvar_mutations.nim b/tests/varres/tprevent_forloopvar_mutations.nim index 15938bb77..43cc04f30 100644 --- a/tests/varres/tprevent_forloopvar_mutations.nim +++ b/tests/varres/tprevent_forloopvar_mutations.nim @@ -1,6 +1,6 @@ discard """ - line: 15 errmsg: "type mismatch: got " + line: 15 nimout: '''type mismatch: got but expected one of: proc inc[T: Ordinal | uint | uint64](x: var T; y = 1) diff --git a/tests/varres/tvarres1.nim b/tests/varres/tvarres1.nim index 5a5247142..e58d7f083 100644 --- a/tests/varres/tvarres1.nim +++ b/tests/varres/tvarres1.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "'bla' escapes its stack frame; context: 'bla'" file: "tvarres1.nim" line: 12 - errormsg: "'bla' escapes its stack frame; context: 'bla'" """ var @@ -14,4 +14,3 @@ proc p(): var int = p() = 45 echo g - diff --git a/tests/varres/tvarres2.nim b/tests/varres/tvarres2.nim index 53a57d882..4ec0bb05b 100644 --- a/tests/varres/tvarres2.nim +++ b/tests/varres/tvarres2.nim @@ -1,7 +1,7 @@ discard """ + errormsg: "expression has no address" file: "tvarres2.nim" line: 11 - errormsg: "expression has no address" """ var @@ -13,4 +13,3 @@ proc p(): var int = p() = 45 echo g - diff --git a/tests/varres/tvarres_via_forwarding.nim b/tests/varres/tvarres_via_forwarding.nim index 8fd3dfcfd..fb7201ad2 100644 --- a/tests/varres/tvarres_via_forwarding.nim +++ b/tests/varres/tvarres_via_forwarding.nim @@ -1,6 +1,6 @@ discard """ - line: 10 errormsg: "'y' escapes its stack frame; context: 'forward(y)'" + line: 10 """ proc forward(x: var int): var int = result = x diff --git a/tests/varres/tvartup.nim b/tests/varres/tvartup.nim index 1957a3e35..a8f15b232 100644 --- a/tests/varres/tvartup.nim +++ b/tests/varres/tvartup.nim @@ -1,5 +1,4 @@ discard """ - file: "tvartup.nim" output: "2 3" """ # Test the new tuple unpacking @@ -9,5 +8,3 @@ proc divmod(a, b: int): tuple[di, mo: int] = var (x, y) = divmod(15, 6) echo x, " ", y - -#OUT 2 3 diff --git a/tests/varres/twrong_parameter.nim b/tests/varres/twrong_parameter.nim index 8a363dd19..58d01fd7e 100644 --- a/tests/varres/twrong_parameter.nim +++ b/tests/varres/twrong_parameter.nim @@ -1,6 +1,6 @@ discard """ - line: 10 errormsg: "'x' is not the first parameter; context: 'x.field[0]'" + line: 10 """ type diff --git a/tests/varstmt/tvardecl.nim b/tests/varstmt/tvardecl.nim index a6b508295..664de7134 100644 --- a/tests/varstmt/tvardecl.nim +++ b/tests/varstmt/tvardecl.nim @@ -1,5 +1,4 @@ discard """ - file: "tvardecl.nim" output: "44" """ # Test the new variable declaration syntax @@ -11,5 +10,3 @@ var write(stdout, a) write(stdout, b) #OUT 44 - - diff --git a/tests/vm/t2574.nim b/tests/vm/t2574.nim index 86602aeaf..4332667b4 100644 --- a/tests/vm/t2574.nim +++ b/tests/vm/t2574.nim @@ -1,6 +1,6 @@ discard """ - line: 14 errormsg: "cannot call method eval at compile time" + line: 14 """ type diff --git a/tests/vm/tcastint.nim b/tests/vm/tcastint.nim index f9d42fc54..437342a74 100644 --- a/tests/vm/tcastint.nim +++ b/tests/vm/tcastint.nim @@ -1,5 +1,4 @@ discard """ - file: "tcastint.nim" output: "OK" """ @@ -130,7 +129,7 @@ proc test_float_cast = doAssert(mantissa == 0, $mantissa) # construct 2^N float, where N is integer - let x = -2'i64 + let x = -2'i64 let xx = (x + exp_bias) shl exp_shift let xf = cast[float](xx) doAssert(xf == 0.25, $xf) @@ -151,7 +150,7 @@ proc test_float32_cast = doAssert(mantissa == 0, $mantissa) # construct 2^N float32 where N is integer - let x = 4'i32 + let x = 4'i32 let xx = (x + exp_bias) shl exp_shift let xf = cast[float32](xx) doAssert(xf == 16.0'f32, $xf) From fb1f5c62b5e74b1a532ddfe9d6c373fc61eff878 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arne=20D=C3=B6ring?= Date: Fri, 30 Nov 2018 14:28:18 +0100 Subject: [PATCH 076/110] tshouldfail is stricter --- testament/tests/shouldfail/tcolumn.nim | 2 +- testament/tests/shouldfail/terrormsg.nim | 2 +- testament/tests/shouldfail/tfile.nim | 2 +- testament/tests/shouldfail/tline.nim | 2 +- tests/testament/tshouldfail.nim | 14 ++++++++++++++ 5 files changed, 18 insertions(+), 4 deletions(-) diff --git a/testament/tests/shouldfail/tcolumn.nim b/testament/tests/shouldfail/tcolumn.nim index f4046d58d..89482e673 100644 --- a/testament/tests/shouldfail/tcolumn.nim +++ b/testament/tests/shouldfail/tcolumn.nim @@ -1,7 +1,7 @@ discard """ +errormsg: "undeclared identifier: 'undeclared'" line: 8 column: 7 -errormsg: "undeclared identifier: 'undeclared'" """ # test should fail because the line directive is wrong diff --git a/testament/tests/shouldfail/terrormsg.nim b/testament/tests/shouldfail/terrormsg.nim index 61c08d93d..dbbdf5021 100644 --- a/testament/tests/shouldfail/terrormsg.nim +++ b/testament/tests/shouldfail/terrormsg.nim @@ -1,7 +1,7 @@ discard """ +errormsg: "wrong error message" line: 8 column: 6 -errormsg: "wrong error message" """ # test should fail because the line directive is wrong diff --git a/testament/tests/shouldfail/tfile.nim b/testament/tests/shouldfail/tfile.nim index 07a526c68..a6c2ad359 100644 --- a/testament/tests/shouldfail/tfile.nim +++ b/testament/tests/shouldfail/tfile.nim @@ -1,6 +1,6 @@ discard """ -file: "notthisfile.nim" errmsg: "undeclared identifier: 'undefined'" +file: "notthisfile.nim" """ echo undefined diff --git a/testament/tests/shouldfail/tline.nim b/testament/tests/shouldfail/tline.nim index 963e44fc7..f7a09875c 100644 --- a/testament/tests/shouldfail/tline.nim +++ b/testament/tests/shouldfail/tline.nim @@ -1,7 +1,7 @@ discard """ +errormsg: "undeclared identifier: 'undeclared'" line: 9 column: 6 -errormsg: "undeclared identifier: 'undeclared'" """ # test should fail because the line directive is wrong diff --git a/tests/testament/tshouldfail.nim b/tests/testament/tshouldfail.nim index a8638e236..d35dd99ac 100644 --- a/tests/testament/tshouldfail.nim +++ b/tests/testament/tshouldfail.nim @@ -3,15 +3,29 @@ cmd: "testament/tester --directory:testament --colors:off --backendLogging:off - action: compile nimout: ''' FAIL: tccodecheck.nim C +Failure: reCodegenFailure +Expected: +baz FAIL: tcolumn.nim C +Failure: reLinesDiffer FAIL: terrormsg.nim C +Failure: reMsgsDiffer FAIL: texitcode1.nim C +Failure: reExitcodesDiffer FAIL: tfile.nim C +Failure: reFilesDiffer FAIL: tline.nim C +Failure: reLinesDiffer FAIL: tmaxcodesize.nim C +Failure: reCodegenFailure +max allowed size: 1 FAIL: tnimout.nim C +Failure: reMsgsDiffer FAIL: toutput.nim C +Failure: reOutputsDiffer FAIL: toutputsub.nim C +Failure: reOutputsDiffer FAIL: tsortoutput.nim C +Failure: reOutputsDiffer ''' """ From 2a4c09ff8887350ec3fa283fe8d562e71b68406b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arne=20D=C3=B6ring?= Date: Mon, 3 Dec 2018 19:12:59 +0100 Subject: [PATCH 077/110] megatest can be executed --- compiler/ccgstmts.nim | 3 +- testament/categories.nim | 113 ++++++++++++++++++ testament/specs.nim | 1 - testament/tester.nim | 5 +- tests/array/tarray.nim | 2 +- tests/async/tasyncfile.nim | 3 +- tests/ccgbugs/tconstobj.nim | 16 --- .../collections/{tsets.nim => thashsets.nim} | 0 tests/compilerapi/tcompilerapi.nim | 3 +- .../{trandom_vars.nim => trandomvars2.nim} | 0 tests/iter/{tconcat.nim => titerconcat.nim} | 0 .../macros/{tgensym.nim => tmacrogensym.nim} | 0 ...ttypeclasses.nim => tmeta_typeclasses.nim} | 0 .../{tmatrix.nim => tmetatypematrix.nim} | 0 tests/misc/tradix.nim | 100 +--------------- tests/stdlib/tsqlparser.nim | 2 +- tests/stdlib/tstdlib_various.nim | 2 +- tests/system/tostring.nim | 5 +- .../types/{tissues.nim => tissues_types.nim} | 0 tests/vm/tconstobj.nim | 22 +++- tests/vm/{tmitems.nim => tmitems_vm.nim} | 0 tests/vm/tvmmisc.nim | 3 +- 22 files changed, 150 insertions(+), 130 deletions(-) delete mode 100644 tests/ccgbugs/tconstobj.nim rename tests/collections/{tsets.nim => thashsets.nim} (100%) rename tests/concepts/{trandom_vars.nim => trandomvars2.nim} (100%) rename tests/iter/{tconcat.nim => titerconcat.nim} (100%) rename tests/macros/{tgensym.nim => tmacrogensym.nim} (100%) rename tests/metatype/{ttypeclasses.nim => tmeta_typeclasses.nim} (100%) rename tests/metatype/{tmatrix.nim => tmetatypematrix.nim} (100%) rename tests/types/{tissues.nim => tissues_types.nim} (100%) rename tests/vm/{tmitems.nim => tmitems_vm.nim} (100%) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index e83b80b7c..6c33b302d 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -559,7 +559,8 @@ proc genParForStmt(p: BProc, t: PNode) = initLocExpr(p, call.sons[1], rangeA) initLocExpr(p, call.sons[2], rangeB) - lineF(p, cpsStmts, "#pragma omp $4$n" & + # $n at the beginning because of #9710 + lineF(p, cpsStmts, "$n#pragma omp $4$n" & "for ($1 = $2; $1 <= $3; ++$1)", [forLoopVar.loc.rdLoc, rangeA.rdLoc, rangeB.rdLoc, diff --git a/testament/categories.nim b/testament/categories.nim index 6ab14a2cf..8bb89c0ae 100644 --- a/testament/categories.nim +++ b/testament/categories.nim @@ -553,3 +553,116 @@ proc processCategory(r: var TResults, cat: Category, options: string) = inc testsRun if testsRun == 0: echo "[Warning] - Invalid category specified \"", cat.string, "\", no tests were run" + + +const specialCategories = [ + "async", + "debugger", + "dll", + "examples", + "flags", + "gc", + "io", + "js", + "lib", + "longgc", + "manyloc", + "nimble-all", + "nimble-core", + "nimble-extra", + "niminaction", + "rodfiles", + "threads", + "untestable" +] + + +# these tests still have bugs. At some point when the bugs are fixd +# this should become empty. + +# exclude for various reasons +const specialDisabedTests = [ + "tests/dir with space/tspace.nim", # can't import dir with spaces. + "tests/method/tmultim.nim", # (77, 8) Error: method is not a base + "tests/system/talloc2.nim", # too much memory + "tests/collections/ttables.nim", # takes too long + "tests/system/tparams.nim", # executes itself with parameters + "tests/stdlib/tquit.nim", # not testing for obvious reasons + "tests/system/trealloc.nim", # out of memory + "tests/system/t7894.nim", # causes out of memory in later tests + "tests/types/tissues_types.nim", # causes out of memory with --gc:boehm +] + +proc parseAllSpecs(): void = + var specs: array[TTestAction, seq[TSpec]] + var specialTests = 0 + var ignoredTests = 0 + var specsWithCfg: seq[TSpec] + var specsWithCustomCmd: seq[TSpec] + var specsEarlyExit: seq[TSpec] + var specsWithInput: seq[TSpec] + + for file in os.walkFiles("tests/*/t*.nim"): + + let a = find(file, '/') + 1 + let b = find(file, '/', a) + let cat = file[a ..< b] + + if cat in specialCategories: + specialTests += 1 + continue + + if file in specialDisabedTests: + # a special ignore here. + continue + + let spec = parseSpec(file) + + #echo cat, ": ", file + if fileExists(file & ".cfg"): + specsWithCfg.add spec + continue + + if fileExists(parentDir(file) / "nim.cfg"): + specsWithCfg.add spec + continue + + if spec.cmd != cmdTemplate(): + specsWithCustomCmd.add spec + continue + + if spec.err == reIgnored: + ignoredTests += 1 + continue + + if spec.exitCode != 0: + specsEarlyExit.add spec + continue + + if spec.input != "": + specsWithInput.add spec + continue + + specs[spec.action].add spec + + for action, specs in specs.pairs: + echo action, ": ", specs.len + echo "specsWithCfg: ", specsWithCfg.len + echo "specsWithCustomCmd: ", specsWithCustomCmd.len + echo "earlyExit: ", specsEarlyExit.len + echo "special: ", specialTests + echo "ignored: ", ignoredTests + echo "withInput: ", specsWithInput.len + + var megatest: string + + for runSpec in specs[actionRun]: + if targetC in runSpec.targets or runSpec.targets == {}: + megatest.add "echo \"------------------------------: " + megatest.add runSpec.file + megatest.add "\"\n" + megatest.add "import \"" + megatest.add runSpec.file + megatest.add "\"\n" + + writeFile("megatest.nim", megatest) diff --git a/testament/specs.nim b/testament/specs.nim index 6c9fafa13..e3bc12376 100644 --- a/testament/specs.nim +++ b/testament/specs.nim @@ -22,7 +22,6 @@ type actionRun = "run" actionCompile = "compile" actionReject = "reject" - actionRunNoSpec = "runNoSpec" TOutputCheck* = enum ocIgnore = "ignore" diff --git a/testament/tester.nim b/testament/tester.nim index 7dfcf9d48..0d736fb3e 100644 --- a/testament/tester.nim +++ b/testament/tester.nim @@ -28,6 +28,7 @@ Command: c|cat|category run all the tests of a certain category r|run run single test file html generate $1 from the database + stats generate statistics about test cases Arguments: arguments are passed to the compiler Options: @@ -380,7 +381,7 @@ proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) = var given = callCompiler(expected.cmd, test.name, test.options, target, extraOptions=" --stdout --hint[Path]:off --hint[Processing]:off") compilerOutputTests(test, target, given, expected, r) - of actionRun, actionRunNoSpec: + of actionRun: # In this branch of code "early return" pattern is clearer than deep # nested conditionals - the empty rows in between to clarify the "danger" var given = callCompiler(expected.cmd, test.name, test.options, @@ -580,6 +581,8 @@ proc main() = processSingleTest(r, cat, p.cmdLineRest.string, file) of "html": generateHtml(resultsFile, optFailing) + of "stats": + parseAllSpecs() else: quit Usage diff --git a/tests/array/tarray.nim b/tests/array/tarray.nim index d12808668..96e90c97a 100644 --- a/tests/array/tarray.nim +++ b/tests/array/tarray.nim @@ -356,7 +356,7 @@ block troofregression: echo testStr[testStr.len - 8 .. testStr.len - 1] & "__" & testStr[0 .. testStr.len - pred(rot)] var - instructions = readFile(getAppDir() / "troofregression2.txt").split(',') + instructions = readFile(parentDir(currentSourcePath) / "troofregression2.txt").split(',') programs = "abcdefghijklmnop" proc dance(dancers: string): string = diff --git a/tests/async/tasyncfile.nim b/tests/async/tasyncfile.nim index 3043b680a..d95850c31 100644 --- a/tests/async/tasyncfile.nim +++ b/tests/async/tasyncfile.nim @@ -53,8 +53,7 @@ proc main() {.async.} = # Issue #7347 block: - let appDir = getAppDir() - var file = openAsync(appDir & DirSep & "hello.txt") + var file = openAsync( parentDir(currentSourcePath) / "hello.txt") echo file.getFileSize() echo await file.readAll() echo file.getFilePos() diff --git a/tests/ccgbugs/tconstobj.nim b/tests/ccgbugs/tconstobj.nim deleted file mode 100644 index 51cf661ee..000000000 --- a/tests/ccgbugs/tconstobj.nim +++ /dev/null @@ -1,16 +0,0 @@ -discard """ - output: '''(FirstName: "James", LastName: "Franco")''' -""" - -# bug #1547 -import tables - -type Person* = object - FirstName*: string - LastName*: string - -let people = { - "001": Person(FirstName: "James", LastName: "Franco") -}.toTable() - -echo people["001"] diff --git a/tests/collections/tsets.nim b/tests/collections/thashsets.nim similarity index 100% rename from tests/collections/tsets.nim rename to tests/collections/thashsets.nim diff --git a/tests/compilerapi/tcompilerapi.nim b/tests/compilerapi/tcompilerapi.nim index 30007eff0..2a7db04eb 100644 --- a/tests/compilerapi/tcompilerapi.nim +++ b/tests/compilerapi/tcompilerapi.nim @@ -15,7 +15,7 @@ import std / [os] proc main() = let std = findNimStdLibCompileTime() - var intr = createInterpreter("myscript.nim", [std, getAppDir()]) + var intr = createInterpreter("myscript.nim",[std, parentDir(currentSourcePath)]) intr.implementRoutine("*", "exposed", "addFloats", proc (a: VmArgs) = setResult(a, getFloat(a, 0) + getFloat(a, 1) + getFloat(a, 2)) ) @@ -51,4 +51,3 @@ block issue9180: evalString("echo 10+1") evalString("echo 10+2") - diff --git a/tests/concepts/trandom_vars.nim b/tests/concepts/trandomvars2.nim similarity index 100% rename from tests/concepts/trandom_vars.nim rename to tests/concepts/trandomvars2.nim diff --git a/tests/iter/tconcat.nim b/tests/iter/titerconcat.nim similarity index 100% rename from tests/iter/tconcat.nim rename to tests/iter/titerconcat.nim diff --git a/tests/macros/tgensym.nim b/tests/macros/tmacrogensym.nim similarity index 100% rename from tests/macros/tgensym.nim rename to tests/macros/tmacrogensym.nim diff --git a/tests/metatype/ttypeclasses.nim b/tests/metatype/tmeta_typeclasses.nim similarity index 100% rename from tests/metatype/ttypeclasses.nim rename to tests/metatype/tmeta_typeclasses.nim diff --git a/tests/metatype/tmatrix.nim b/tests/metatype/tmetatypematrix.nim similarity index 100% rename from tests/metatype/tmatrix.nim rename to tests/metatype/tmetatypematrix.nim diff --git a/tests/misc/tradix.nim b/tests/misc/tradix.nim index 5009dfcfb..e6dde73f6 100644 --- a/tests/misc/tradix.nim +++ b/tests/misc/tradix.nim @@ -126,7 +126,7 @@ proc excl*(r: PRadixNode, a: ByteAddress): bool = proc addLeaf(r: var PRadixNode, a: int): bool = if r == nil: # a linear node: - var x = cast[ptr TRadixNodeLinear](alloc(sizeof(TRadixNodeLinear))) + var x = cast[ptr TRadixNodeLinear](alloc0(sizeof(TRadixNodeLinear))) x.kind = rnLeafLinear x.len = 1'i8 x.keys[0] = toU8(a) @@ -162,7 +162,7 @@ proc addInner(r: var PRadixNode, a: int, d: int): bool = var k = a shr d and 0xff if r == nil: # a linear node: - var x = cast[ptr TRadixNodeLinear](alloc(sizeof(TRadixNodeLinear))) + var x = cast[ptr TRadixNodeLinear](alloc0(sizeof(TRadixNodeLinear))) x.kind = rnLinear x.len = 1'i8 x.keys[0] = toU8(k) @@ -246,99 +246,3 @@ proc main() = for x in elements(r): echo(x) main() - - -when false: - proc traverse(r: PRadixNode, prefix: int, d: int) = - if r == nil: return - case r.kind - of rnLeafBits: - assert(d == 0) - var x = cast[ptr TRadixNodeLeafBits](r) - # iterate over any bit: - for i in 0..high(x.b): - if x.b[i] != 0: # test all bits for zero - for j in 0..BitsPerUnit-1: - if testBit(x.b[i], j): - visit(prefix or i*BitsPerUnit+j) - of rnLeafLinear: - assert(d == 0) - var x = cast[ptr TRadixNodeLeafLinear](r) - for i in 0..ze(x.len)-1: - visit(prefix or ze(x.keys[i])) - of rnFull: - var x = cast[ptr TRadixNodeFull](r) - for i in 0..high(r.b): - if r.b[i] != nil: - traverse(r.b[i], prefix or (i shl d), d-8) - of rnLinear: - var x = cast[ptr TRadixNodeLinear](r) - for i in 0..ze(x.len)-1: - traverse(x.vals[i], prefix or (ze(x.keys[i]) shl d), d-8) - - type - TRadixIter {.final.} = object - r: PRadixNode - p: int - x: int - - proc init(i: var TRadixIter, r: PRadixNode) = - i.r = r - i.x = 0 - i.p = 0 - - proc nextr(i: var TRadixIter): PRadixNode = - if i.r == nil: return nil - case i.r.kind - of rnFull: - var r = cast[ptr TRadixNodeFull](i.r) - while i.x <= high(r.b): - if r.b[i.x] != nil: - i.p = i.x - return r.b[i.x] - inc(i.x) - of rnLinear: - var r = cast[ptr TRadixNodeLinear](i.r) - if i.x < ze(r.len): - i.p = ze(r.keys[i.x]) - result = r.vals[i.x] - inc(i.x) - else: assert(false) - - proc nexti(i: var TRadixIter): int = - result = -1 - case i.r.kind - of rnLeafBits: - var r = cast[ptr TRadixNodeLeafBits](i.r) - # iterate over any bit: - for i in 0..high(r.b): - if x.b[i] != 0: # test all bits for zero - for j in 0..BitsPerUnit-1: - if testBit(x.b[i], j): - visit(prefix or i*BitsPerUnit+j) - of rnLeafLinear: - var r = cast[ptr TRadixNodeLeafLinear](i.r) - if i.x < ze(r.len): - result = ze(r.keys[i.x]) - inc(i.x) - - iterator elements(r: PRadixNode): ByteAddress {.inline.} = - var - a, b, c, d: TRadixIter - init(a, r) - while true: - var x = nextr(a) - if x != nil: - init(b, x) - while true: - var y = nextr(b) - if y != nil: - init(c, y) - while true: - var z = nextr(c) - if z != nil: - init(d, z) - while true: - var q = nexti(d) - if q != -1: - yield a.p shl 24 or b.p shl 16 or c.p shl 8 or q diff --git a/tests/stdlib/tsqlparser.nim b/tests/stdlib/tsqlparser.nim index 4a7b2f7d7..11ee22e2b 100644 --- a/tests/stdlib/tsqlparser.nim +++ b/tests/stdlib/tsqlparser.nim @@ -6,7 +6,7 @@ discard """ import parsesql, streams, os -var tree = parseSql(newFileStream(getAppDir() / "somesql.sql"), "somesql") +var tree = parseSql(newFileStream(parentDir(currentSourcePath) / "somesql.sql"), "somesql") discard renderSql(tree) echo "true" diff --git a/tests/stdlib/tstdlib_various.nim b/tests/stdlib/tstdlib_various.nim index 7abc9a391..d1723df78 100644 --- a/tests/stdlib/tstdlib_various.nim +++ b/tests/stdlib/tstdlib_various.nim @@ -219,7 +219,7 @@ block tsplit2: block tsqlparser: # Just check that we can parse 'somesql' and render it without crashes. - var tree = parseSql(newFileStream(getAppDir() / "somesql.sql"), "somesql") + var tree = parseSql(newFileStream( parentDir(currentSourcePath) / "somesql.sql"), "somesql") discard renderSql(tree) diff --git a/tests/system/tostring.nim b/tests/system/tostring.nim index 04b37f133..ea4a44417 100644 --- a/tests/system/tostring.nim +++ b/tests/system/tostring.nim @@ -1,5 +1,5 @@ discard """ - output: "" + output: "DONE: tostring.nim" """ doAssert "@[23, 45]" == $(@[23, 45]) @@ -115,3 +115,6 @@ block: var s: string s.addQuoted a2 doAssert s == "\"fo\\\"o2\"" + + +echo "DONE: tostring.nim" diff --git a/tests/types/tissues.nim b/tests/types/tissues_types.nim similarity index 100% rename from tests/types/tissues.nim rename to tests/types/tissues_types.nim diff --git a/tests/vm/tconstobj.nim b/tests/vm/tconstobj.nim index 38fcdd844..021fcb728 100644 --- a/tests/vm/tconstobj.nim +++ b/tests/vm/tconstobj.nim @@ -1,10 +1,12 @@ discard """ - output: '''(name: "hello") -(-1, 0)''' + output: ''' +(name: "hello") +(-1, 0) +(FirstName: "James", LastName: "Franco") +''' """ # bug #2774, bug #3195 - type Foo = object name: string @@ -14,7 +16,6 @@ const fooArray = [ echo fooArray[0] - type Position = object x, y: int @@ -34,3 +35,16 @@ const ] echo offset[1] + +# bug #1547 +import tables + +type Person* = object + FirstName*: string + LastName*: string + +let people = { + "001": Person(FirstName: "James", LastName: "Franco") +}.toTable() + +echo people["001"] diff --git a/tests/vm/tmitems.nim b/tests/vm/tmitems_vm.nim similarity index 100% rename from tests/vm/tmitems.nim rename to tests/vm/tmitems_vm.nim diff --git a/tests/vm/tvmmisc.nim b/tests/vm/tvmmisc.nim index 85de26e39..35deea224 100644 --- a/tests/vm/tvmmisc.nim +++ b/tests/vm/tvmmisc.nim @@ -70,7 +70,8 @@ block: # Tests for VM ops block: static: - assert "vm" in getProjectPath() + # for joint test, the project path is different + assert "vm" in getProjectPath() or "Nim" in getProjectPath() let b = getEnv("UNSETENVVAR") assert b == "" From 3859878db8e6da15d3513c931e0d811dcf03b250 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arne=20D=C3=B6ring?= Date: Wed, 5 Dec 2018 00:42:56 +0100 Subject: [PATCH 078/110] megatest checks output and nimout --- testament/categories.nim | 60 ++++++++++-- testament/specs.nim | 6 +- testament/tester.nim | 16 ++-- tests/ccgbugs/tmissinginit.nim | 2 +- tests/ccgbugs/tobjconstr_bad_aliasing.nim | 3 +- tests/concepts/trandomvars.nim | 4 +- tests/errmsgs/treportunused.nim | 1 + tests/generics/tgeneric3.nim | 89 ++++++++--------- tests/generics/tgenericvariant.nim | 4 +- tests/generics/tparser_generator.nim | 27 +++--- tests/generics/trtree.nim | 112 +++++++++++----------- tests/misc/tshadow_magic_type.nim | 7 +- tests/objects/tobjconstr.nim | 31 +++--- tests/overload/toverload_issues.nim | 36 ++++--- tests/stdlib/tnativesockets.nim | 11 --- tests/typerel/texplicitcmp.nim | 11 +-- 16 files changed, 218 insertions(+), 202 deletions(-) delete mode 100644 tests/stdlib/tnativesockets.nim diff --git a/testament/categories.nim b/testament/categories.nim index 8bb89c0ae..978719307 100644 --- a/testament/categories.nim +++ b/testament/categories.nim @@ -591,9 +591,10 @@ const specialDisabedTests = [ "tests/system/trealloc.nim", # out of memory "tests/system/t7894.nim", # causes out of memory in later tests "tests/types/tissues_types.nim", # causes out of memory with --gc:boehm + "tests/pragmas/tused.nim", # paths in nimout differ when imported ] -proc parseAllSpecs(): void = +proc runJoinedTest(): void = var specs: array[TTestAction, seq[TSpec]] var specialTests = 0 var ignoredTests = 0 @@ -601,6 +602,7 @@ proc parseAllSpecs(): void = var specsWithCustomCmd: seq[TSpec] var specsEarlyExit: seq[TSpec] var specsWithInput: seq[TSpec] + var specsNonCtarget: seq[TSpec] for file in os.walkFiles("tests/*/t*.nim"): @@ -643,6 +645,10 @@ proc parseAllSpecs(): void = specsWithInput.add spec continue + if card(spec.targets) > 0 and spec.targets != {targetC}: + specsNonCtarget.add spec + continue + specs[spec.action].add spec for action, specs in specs.pairs: @@ -653,16 +659,52 @@ proc parseAllSpecs(): void = echo "special: ", specialTests echo "ignored: ", ignoredTests echo "withInput: ", specsWithInput.len + echo "nonCtarget: ", specsNonCtarget.len var megatest: string - for runSpec in specs[actionRun]: - if targetC in runSpec.targets or runSpec.targets == {}: - megatest.add "echo \"------------------------------: " - megatest.add runSpec.file - megatest.add "\"\n" - megatest.add "import \"" - megatest.add runSpec.file - megatest.add "\"\n" + megatest.add "import \"" + megatest.add runSpec.file + megatest.add "\"\n" writeFile("megatest.nim", megatest) + + let args = ["c", "-d:testing", "--gc:boehm", "megatest.nim"] + var (buf, exitCode) = execCmdEx2(command = "nim", args = args, options = {poStdErrToStdOut, poUsePath}, input = "") + if exitCode != 0: + quit("megatest compilation failed") + + echo "compilation ok" + + var nimoutOK = true + for runSpec in specs[actionRun]: + for line in runSpec.nimout.splitLines: + if buf.find(line) < 0: + echo "could not find: ", line + echo runSpec.file + nimoutOK = false + + if nimoutOK: + echo "nimout OK" + else: + echo "nimout FAIL" + + (buf, exitCode) = execCmdEx2("./megatest", [], {}, "") + if exitCode != 0: + quit("megatest execution failed") + + echo "run ok" + + var outputOK = true + for runSpec in specs[actionRun]: + for line in runSpec.output.splitLines: + if buf.find(line) < 0: + echo "could not find: ", line + echo runSpec.file + outputOK = false + if outputOK: + echo "output OK" + else: + echo "output FAIL" + + removeFile("megatest.nim") diff --git a/testament/specs.nim b/testament/specs.nim index e3bc12376..e3ad3a4ff 100644 --- a/testament/specs.nim +++ b/testament/specs.nim @@ -57,7 +57,7 @@ type input*: string outputCheck*: TOutputCheck sortoutput*: bool - outp*: string + output*: string line*, column*: int tfile*: string tline*, tcolumn*: int @@ -161,12 +161,12 @@ proc parseSpec*(filename: string): TSpec = discard parseInt(e.value, result.tcolumn) of "output": result.outputCheck = ocEqual - result.outp = strip(e.value) + result.output = strip(e.value) of "input": result.input = e.value of "outputsub": result.outputCheck = ocSubstr - result.outp = strip(e.value) + result.output = strip(e.value) of "sortoutput": try: result.sortoutput = parseCfgBool(e.value) diff --git a/testament/tester.nim b/testament/tester.nim index 0d736fb3e..73aae0bc7 100644 --- a/testament/tester.nim +++ b/testament/tester.nim @@ -141,7 +141,7 @@ proc callCompiler(cmdTemplate, filename, options: string, close(p) result.msg = "" result.file = "" - result.outp = "" + result.output = "" result.line = 0 result.column = 0 result.tfile = "" @@ -173,7 +173,7 @@ proc callCCompiler(cmdTemplate, filename, options: string, result.nimout = "" result.msg = "" result.file = "" - result.outp = "" + result.output = "" result.line = -1 while outp.readLine(x.TaintedString) or running(p): result.nimout.add(x & "\n") @@ -400,12 +400,12 @@ proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) = exeFile = changeFileExt(test.name, ExeExt) if not existsFile(exeFile): - r.addResult(test, target, expected.outp, "executable not found", reExeNotFound) + r.addResult(test, target, expected.output, "executable not found", reExeNotFound) continue let nodejs = if isJsTarget: findNodeJs() else: "" if isJsTarget and nodejs == "": - r.addResult(test, target, expected.outp, "nodejs binary not in PATH", + r.addResult(test, target, expected.output, "nodejs binary not in PATH", reExeNotFound) continue @@ -438,10 +438,10 @@ proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) = bufB, reExitCodesDiffer) continue - if (expected.outputCheck == ocEqual and expected.outp != bufB) or - (expected.outputCheck == ocSubstr and expected.outp notin bufB): + if (expected.outputCheck == ocEqual and expected.output != bufB) or + (expected.outputCheck == ocSubstr and expected.output notin bufB): given.err = reOutputsDiffer - r.addResult(test, target, expected.outp, bufB, reOutputsDiffer) + r.addResult(test, target, expected.output, bufB, reOutputsDiffer) continue compilerOutputTests(test, target, given, expected, r) @@ -582,7 +582,7 @@ proc main() = of "html": generateHtml(resultsFile, optFailing) of "stats": - parseAllSpecs() + runJoinedTest() else: quit Usage diff --git a/tests/ccgbugs/tmissinginit.nim b/tests/ccgbugs/tmissinginit.nim index b4087008a..8806a2f21 100644 --- a/tests/ccgbugs/tmissinginit.nim +++ b/tests/ccgbugs/tmissinginit.nim @@ -27,4 +27,4 @@ echo bug()[0] echo bug()[0] echo bug()[0] -when isMainModule: test() +test() diff --git a/tests/ccgbugs/tobjconstr_bad_aliasing.nim b/tests/ccgbugs/tobjconstr_bad_aliasing.nim index ea51ecacb..9f6045364 100644 --- a/tests/ccgbugs/tobjconstr_bad_aliasing.nim +++ b/tests/ccgbugs/tobjconstr_bad_aliasing.nim @@ -22,5 +22,4 @@ proc dosomething(): seq[TThing] = result = @[TThing(data: 10, children: result)] -when isMainModule: - echo($dosomething()[0]) +echo($dosomething()[0]) diff --git a/tests/concepts/trandomvars.nim b/tests/concepts/trandomvars.nim index db41aa901..1f04b9ecf 100644 --- a/tests/concepts/trandomvars.nim +++ b/tests/concepts/trandomvars.nim @@ -41,7 +41,8 @@ proc lift1[A, B](f: proc(a: A): B, r: RandomVar[A]): ClosureVar[B] = return inner -when isMainModule: + +proc main() = proc sq(x: float): float = x * x let @@ -59,3 +60,4 @@ when isMainModule: echo rng.sample(u) echo rng.sample(t) +main() diff --git a/tests/errmsgs/treportunused.nim b/tests/errmsgs/treportunused.nim index 929da8843..f83ad5633 100644 --- a/tests/errmsgs/treportunused.nim +++ b/tests/errmsgs/treportunused.nim @@ -12,6 +12,7 @@ treportunused.nim(27, 5) Hint: 's9' is declared but not used [XDeclaredButNotUse treportunused.nim(21, 10) Hint: 's3' is declared but not used [XDeclaredButNotUsed] treportunused.nim(28, 6) Hint: 's10' is declared but not used [XDeclaredButNotUsed] ''' +action: compile """ # bug #9764 diff --git a/tests/generics/tgeneric3.nim b/tests/generics/tgeneric3.nim index 34b415446..4cb12f91b 100644 --- a/tests/generics/tgeneric3.nim +++ b/tests/generics/tgeneric3.nim @@ -430,55 +430,50 @@ iterator keys* [T,D] (n: PNode[T,D]): T = i = Path[level].Xi inc(i) +proc test() = + var oldvalue: int + var root = internalPut[int, int](nil, 312, 312, oldvalue) + var someOtherRoot = internalPut[string, int](nil, "312", 312, oldvalue) + var it1 = internalFind(root, 312) + echo it1.value -when isMainModule: + for i in 1..1_000_000: + root = internalPut(root, i, i, oldvalue) - proc test() = - var oldvalue: int - var root = internalPut[int, int](nil, 312, 312, oldvalue) - var someOtherRoot = internalPut[string, int](nil, "312", 312, oldvalue) - var it1 = internalFind(root, 312) - echo it1.value - - for i in 1..1_000_000: - root = internalPut(root, i, i, oldvalue) - - var cnt = 0 - oldvalue = -1 - when true : # code compiles, when this or the other when is switched to false - for k in root.keys : - if k <= oldvalue : - echo k - oldvalue = k - inc(cnt) - echo cnt + var cnt = 0 + oldvalue = -1 + when true : # code compiles, when this or the other when is switched to false + for k in root.keys : + if k <= oldvalue : + echo k + oldvalue = k + inc(cnt) + echo cnt + when true : + cnt = 0 + VisitAll(root, proc(key, val: int) = inc(cnt)) + echo cnt when true : - cnt = 0 - VisitAll(root, proc(key, val: int) = inc(cnt)) - echo cnt - when true : - root = VisitAll(root, proc(key: int, value: var int): bool = - return key mod 2 == 0 ) - cnt = 0 - oldvalue = -1 - VisitAll(root, proc(key: int, value: int) {.closure.} = - if key <= oldvalue : - echo key - oldvalue = key - inc(cnt) ) - echo cnt root = VisitAll(root, proc(key: int, value: var int): bool = - return key mod 2 != 0 ) - cnt = 0 - oldvalue = -1 - VisitAll(root, proc(key: int, value: int) {.closure.} = - if key <= oldvalue : - echo "error ", key - oldvalue = key - inc(cnt) ) - echo cnt - #traceTree(root) + return key mod 2 == 0 ) + cnt = 0 + oldvalue = -1 + VisitAll(root, proc(key: int, value: int) {.closure.} = + if key <= oldvalue : + echo key + oldvalue = key + inc(cnt) ) + echo cnt + root = VisitAll(root, proc(key: int, value: var int): bool = + return key mod 2 != 0 ) + cnt = 0 + oldvalue = -1 + VisitAll(root, proc(key: int, value: int) {.closure.} = + if key <= oldvalue : + echo "error ", key + oldvalue = key + inc(cnt) ) + echo cnt + #traceTree(root) - - - test() +test() diff --git a/tests/generics/tgenericvariant.nim b/tests/generics/tgenericvariant.nim index 73c8af825..5ba3a2e7c 100644 --- a/tests/generics/tgenericvariant.nim +++ b/tests/generics/tgenericvariant.nim @@ -26,9 +26,11 @@ proc safeReadLine(): TMaybe[string] = if r == "": return Nothing[string]() else: return Just(r) -when isMainModule: +proc main() = var Test = Just("Test") echo(Test.value) var mSomething = safeReadLine() echo(mSomething.value) mSomething = safeReadLine() + +main() diff --git a/tests/generics/tparser_generator.nim b/tests/generics/tparser_generator.nim index 01ddd29b8..a94506d62 100644 --- a/tests/generics/tparser_generator.nim +++ b/tests/generics/tparser_generator.nim @@ -397,19 +397,18 @@ template grammar*[K](Kind, Text, Symbol: typedesc; default: K, code: untyped): t template grammar*[K](Kind: typedesc; default: K, code: untyped): typed {.hint[XDeclaredButNotUsed]: off.} = grammar(Kind, string, char, default, code) -when isMainModule: - block: - type DummyKind = enum dkDefault - grammar(DummyKind, string, char, dkDefault): - let rule = token("h[a]+m") + ignore(token(r"\s+")) + (literal("eggs") / literal("beans")) - var text = "ham beans" - discard rule.parse(text) +block: + type DummyKind = enum dkDefault + grammar(DummyKind, string, char, dkDefault): + let rule = token("h[a]+m") + ignore(token(r"\s+")) + (literal("eggs") / literal("beans")) + var text = "ham beans" + discard rule.parse(text) - var recursive = newRule() - recursive -> (literal("(") + recursive + literal(")")) / token(r"\d+") - for test in ["spam", "57", "(25)", "((25))"]: - discard recursive.parse(test) + var recursive = newRule() + recursive -> (literal("(") + recursive + literal(")")) / token(r"\d+") + for test in ["spam", "57", "(25)", "((25))"]: + discard recursive.parse(test) - let repeated = +literal("spam") + ?literal("ham") + *literal("salami") - for test in ["ham", "spam", "spamspamspam" , "spamham", "spamsalami", "spamsalamisalami"]: - discard repeated.parse(test) + let repeated = +literal("spam") + ?literal("ham") + *literal("salami") + for test in ["ham", "spam", "spamspamspam" , "spamham", "spamsalami", "spamsalamisalami"]: + discard repeated.parse(test) diff --git a/tests/generics/trtree.nim b/tests/generics/trtree.nim index 321b31df6..3fb080335 100644 --- a/tests/generics/trtree.nim +++ b/tests/generics/trtree.nim @@ -589,70 +589,68 @@ proc delete*[M, D: Dim; RT, LT](t: RTree[M, D, RT, LT]; leaf: L[D, RT, LT]): boo t.root.parent = nil return true -when isMainModule: - var t = [4, 1, 3, 2] - var xt = 7 - sortPlus(t, xt, system.cmp, SortOrder.Ascending) - echo xt, " ", t +var t = [4, 1, 3, 2] +var xt = 7 +sortPlus(t, xt, system.cmp, SortOrder.Ascending) +echo xt, " ", t - type - RSE = L[2, int, int] - RSeq = seq[RSE] +type + RSE = L[2, int, int] + RSeq = seq[RSE] - proc rseq_search(rs: RSeq; rse: RSE): seq[int] = - result = newSeq[int]() - for i in rs: - if intersect(i.b, rse.b): - result.add(i.l) +proc rseq_search(rs: RSeq; rse: RSE): seq[int] = + result = newSeq[int]() + for i in rs: + if intersect(i.b, rse.b): + result.add(i.l) - proc rseq_delete(rs: var RSeq; rse: RSE): bool = - for i in 0 .. rs.high: - if rs[i] == rse: - #rs.delete(i) - rs[i] = rs[rs.high] - rs.setLen(rs.len - 1) - return true +proc rseq_delete(rs: var RSeq; rse: RSE): bool = + for i in 0 .. rs.high: + if rs[i] == rse: + #rs.delete(i) + rs[i] = rs[rs.high] + rs.setLen(rs.len - 1) + return true - import random, algorithm +import random, algorithm - proc test(n: int) = - var b: Box[2, int] - echo center(b) - var x1, x2, y1, y2: int - var t = newRStarTree[8, 2, int, int]() - #var t = newRTree[8, 2, int, int]() - var rs = newSeq[RSE]() - for i in 0 .. 5: - for i in 0 .. n - 1: - x1 = rand(1000) - y1 = rand(1000) - x2 = x1 + rand(25) - y2 = y1 + rand(25) - b = [(x1, x2), (y1, y2)] - let el: L[2, int, int] = (b, i + 7) - t.insert(el) - rs.add(el) +proc test(n: int) = + var b: Box[2, int] + echo center(b) + var x1, x2, y1, y2: int + var t = newRStarTree[8, 2, int, int]() + #var t = newRTree[8, 2, int, int]() + var rs = newSeq[RSE]() + for i in 0 .. 5: + for i in 0 .. n - 1: + x1 = rand(1000) + y1 = rand(1000) + x2 = x1 + rand(25) + y2 = y1 + rand(25) + b = [(x1, x2), (y1, y2)] + let el: L[2, int, int] = (b, i + 7) + t.insert(el) + rs.add(el) - for i in 0 .. (n div 4): - let j = rand(rs.high) - var el = rs[j] - assert t.delete(el) - assert rs.rseq_delete(el) + for i in 0 .. (n div 4): + let j = rand(rs.high) + var el = rs[j] + assert t.delete(el) + assert rs.rseq_delete(el) - for i in 0 .. n - 1: - x1 = rand(1000) - y1 = rand(1000) - x2 = x1 + rand(100) - y2 = y1 + rand(100) - b = [(x1, x2), (y1, y2)] - let el: L[2, int, int] = (b, i) - let r = search(t, b) - let r2 = rseq_search(rs, el) - assert r.len == r2.len - assert r.sorted(system.cmp) == r2.sorted(system.cmp) + for i in 0 .. n - 1: + x1 = rand(1000) + y1 = rand(1000) + x2 = x1 + rand(100) + y2 = y1 + rand(100) + b = [(x1, x2), (y1, y2)] + let el: L[2, int, int] = (b, i) + let r = search(t, b) + let r2 = rseq_search(rs, el) + assert r.len == r2.len + assert r.sorted(system.cmp) == r2.sorted(system.cmp) - test(1500) - - # 651 lines +test(1500) +# 651 lines diff --git a/tests/misc/tshadow_magic_type.nim b/tests/misc/tshadow_magic_type.nim index 6f9716bb9..3176a4596 100644 --- a/tests/misc/tshadow_magic_type.nim +++ b/tests/misc/tshadow_magic_type.nim @@ -26,7 +26,6 @@ proc lrange*(key: string): TRedisList = foo.str = key result = @[foo] -when isMainModule: - var p = lrange("mylist") - for i in items(p): - echo(i.str) +var p = lrange("mylist") +for i in items(p): + echo(i.str) diff --git a/tests/objects/tobjconstr.nim b/tests/objects/tobjconstr.nim index 7238d10c7..1e4d89d68 100644 --- a/tests/objects/tobjconstr.nim +++ b/tests/objects/tobjconstr.nim @@ -1,14 +1,15 @@ discard """ - output: '''(k: kindA, a: (x: "abc", z: [1, 1, 3]), method: ()) -(k: kindA, a: (x: "abc", z: [1, 2, 3]), method: ()) -(k: kindA, a: (x: "abc", z: [1, 3, 3]), method: ()) -(k: kindA, a: (x: "abc", z: [1, 4, 3]), method: ()) -(k: kindA, a: (x: "abc", z: [1, 5, 3]), method: ()) -(k: kindA, a: (x: "abc", z: [1, 6, 3]), method: ()) -(k: kindA, a: (x: "abc", z: [1, 7, 3]), method: ()) -(k: kindA, a: (x: "abc", z: [1, 8, 3]), method: ()) -(k: kindA, a: (x: "abc", z: [1, 9, 3]), method: ()) -(k: kindA, a: (x: "abc", z: [1, 10, 3]), method: ()) + output: ''' +(k: kindA, a: (x: "abc", z: @[1, 1, 3]), method: ()) +(k: kindA, a: (x: "abc", z: @[1, 2, 3]), method: ()) +(k: kindA, a: (x: "abc", z: @[1, 3, 3]), method: ()) +(k: kindA, a: (x: "abc", z: @[1, 4, 3]), method: ()) +(k: kindA, a: (x: "abc", z: @[1, 5, 3]), method: ()) +(k: kindA, a: (x: "abc", z: @[1, 6, 3]), method: ()) +(k: kindA, a: (x: "abc", z: @[1, 7, 3]), method: ()) +(k: kindA, a: (x: "abc", z: @[1, 8, 3]), method: ()) +(k: kindA, a: (x: "abc", z: @[1, 9, 3]), method: ()) +(k: kindA, a: (x: "abc", z: @[1, 10, 3]), method: ()) (y: 0, x: 123) (y: 678, x: 123) (z: 89, y: 0, x: 128) @@ -16,7 +17,8 @@ discard """ (y: 678, x: 123) (y: 0, x: 123) (y: 678, x: 123) -(y: 123, x: 678)''' +(y: 123, x: 678) +''' """ type @@ -32,13 +34,6 @@ type a: TArg `method`: TEmpty # bug #1791 -proc `$`[T](s: seq[T]): string = - result = "[" - for i, x in s: - if i > 0: result.add(", ") - result.add($x) - result.add("]") - proc main() = for i in 1..10: let d = TDummy(k: kindA, a: TArg(x: "abc", z: @[1,i,3]), `method`: TEmpty()) diff --git a/tests/overload/toverload_issues.nim b/tests/overload/toverload_issues.nim index 7980f51a9..fe1603a44 100644 --- a/tests/overload/toverload_issues.nim +++ b/tests/overload/toverload_issues.nim @@ -119,28 +119,24 @@ template test(loopCount: int, testBody: untyped): typed = test(loopCount, 0, testBody) echo "done extraI passed 0" -when isMainModule: - var - loops = 0 +var + loops = 0 - test 0, 0: +test 0, 0: + loops += 1 +echo "test 0 complete, loops=", loops + +test 1, 1.0: + loops += 1 +echo "test 1.0 complete, loops=", loops + +when true: + # when true we get the following compile time error: + # b.nim(35, 6) Error: expression 'loops += 1' has no type (or is ambiguous) + loops = 0 + test 2: loops += 1 - echo "test 0 complete, loops=", loops - - test 1, 1.0: - loops += 1 - echo "test 1.0 complete, loops=", loops - - when true: - # when true we get the following compile time error: - # b.nim(35, 6) Error: expression 'loops += 1' has no type (or is ambiguous) - loops = 0 - test 2: - loops += 1 - echo "test no extra complete, loops=", loops - - - + echo "test no extra complete, loops=", loops # bug #2229 type diff --git a/tests/stdlib/tnativesockets.nim b/tests/stdlib/tnativesockets.nim deleted file mode 100644 index c2738b8a5..000000000 --- a/tests/stdlib/tnativesockets.nim +++ /dev/null @@ -1,11 +0,0 @@ -discard """ -outputsub: "" -""" - -import nativesockets, unittest - -suite "nativesockets": - test "getHostname": - let hostname = getHostname() - check hostname.len > 0 - check hostname.len < 64 diff --git a/tests/typerel/texplicitcmp.nim b/tests/typerel/texplicitcmp.nim index e91ac2ffe..b11aa2f4e 100644 --- a/tests/typerel/texplicitcmp.nim +++ b/tests/typerel/texplicitcmp.nim @@ -24,9 +24,8 @@ proc weird(json_params: Table) = sort(f, system.cmp[int]) outp(f) -when isMainModule: - var t = @[3, 2, 1] - sort(t, system.cmp[int]) - outp(t) - works() - weird(initTable[string, JsonNode]()) +var t = @[3, 2, 1] +sort(t, system.cmp[int]) +outp(t) +works() +weird(initTable[string, JsonNode]()) From c0c35839cc65717283edda72ce34579b992563ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arne=20D=C3=B6ring?= Date: Wed, 5 Dec 2018 01:15:12 +0100 Subject: [PATCH 079/110] megatest integrated in default test all --- testament/categories.nim | 109 ++++++++++++++++++--------------------- testament/tester.nim | 6 ++- 2 files changed, 54 insertions(+), 61 deletions(-) diff --git a/testament/categories.nim b/testament/categories.nim index 978719307..48aa5844c 100644 --- a/testament/categories.nim +++ b/testament/categories.nim @@ -497,7 +497,9 @@ proc processSingleTest(r: var TResults, cat: Category, options, test: string) = testSpec r, makeTest(test, options, cat), {target} else: echo "[Warning] - ", test, " test does not exist" -proc processCategory(r: var TResults, cat: Category, options: string) = +proc isJoinableSpec(spec: TSpec): bool + +proc processCategory(r: var TResults, cat: Category, options: string, runJoinableTests: bool) = case cat.string.normalize of "rodfiles": when false: @@ -549,7 +551,11 @@ proc processCategory(r: var TResults, cat: Category, options: string) = else: var testsRun = 0 for name in os.walkFiles("tests" & DirSep &.? cat.string / "t*.nim"): - testSpec r, makeTest(name, options, cat) + let test = makeTest(name, options, cat) + if runJoinableTests or not isJoinableSpec(test.spec): + testSpec r, test + else: + echo "filter out: ", test.name inc testsRun if testsRun == 0: echo "[Warning] - Invalid category specified \"", cat.string, "\", no tests were run" @@ -594,75 +600,58 @@ const specialDisabedTests = [ "tests/pragmas/tused.nim", # paths in nimout differ when imported ] -proc runJoinedTest(): void = - var specs: array[TTestAction, seq[TSpec]] - var specialTests = 0 - var ignoredTests = 0 - var specsWithCfg: seq[TSpec] - var specsWithCustomCmd: seq[TSpec] - var specsEarlyExit: seq[TSpec] - var specsWithInput: seq[TSpec] - var specsNonCtarget: seq[TSpec] +proc isJoinableSpec(spec: TSpec): bool = + if spec.action != actionRun: + return false + + if spec.file in specialDisabedTests: + return false + + if fileExists(spec.file & ".cfg"): + return false + + if fileExists(parentDir(spec.file) / "nim.cfg"): + return false + + if spec.cmd != cmdTemplate(): + return false + + if spec.err == reIgnored: + return false + + if spec.exitCode != 0: + return false + + if spec.input != "": + return false + + if spec.targets != {} and spec.targets != {targetC}: + return false + + return true + + +proc runJoinedTest(): bool = + ## returs a list of tests that have problems + var specs:seq[TSpec] for file in os.walkFiles("tests/*/t*.nim"): - let a = find(file, '/') + 1 let b = find(file, '/', a) let cat = file[a ..< b] if cat in specialCategories: - specialTests += 1 - continue - - if file in specialDisabedTests: - # a special ignore here. continue let spec = parseSpec(file) - #echo cat, ": ", file - if fileExists(file & ".cfg"): - specsWithCfg.add spec - continue + if isJoinableSpec(spec): + specs.add spec - if fileExists(parentDir(file) / "nim.cfg"): - specsWithCfg.add spec - continue - - if spec.cmd != cmdTemplate(): - specsWithCustomCmd.add spec - continue - - if spec.err == reIgnored: - ignoredTests += 1 - continue - - if spec.exitCode != 0: - specsEarlyExit.add spec - continue - - if spec.input != "": - specsWithInput.add spec - continue - - if card(spec.targets) > 0 and spec.targets != {targetC}: - specsNonCtarget.add spec - continue - - specs[spec.action].add spec - - for action, specs in specs.pairs: - echo action, ": ", specs.len - echo "specsWithCfg: ", specsWithCfg.len - echo "specsWithCustomCmd: ", specsWithCustomCmd.len - echo "earlyExit: ", specsEarlyExit.len - echo "special: ", specialTests - echo "ignored: ", ignoredTests - echo "withInput: ", specsWithInput.len - echo "nonCtarget: ", specsNonCtarget.len + echo "joinable specs: ", specs.len var megatest: string - for runSpec in specs[actionRun]: + for runSpec in specs: megatest.add "import \"" megatest.add runSpec.file megatest.add "\"\n" @@ -677,7 +666,7 @@ proc runJoinedTest(): void = echo "compilation ok" var nimoutOK = true - for runSpec in specs[actionRun]: + for runSpec in specs: for line in runSpec.nimout.splitLines: if buf.find(line) < 0: echo "could not find: ", line @@ -696,7 +685,7 @@ proc runJoinedTest(): void = echo "run ok" var outputOK = true - for runSpec in specs[actionRun]: + for runSpec in specs: for line in runSpec.output.splitLines: if buf.find(line) < 0: echo "could not find: ", line @@ -708,3 +697,5 @@ proc runJoinedTest(): void = echo "output FAIL" removeFile("megatest.nim") + + return nimoutOK and outputOK diff --git a/testament/tester.nim b/testament/tester.nim index 73aae0bc7..11489e7a6 100644 --- a/testament/tester.nim +++ b/testament/tester.nim @@ -553,6 +553,8 @@ proc main() = var r = initResults() case action of "all": + doAssert runJoinedTest() + let testsDir = "tests" & DirSep var myself = quoteShell(findExe("testament" / "tester")) if targetsStr.len > 0: @@ -573,7 +575,7 @@ proc main() = of "c", "cat", "category": var cat = Category(p.key) p.next - processCategory(r, cat, p.cmdLineRest.string) + processCategory(r, cat, p.cmdLineRest.string, runJoinableTests = false) of "r", "run": let (dir, file) = splitPath(p.key.string) let (_, subdir) = splitPath(dir) @@ -582,7 +584,7 @@ proc main() = of "html": generateHtml(resultsFile, optFailing) of "stats": - runJoinedTest() + discard runJoinedTest() else: quit Usage From a5ecbf823f178c2800d40bcff562bc4eca0f2030 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arne=20D=C3=B6ring?= Date: Wed, 5 Dec 2018 19:03:01 +0100 Subject: [PATCH 080/110] lots of small changes --- .gitignore | 3 + testament/categories.nim | 73 ++++++++++++++++--- testament/specs.nim | 5 +- testament/tester.nim | 3 + tests/async/t7192.nim | 2 +- tests/async/tasyncexceptions.nim | 2 +- tests/async/tasyncrecursion.nim | 2 +- tests/bind/tdatabind.nim | 2 +- tests/ccgbugs/t8616.nim | 2 +- tests/ccgbugs/t8781.nim | 2 +- tests/ccgbugs/tgeneric_closure.nim | 2 +- tests/ccgbugs/tgeneric_smallobj_asgn_opt.nim | 5 +- tests/ccgbugs/tmarkerproc_regression.nim | 4 +- tests/ccgbugs/tmissingbracket.nim | 7 +- tests/collections/ttables.nim | 4 +- tests/deps/jester-#head/jester/patterns.nim | 2 +- .../jester-#head/jester/private/utils.nim | 2 +- tests/deps/zip-0.2.1/zip/zipfiles.nim | 2 +- tests/destructor/tmove_objconstr.nim | 2 +- .../turn_destroy_into_finalizer.nim | 7 +- tests/discard/tdiscardable.nim | 3 + tests/distinct/tdistinct.nim | 6 +- tests/errmsgs/t6483.nim | 2 +- tests/errmsgs/tproper_stacktrace.nim | 2 +- tests/errmsgs/treportunused.nim | 1 - tests/generics/tbintree.nim | 2 +- tests/generics/toverloading_typedesc.nim | 2 +- tests/generics/tthread_generic.nim | 2 +- tests/generics/twrong_floatlit_type.nim | 2 +- tests/implicit/timplicit.nim | 5 +- tests/iter/titer10.nim | 2 +- tests/js/tvarargs.nim | 2 +- tests/macros/tmacro4.nim | 2 +- .../argument_parser/argument_parser.nim | 2 +- tests/manyloc/argument_parser/ex_wget.nim | 2 +- .../dependencies/genpacket/genpacket.nim | 2 +- .../dependencies/genpacket/genpacket_enet.nim | 2 +- .../dependencies/genpacket/macro_dsl.nim | 2 +- .../dependencies/genpacket/streams_enh.nim | 2 +- .../keineschweine/dependencies/nake/nake.nim | 2 +- .../keineschweine/enet_server/enet_server.nim | 2 +- tests/manyloc/keineschweine/keineschweine.nim | 2 +- tests/manyloc/keineschweine/lib/estreams.nim | 2 +- .../manyloc/keineschweine/lib/map_filter.nim | 2 +- .../manyloc/keineschweine/lib/sg_packets.nim | 2 +- .../keineschweine/lib/zlib_helpers.nim | 2 +- .../keineschweine/server/old_dirserver.nim | 2 +- .../keineschweine/server/old_sg_server.nim | 2 +- tests/manyloc/nake/nake.nim | 2 +- tests/misc/thallo.nim | 4 +- tests/misc/tradix.nim | 3 + tests/misc/tsortdev.nim | 5 +- .../Chapter3/ChatApp/src/protocol.nim | 2 +- .../Chapter3/ChatApp/src/server.nim | 2 +- .../Chapter6/WikipediaStats/concurrency.nim | 2 +- .../WikipediaStats/concurrency_regex.nim | 2 +- .../Chapter6/WikipediaStats/naive.nim | 2 +- .../WikipediaStats/parallel_counts.nim | 2 +- .../WikipediaStats/sequential_counts.nim | 2 +- .../Chapter7/Tweeter/src/views/user.nim | 2 +- .../Chapter7/Tweeter/tests/database_test.nim | 2 +- tests/osproc/ta_out.nim | 6 ++ tests/osproc/texecps.nim | 7 +- tests/osproc/tstderr.nim | 7 +- tests/parallel/tarray_of_channels.nim | 2 +- tests/parallel/tgc_unsafe.nim | 2 +- tests/parallel/tgc_unsafe2.nim | 2 +- tests/parallel/tmissing_deepcopy.nim | 2 +- tests/parallel/tsimple_array_checks.nim | 2 +- tests/parallel/twrong_refcounts.nim | 2 +- tests/statictypes/t9255.nim | 2 +- tests/stdlib/tjsonmacro.nim | 2 +- tests/system/helpers/readall_echo.nim | 2 +- tests/template/annotate.nim | 2 +- tests/template/t_otemplates.nim | 2 +- tests/template/template_issues.nim | 2 +- tests/template/tgensymregression.nim | 2 +- tests/template/thygienictempl.nim | 2 +- tests/template/twrongopensymchoice.nim | 2 +- tests/threads/t8535.nim | 2 +- tests/tuples/ttuples_various.nim | 2 +- tests/typerel/t2plus.nim | 2 +- tests/types/tillegaltyperecursion.nim | 2 +- tests/untestable/tssl.nim | 2 +- tests/vm/tforwardproc.nim | 2 +- 85 files changed, 180 insertions(+), 110 deletions(-) diff --git a/.gitignore b/.gitignore index 8cd092639..d736cdf8d 100644 --- a/.gitignore +++ b/.gitignore @@ -66,3 +66,6 @@ testresults/ test.txt /test.ini +tweeter.db +tweeter_test.db +megatest.nim diff --git a/testament/categories.nim b/testament/categories.nim index 48aa5844c..d9089e941 100644 --- a/testament/categories.nim +++ b/testament/categories.nim @@ -579,7 +579,8 @@ const specialCategories = [ "niminaction", "rodfiles", "threads", - "untestable" + "untestable", + "stdlib", ] @@ -598,9 +599,18 @@ const specialDisabedTests = [ "tests/system/t7894.nim", # causes out of memory in later tests "tests/types/tissues_types.nim", # causes out of memory with --gc:boehm "tests/pragmas/tused.nim", # paths in nimout differ when imported + "tests/generics/trtree.nim", # very very ugly test + "tests/array/tarray.nim", # + "tests/osproc/texecps.nim", # uses getAppFileName() to start itself with arguments + "tests/destructor/turn_destroy_into_finalizer.nim", # fails when imported + "tests/osproc/texitsignal.nim", # uses getAppFileName() to start itself with arguments ] proc isJoinableSpec(spec: TSpec): bool = + + if spec.sortoutput: + return false + if spec.action != actionRun: return false @@ -678,24 +688,63 @@ proc runJoinedTest(): bool = else: echo "nimout FAIL" - (buf, exitCode) = execCmdEx2("./megatest", [], {}, "") + (buf, exitCode) = execCmdEx2("./megatest", [], {poStdErrToStdOut}, "") if exitCode != 0: quit("megatest execution failed") echo "run ok" - var outputOK = true - for runSpec in specs: + + writeFile("outputGotten.txt", buf) + var outputExpected = "" + + var outputErrorCount = 0 + var currentPos = 0 + + var lastLine = "" + + # when a lot of output is skipped, this can be the cause why a later test fails. + var warnings = "" + + for i, runSpec in specs: + outputExpected.add runSpec.output + if outputExpected[^1] != '\n': + outputExpected.add '\n' + for line in runSpec.output.splitLines: - if buf.find(line) < 0: - echo "could not find: ", line - echo runSpec.file - outputOK = false - if outputOK: + if line != "": + #if line == "2": + # echo "found the test: ", runSpec.file + let newPos = buf.find(line, currentPos) + if newPos < 0: + if outputErrorCount < 5: + echo "could not find: ", line + echo "it could be, because the test failed, or too much output is discarded by a previous search in the output." + echo warnings + warnings.setLen 0 + + # don't spam too much of this + if outputErrorCount == 0: + echo "############" + echo buf[currentPos-200 ..< currentPos] + echo "| (", current_pos, ")" + echo buf[currentPos ..< min(currentPos+200, buf.len)] + echo "############" + + inc outputErrorCount + else: + if currentPos + lastLine.len * 2 < newPos: + warnings.addLine "Warning long skip in search for: ", line + warnings.addLine "in test: ", runSpec.file + currentPos = newPos + line.len + + lastLine = line + if outputErrorCount == 0: echo "output OK" else: - echo "output FAIL" + echo "output FAIL (", outputErrorCount, " errors)" - removeFile("megatest.nim") + writeFile("outputExpected.txt", outputExpected) - return nimoutOK and outputOK + # removeFile("megatest.nim") + return nimoutOK and outputErrorCount == 0 diff --git a/testament/specs.nim b/testament/specs.nim index e3ad3a4ff..9cbf2a9f6 100644 --- a/testament/specs.nim +++ b/testament/specs.nim @@ -109,12 +109,11 @@ proc parseTargets*(value: string): set[TTarget] = of "js": result.incl(targetJS) else: echo "target ignored: " & v - -proc addLine(self: var string; a: string) = +proc addLine*(self: var string; a: string) = self.add a self.add "\n" -proc addLine(self: var string; a,b: string) = +proc addLine*(self: var string; a,b: string) = self.add a self.add b self.add "\n" diff --git a/testament/tester.nim b/testament/tester.nim index 11489e7a6..d82d5ec0c 100644 --- a/testament/tester.nim +++ b/testament/tester.nim @@ -497,6 +497,9 @@ else: # array of modules disabled from compilation test of stdlib. disabledFiles = ["-"] + + + include categories # proc runCaasTests(r: var TResults) = diff --git a/tests/async/t7192.nim b/tests/async/t7192.nim index c380f93e1..9ac0e07c0 100644 --- a/tests/async/t7192.nim +++ b/tests/async/t7192.nim @@ -9,6 +9,6 @@ import asyncdispatch proc testCallback() = echo "testCallback()" -when isMainModule: +when true: callSoon(testCallback) poll() diff --git a/tests/async/tasyncexceptions.nim b/tests/async/tasyncexceptions.nim index 3a34478ca..de61c099d 100644 --- a/tests/async/tasyncexceptions.nim +++ b/tests/async/tasyncexceptions.nim @@ -27,7 +27,7 @@ proc serve() {.async.} = var fut = await accept() await processClient(fut) -when isMainModule: +when true: proc main = var fut = serve() fut.callback = diff --git a/tests/async/tasyncrecursion.nim b/tests/async/tasyncrecursion.nim index c038be640..7c12dbb0e 100644 --- a/tests/async/tasyncrecursion.nim +++ b/tests/async/tasyncrecursion.nim @@ -15,7 +15,7 @@ proc asyncRecursionTest*(): Future[int] {.async.} = inc(result, await asyncRecursionCycle(i)) inc(i) -when isMainModule: +when true: setGlobalDispatcher(newDispatcher()) var i = waitFor asyncRecursionTest() echo i diff --git a/tests/bind/tdatabind.nim b/tests/bind/tdatabind.nim index 124faee6f..f6455749c 100644 --- a/tests/bind/tdatabind.nim +++ b/tests/bind/tdatabind.nim @@ -74,7 +74,7 @@ proc propertyBind*[T](p1: var TProperty[T], p2: var TProperty[T]) = proc `->`[T](p1: var TProperty[T], p2: var TProperty[T]) = propertyBind(p2,p1) -when isMainModule: +when true: # Initial value testing var myProp = newProperty(5) diff --git a/tests/ccgbugs/t8616.nim b/tests/ccgbugs/t8616.nim index 54068652a..5fd940d3b 100644 --- a/tests/ccgbugs/t8616.nim +++ b/tests/ccgbugs/t8616.nim @@ -1,4 +1,4 @@ import pkg8616 / scheduler -when isMainModule: +when true: init() diff --git a/tests/ccgbugs/t8781.nim b/tests/ccgbugs/t8781.nim index 1fa8ec8a5..884c6962a 100644 --- a/tests/ccgbugs/t8781.nim +++ b/tests/ccgbugs/t8781.nim @@ -18,7 +18,7 @@ type of false: region: float -when isMainModule: +when true: let r = 1.5 let a = TypeOne(animatedU: true, animated: false, diff --git a/tests/ccgbugs/tgeneric_closure.nim b/tests/ccgbugs/tgeneric_closure.nim index bb3b924b9..9f3c5b446 100644 --- a/tests/ccgbugs/tgeneric_closure.nim +++ b/tests/ccgbugs/tgeneric_closure.nim @@ -15,7 +15,7 @@ type proc mult(x:int, y:var int) = y = 2 * x -when isMainModule: +when true: var input = 1 var output = 0 diff --git a/tests/ccgbugs/tgeneric_smallobj_asgn_opt.nim b/tests/ccgbugs/tgeneric_smallobj_asgn_opt.nim index 919dc3fc1..3788b9985 100644 --- a/tests/ccgbugs/tgeneric_smallobj_asgn_opt.nim +++ b/tests/ccgbugs/tgeneric_smallobj_asgn_opt.nim @@ -1,5 +1,5 @@ discard """ - output: '''false''' + output: "done generic smallobj asgn opt" """ # bug #5402 @@ -23,4 +23,5 @@ proc newListOfContainers[T](): ListOfContainers[T] = result.list = initDoublyLinkedList[Container[T]]() let q = newListOfContainers[int64]() -echo q.contains(123) +if not q.contains(123): + echo "done generic smallobj asgn opt" diff --git a/tests/ccgbugs/tmarkerproc_regression.nim b/tests/ccgbugs/tmarkerproc_regression.nim index 99b38e3ec..3b606b834 100644 --- a/tests/ccgbugs/tmarkerproc_regression.nim +++ b/tests/ccgbugs/tmarkerproc_regression.nim @@ -1,5 +1,5 @@ discard """ - output: "done" + output: "done markerproc regression" """ type @@ -42,6 +42,6 @@ proc main = let expected = $i & "some longer text here " & $i if a[i].ver.string != expected: quit "bug!" - echo "done" + echo "done markerproc regression" main() diff --git a/tests/ccgbugs/tmissingbracket.nim b/tests/ccgbugs/tmissingbracket.nim index d54983860..468e13366 100644 --- a/tests/ccgbugs/tmissingbracket.nim +++ b/tests/ccgbugs/tmissingbracket.nim @@ -1,6 +1,8 @@ discard """ - output: '''Subobject test called -5''' +output: ''' +Subobject test called +5 +''' """ type @@ -49,4 +51,3 @@ var a: SubObject a.test() echo a.t - diff --git a/tests/collections/ttables.nim b/tests/collections/ttables.nim index f1355e747..b22b2b237 100644 --- a/tests/collections/ttables.nim +++ b/tests/collections/ttables.nim @@ -1,6 +1,6 @@ discard """ output: ''' -done +done tableadds And we get here 1 2 @@ -17,7 +17,7 @@ block tableadds: tab.add "key", "value " & $i main() - echo "done" + echo "done tableadds" block tcounttable: diff --git a/tests/deps/jester-#head/jester/patterns.nim b/tests/deps/jester-#head/jester/patterns.nim index 52b0d3a15..c827fbc7f 100644 --- a/tests/deps/jester-#head/jester/patterns.nim +++ b/tests/deps/jester-#head/jester/patterns.nim @@ -120,7 +120,7 @@ proc match*(pattern: Pattern, s: string): if s.len != i: result.matched = false -when isMainModule: +when true: let f = parsePattern("/show/@id/test/@show?/?") doAssert match(f, "/show/12/test/hallo/").matched doAssert match(f, "/show/2131726/test/jjjuuwąąss").matched diff --git a/tests/deps/jester-#head/jester/private/utils.nim b/tests/deps/jester-#head/jester/private/utils.nim index 66f0b37a6..0ddc5945b 100644 --- a/tests/deps/jester-#head/jester/private/utils.nim +++ b/tests/deps/jester-#head/jester/private/utils.nim @@ -188,7 +188,7 @@ when not declared(normalizePath) and not declared(normalizedPath): result = path normalizePath(result) -when isMainModule: +when true: var r = {:}.newStringTable parseUrlQuery("FirstName=Mickey", r) echo r diff --git a/tests/deps/zip-0.2.1/zip/zipfiles.nim b/tests/deps/zip-0.2.1/zip/zipfiles.nim index ca1979488..274587df9 100644 --- a/tests/deps/zip-0.2.1/zip/zipfiles.nim +++ b/tests/deps/zip-0.2.1/zip/zipfiles.nim @@ -186,7 +186,7 @@ proc extractAll*(z: var ZipArchive, dest: string) = createDir(dest / file[0..file.rfind("/")]) extractFile(z, file, dest / file) -when not defined(testing) and isMainModule: +when not defined(testing) and true: var zip: ZipArchive if not zip.open("nim-0.11.0.zip"): raise newException(IOError, "opening zip failed") diff --git a/tests/destructor/tmove_objconstr.nim b/tests/destructor/tmove_objconstr.nim index 51aba1592..875f78283 100644 --- a/tests/destructor/tmove_objconstr.nim +++ b/tests/destructor/tmove_objconstr.nim @@ -36,7 +36,7 @@ proc pointlessWrapper(s: string): Data = proc main = var x = pointlessWrapper"test" -when isMainModule: +when true: main() # bug #985 diff --git a/tests/destructor/turn_destroy_into_finalizer.nim b/tests/destructor/turn_destroy_into_finalizer.nim index f5b705593..b3f34003e 100644 --- a/tests/destructor/turn_destroy_into_finalizer.nim +++ b/tests/destructor/turn_destroy_into_finalizer.nim @@ -1,5 +1,5 @@ discard """ - output: '''true''' + output: "turn_destroy_into_finalizer works" """ type @@ -17,6 +17,9 @@ proc main = for i in 1..50_000: new(r) r.id = i - echo destroyed > 30_000 + if destroyed > 30_000: + echo "turn_destroy_into_finalizer works" + else: + echo "turn_destroy_into_finalizer failed: ", destroyed main() diff --git a/tests/discard/tdiscardable.nim b/tests/discard/tdiscardable.nim index a3dd966a0..81e17866a 100644 --- a/tests/discard/tdiscardable.nim +++ b/tests/discard/tdiscardable.nim @@ -1,10 +1,13 @@ discard """ output: ''' +tdiscardable 1 1 ''' """ +echo "tdiscardable" + # Test the discardable pragma proc p(x, y: int): int {.discardable.} = diff --git a/tests/distinct/tdistinct.nim b/tests/distinct/tdistinct.nim index 52728fc2b..70e586ded 100644 --- a/tests/distinct/tdistinct.nim +++ b/tests/distinct/tdistinct.nim @@ -1,9 +1,11 @@ discard """ output: ''' +tdistinct 25 ''' """ +echo "tdistinct" block tborrowdot: type @@ -18,8 +20,6 @@ block tborrowdot: bb.a = 90 bb.s = "abc" - - block tcurrncy: template Additive(typ: untyped) = proc `+`(x, y: typ): typ {.borrow.} @@ -53,8 +53,6 @@ block tcurrncy: DefineCurrency(TEuro, int) echo($( 12.TDollar + 13.TDollar )) #OUT 25 - - block tconsts: # bug #2641 diff --git a/tests/errmsgs/t6483.nim b/tests/errmsgs/t6483.nim index 59ea6d7e2..0e977b36d 100644 --- a/tests/errmsgs/t6483.nim +++ b/tests/errmsgs/t6483.nim @@ -16,7 +16,7 @@ type variables: seq[VarItem] children: seq[VarScope] -when isMainModule: +when true: var scope1 = VarScope( variables: newSeq[VarItem](), children: newSeq[VarScope]() diff --git a/tests/errmsgs/tproper_stacktrace.nim b/tests/errmsgs/tproper_stacktrace.nim index 134946651..c0090a595 100644 --- a/tests/errmsgs/tproper_stacktrace.nim +++ b/tests/errmsgs/tproper_stacktrace.nim @@ -66,7 +66,7 @@ template verifyStackTrace*(expectedStackTrace: string, body: untyped) = -when isMainModule: +when true: # <-- Align with line 70 in the text editor block: proc bar() = diff --git a/tests/errmsgs/treportunused.nim b/tests/errmsgs/treportunused.nim index f83ad5633..c74fea46f 100644 --- a/tests/errmsgs/treportunused.nim +++ b/tests/errmsgs/treportunused.nim @@ -16,7 +16,6 @@ action: compile """ # bug #9764 - iterator s1(a:string): int = discard iterator s2(): int = discard template s3(): untyped = 123 diff --git a/tests/generics/tbintree.nim b/tests/generics/tbintree.nim index b4507e298..962d4f315 100644 --- a/tests/generics/tbintree.nim +++ b/tests/generics/tbintree.nim @@ -81,7 +81,7 @@ proc debug[T](a: PBinaryTree[T]) = echo a.data debug(a.ri) -when isMainModule: +when true: var root: PBinaryTree[string] x = newNode("hello") diff --git a/tests/generics/toverloading_typedesc.nim b/tests/generics/toverloading_typedesc.nim index 94f4d860d..5ab700828 100644 --- a/tests/generics/toverloading_typedesc.nim +++ b/tests/generics/toverloading_typedesc.nim @@ -10,7 +10,7 @@ type LBar = object -when isMainModule: +when true: doAssert FBar.new() == 3 proc new(_: typedesc[LFoo]): int = 0 diff --git a/tests/generics/tthread_generic.nim b/tests/generics/tthread_generic.nim index f2e9cafa9..2af5a7615 100644 --- a/tests/generics/tthread_generic.nim +++ b/tests/generics/tthread_generic.nim @@ -26,7 +26,7 @@ proc `@||->`*[T](fn: proc(): T {.thread.}, proc `||->`*[T](fn: proc(): T{.thread.}, callback: proc(val: T){.thread.}) = discard fn @||-> callback -when isMainModule: +when true: import os proc testFunc(): int {.thread.} = return 1 diff --git a/tests/generics/twrong_floatlit_type.nim b/tests/generics/twrong_floatlit_type.nim index c1830cd5a..04bacc0d9 100644 --- a/tests/generics/twrong_floatlit_type.nim +++ b/tests/generics/twrong_floatlit_type.nim @@ -108,7 +108,7 @@ proc `/`*[S](a, b: Vector2D[S]): Vector2D[S] = proc vec[S](x, y: S): Vector2D[S] = Vector2D[S](x: x, y: y) -if isMainModule: +if true: # Comment out this let, and the program will fail to # compile with a type mismatch, as expected. diff --git a/tests/implicit/timplicit.nim b/tests/implicit/timplicit.nim index 70f14db53..bb701249c 100644 --- a/tests/implicit/timplicit.nim +++ b/tests/implicit/timplicit.nim @@ -6,6 +6,7 @@ discard """ 4 2 88 +timplicit done ''' """ @@ -43,4 +44,6 @@ block: var indirect = p x.indirect(44) - echo x[] \ No newline at end of file + echo x[] + + echo "timplicit done" diff --git a/tests/iter/titer10.nim b/tests/iter/titer10.nim index 6a6afc780..9c76b62e1 100644 --- a/tests/iter/titer10.nim +++ b/tests/iter/titer10.nim @@ -23,7 +23,7 @@ when true: for val in sortable: yield val - when isMainModule: + when true: proc main = for val in byDistance([2, 3, 5, 1], 3): echo val diff --git a/tests/js/tvarargs.nim b/tests/js/tvarargs.nim index b8c532767..8d57af58d 100644 --- a/tests/js/tvarargs.nim +++ b/tests/js/tvarargs.nim @@ -11,5 +11,5 @@ type var console* {.importc.}: Console -when isMainModule: +when true: console.log "Hello, world" diff --git a/tests/macros/tmacro4.nim b/tests/macros/tmacro4.nim index 164afaeb7..7c2839aba 100644 --- a/tests/macros/tmacro4.nim +++ b/tests/macros/tmacro4.nim @@ -11,7 +11,7 @@ macro test_macro*(s: string, n: untyped): untyped = add(ass, newIdentNode("str")) add(ass, newStrLitNode("after")) add(result, ass) -when isMainModule: +when true: var str: string = "before" test_macro(str): var i : integer = 123 diff --git a/tests/manyloc/argument_parser/argument_parser.nim b/tests/manyloc/argument_parser/argument_parser.nim index d42842f93..9a37ef8c9 100644 --- a/tests/manyloc/argument_parser/argument_parser.nim +++ b/tests/manyloc/argument_parser/argument_parser.nim @@ -486,7 +486,7 @@ proc echo_help*(expected: seq[Tparameter_specification] = @[], echo line -when isMainModule: +when true: # Simply tests code embedded in docs. let parsed_param1 = new_parsed_parameter(PK_FLOAT, 3.41) diff --git a/tests/manyloc/argument_parser/ex_wget.nim b/tests/manyloc/argument_parser/ex_wget.nim index 625a6f595..ebbf1933f 100644 --- a/tests/manyloc/argument_parser/ex_wget.nim +++ b/tests/manyloc/argument_parser/ex_wget.nim @@ -81,7 +81,7 @@ proc process_commandline(): Tcommandline_results = echo "Will use progress type $1" % [result.options[PARAM_PROGRESS[0]].str_val] -when isMainModule: +when true: let args = process_commandline() for param in args.positional_parameters: echo "Downloading $1" % param.str_val diff --git a/tests/manyloc/keineschweine/dependencies/genpacket/genpacket.nim b/tests/manyloc/keineschweine/dependencies/genpacket/genpacket.nim index 3026cc4b9..fe9909750 100644 --- a/tests/manyloc/keineschweine/dependencies/genpacket/genpacket.nim +++ b/tests/manyloc/keineschweine/dependencies/genpacket/genpacket.nim @@ -252,7 +252,7 @@ template forwardPacketT*(typeName: expr): stmt {.dirty, immediate.} = proc `pack typeName`*(p: var typeName; s: PStream) = writeData(s, addr p, sizeof(p)) -when isMainModule: +when true: type SomeEnum = enum A = 0'i8, diff --git a/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim b/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim index dccbe61ba..5d844cff9 100644 --- a/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim +++ b/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim @@ -244,7 +244,7 @@ template forwardPacketT*(typeName: untyped; underlyingType: untyped) {.dirty.} = #writeData(s, addr p, sizeof(p)) buffer.write(underlyingType(ord)) -when isMainModule: +when true: type SomeEnum = enum A = 0'i8, diff --git a/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim b/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim index 33d2a7177..a9e1e4dbb 100644 --- a/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim +++ b/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim @@ -50,7 +50,7 @@ macro `?`(a: untyped): untyped = result = ($a[1].ident)[0].lit ## echo(?F,?a,?t,?t,?y) -when isMainModule: +when true: macro foo(x: untyped) = result = newNimNode(nnkStmtList) result.add(newNimNode(nnkCall).und(!!"echo", "Hello thar".lit)) diff --git a/tests/manyloc/keineschweine/dependencies/genpacket/streams_enh.nim b/tests/manyloc/keineschweine/dependencies/genpacket/streams_enh.nim index 5a1dffc93..ad0d20f1c 100644 --- a/tests/manyloc/keineschweine/dependencies/genpacket/streams_enh.nim +++ b/tests/manyloc/keineschweine/dependencies/genpacket/streams_enh.nim @@ -24,7 +24,7 @@ proc writeLEStr*(s: PStream, str: string) = s.write(str.len.int16) s.write(str) -when isMainModule: +when true: var testStream = newStringStream() testStream.writeLEStr("Hello") diff --git a/tests/manyloc/keineschweine/dependencies/nake/nake.nim b/tests/manyloc/keineschweine/dependencies/nake/nake.nim index 5341c1079..83569e30e 100644 --- a/tests/manyloc/keineschweine/dependencies/nake/nake.nim +++ b/tests/manyloc/keineschweine/dependencies/nake/nake.nim @@ -50,7 +50,7 @@ template withDir*(dir: string; body: stmt): stmt = body cd(curDir) -when isMainModule: +when true: if not existsFile("nakefile.nim"): echo "No nakefile.nim found. Current working dir is ", getCurrentDir() quit 1 diff --git a/tests/manyloc/keineschweine/enet_server/enet_server.nim b/tests/manyloc/keineschweine/enet_server/enet_server.nim index eae7c034e..3bb259386 100644 --- a/tests/manyloc/keineschweine/enet_server/enet_server.nim +++ b/tests/manyloc/keineschweine/enet_server/enet_server.nim @@ -102,7 +102,7 @@ handlers[HZoneJoinReq] = proc(client: PClient; buffer: PBuffer) = -when isMainModule: +when true: import parseopt, matchers, os, json diff --git a/tests/manyloc/keineschweine/keineschweine.nim b/tests/manyloc/keineschweine/keineschweine.nim index 04fec2788..b6fd3cc19 100644 --- a/tests/manyloc/keineschweine/keineschweine.nim +++ b/tests/manyloc/keineschweine/keineschweine.nim @@ -663,7 +663,7 @@ proc mainRender() = proc readyMainState() = specInputClient.setActive() -when isMainModule: +when true: import parseopt localPlayer = newPlayer() diff --git a/tests/manyloc/keineschweine/lib/estreams.nim b/tests/manyloc/keineschweine/lib/estreams.nim index 00a55c626..43a6d7004 100644 --- a/tests/manyloc/keineschweine/lib/estreams.nim +++ b/tests/manyloc/keineschweine/lib/estreams.nim @@ -106,7 +106,7 @@ proc readChar*(buffer: PBuffer): char {.inline.} = return readInt8(buffer).char proc readBool*(buffer: PBuffer): bool {.inline.} = return readInt8(buffer).bool -when isMainModule: +when true: var b = newBuffer(100) var str = "hello there" b.write str diff --git a/tests/manyloc/keineschweine/lib/map_filter.nim b/tests/manyloc/keineschweine/lib/map_filter.nim index f3f1df190..e12930066 100644 --- a/tests/manyloc/keineschweine/lib/map_filter.nim +++ b/tests/manyloc/keineschweine/lib/map_filter.nim @@ -17,7 +17,7 @@ template unless*(condition: untyped; body: untyped) {.dirty.} = if not condition: body -when isMainModule: +when true: proc dumpSeq[T](x: seq[T]) = for index, item in x.pairs: echo index, " ", item diff --git a/tests/manyloc/keineschweine/lib/sg_packets.nim b/tests/manyloc/keineschweine/lib/sg_packets.nim index f3a0e8925..9a5aa5496 100644 --- a/tests/manyloc/keineschweine/lib/sg_packets.nim +++ b/tests/manyloc/keineschweine/lib/sg_packets.nim @@ -92,7 +92,7 @@ defPacket(DsMsg, tuple[msg: string]) let HVerifyClient* = 'v' defPacket(SdVerifyClient, tuple[session: ScLogin]) -when isMainModule: +when true: var buf = newBuffer(100) var m = toMd5("hello there") diff --git a/tests/manyloc/keineschweine/lib/zlib_helpers.nim b/tests/manyloc/keineschweine/lib/zlib_helpers.nim index 076475964..895f41759 100644 --- a/tests/manyloc/keineschweine/lib/zlib_helpers.nim +++ b/tests/manyloc/keineschweine/lib/zlib_helpers.nim @@ -20,7 +20,7 @@ proc uncompress*(source: string, destLen: var int): string = echo "Error occurred: ", res -when isMainModule: +when true: import strutils var r = compress("Hello") echo repr(r) diff --git a/tests/manyloc/keineschweine/server/old_dirserver.nim b/tests/manyloc/keineschweine/server/old_dirserver.nim index 202dc6fe7..cfb0b0377 100644 --- a/tests/manyloc/keineschweine/server/old_dirserver.nim +++ b/tests/manyloc/keineschweine/server/old_dirserver.nim @@ -156,7 +156,7 @@ proc poll*(timeout: int = 250) = echo("Write ", c, " result: ", res, " data: ", repr(c.outputBuf.data)) c.outputBuf.flush() -when isMainModule: +when true: import parseopt, matchers, strutils var cfgFile = "dirserver_settings.json" for kind, key, val in getOpt(): diff --git a/tests/manyloc/keineschweine/server/old_sg_server.nim b/tests/manyloc/keineschweine/server/old_sg_server.nim index bddc74c6d..d046df9dd 100644 --- a/tests/manyloc/keineschweine/server/old_sg_server.nim +++ b/tests/manyloc/keineschweine/server/old_sg_server.nim @@ -141,7 +141,7 @@ proc poll*(timeout: int = 250) = echo("Write ", c, " result: ", res, " data: ", c.outputBuf.data) c.outputBuf.flush() -when isMainModule: +when true: import parseopt, matchers, strutils var zoneCfgFile = "./server_settings.json" for kind, key, val in getOpt(): diff --git a/tests/manyloc/nake/nake.nim b/tests/manyloc/nake/nake.nim index ff3c10a17..ebcf21d19 100644 --- a/tests/manyloc/nake/nake.nim +++ b/tests/manyloc/nake/nake.nim @@ -50,7 +50,7 @@ template withDir*(dir: string; body: untyped) = body cd(curDir) -when isMainModule: +when true: if not existsFile("nakefile.nim"): echo "No nakefile.nim found. Current working dir is ", getCurrentDir() quit 1 diff --git a/tests/misc/thallo.nim b/tests/misc/thallo.nim index 6f9d49121..7172a6b46 100644 --- a/tests/misc/thallo.nim +++ b/tests/misc/thallo.nim @@ -11,7 +11,7 @@ type TMyEnum = enum meA, meB, meC, meD -when isMainModule: +when true: {.hint: "this is the main file".} proc fac[T](x: T): T = @@ -84,5 +84,5 @@ for i in 2..6: for j in countdown(i+4, 2): echo(fac(i * j)) -when isMainModule: +when true: {.hint: "this is the main file".} diff --git a/tests/misc/tradix.nim b/tests/misc/tradix.nim index e6dde73f6..5be89530f 100644 --- a/tests/misc/tradix.nim +++ b/tests/misc/tradix.nim @@ -1,5 +1,6 @@ discard """ output: ''' +start tradix.nim false false false @@ -29,6 +30,8 @@ false ## We use a radix tree with node compression. ## There are two node kinds: +echo "start tradix.nim" + const BitsPerUnit = 8*sizeof(int) type diff --git a/tests/misc/tsortdev.nim b/tests/misc/tsortdev.nim index f360d9646..0b2a4f3e8 100644 --- a/tests/misc/tsortdev.nim +++ b/tests/misc/tsortdev.nim @@ -1,5 +1,5 @@ discard """ - output: "done" + output: "done tsortdev" """ import algorithm, strutils @@ -55,5 +55,4 @@ proc main() = for i in 0..1_000: main() -echo "done" - +echo "done tsortdev" diff --git a/tests/niminaction/Chapter3/ChatApp/src/protocol.nim b/tests/niminaction/Chapter3/ChatApp/src/protocol.nim index af515861c..4c122d4cc 100644 --- a/tests/niminaction/Chapter3/ChatApp/src/protocol.nim +++ b/tests/niminaction/Chapter3/ChatApp/src/protocol.nim @@ -37,7 +37,7 @@ proc createMessage*(username, message: string): string = "message": %message }) & "\c\l" -when isMainModule: +when true: block: let data = """{"username": "dom", "message": "hello"}""" let parsed = parseMessage(data) diff --git a/tests/niminaction/Chapter3/ChatApp/src/server.nim b/tests/niminaction/Chapter3/ChatApp/src/server.nim index 31da74d16..fbf0e5110 100644 --- a/tests/niminaction/Chapter3/ChatApp/src/server.nim +++ b/tests/niminaction/Chapter3/ChatApp/src/server.nim @@ -79,7 +79,7 @@ proc loop(server: Server, port = 7687) {.async.} = # Check whether this module has been imported as a dependency to another # module, or whether this module is the main module. -when isMainModule: +when true: # Initialise a new server. var server = newServer() echo("Server initialised!") diff --git a/tests/niminaction/Chapter6/WikipediaStats/concurrency.nim b/tests/niminaction/Chapter6/WikipediaStats/concurrency.nim index f20e21f4d..766f07fa5 100644 --- a/tests/niminaction/Chapter6/WikipediaStats/concurrency.nim +++ b/tests/niminaction/Chapter6/WikipediaStats/concurrency.nim @@ -79,5 +79,5 @@ proc readChunks(filename: string, chunksize = 1000000): Stats = file.close() -when isMainModule: +when true: echo readChunks(filename) diff --git a/tests/niminaction/Chapter6/WikipediaStats/concurrency_regex.nim b/tests/niminaction/Chapter6/WikipediaStats/concurrency_regex.nim index dbd635634..19b157926 100644 --- a/tests/niminaction/Chapter6/WikipediaStats/concurrency_regex.nim +++ b/tests/niminaction/Chapter6/WikipediaStats/concurrency_regex.nim @@ -64,5 +64,5 @@ proc readChunks(filename: string, chunksize = 1000000): Stats = file.close() -when isMainModule: +when true: echo readChunks(filename) diff --git a/tests/niminaction/Chapter6/WikipediaStats/naive.nim b/tests/niminaction/Chapter6/WikipediaStats/naive.nim index ce995efaf..687177f74 100644 --- a/tests/niminaction/Chapter6/WikipediaStats/naive.nim +++ b/tests/niminaction/Chapter6/WikipediaStats/naive.nim @@ -29,5 +29,5 @@ proc parse(filename: string): tuple[projectName, pageTitle: string, file.close() -when isMainModule: +when true: echo parse(filename) diff --git a/tests/niminaction/Chapter6/WikipediaStats/parallel_counts.nim b/tests/niminaction/Chapter6/WikipediaStats/parallel_counts.nim index 74857367a..2c4a59d83 100644 --- a/tests/niminaction/Chapter6/WikipediaStats/parallel_counts.nim +++ b/tests/niminaction/Chapter6/WikipediaStats/parallel_counts.nim @@ -70,7 +70,7 @@ proc readPageCounts(filename: string, chunkSize = 1_000_000) = echo("Most popular is: ", mostPopular) -when isMainModule: +when true: const file = "pagecounts-20160101-050000" let filename = getCurrentDir() / file readPageCounts(filename) diff --git a/tests/niminaction/Chapter6/WikipediaStats/sequential_counts.nim b/tests/niminaction/Chapter6/WikipediaStats/sequential_counts.nim index 102dd15d3..f4bae3df5 100644 --- a/tests/niminaction/Chapter6/WikipediaStats/sequential_counts.nim +++ b/tests/niminaction/Chapter6/WikipediaStats/sequential_counts.nim @@ -32,7 +32,7 @@ proc readPageCounts(filename: string) = echo("Most popular is: ", mostPopular) -when isMainModule: +when true: const file = "pagecounts-20160101-050000" let filename = getCurrentDir() / file readPageCounts(filename) diff --git a/tests/niminaction/Chapter7/Tweeter/src/views/user.nim b/tests/niminaction/Chapter7/Tweeter/src/views/user.nim index f3791b493..18f3713b3 100644 --- a/tests/niminaction/Chapter7/Tweeter/src/views/user.nim +++ b/tests/niminaction/Chapter7/Tweeter/src/views/user.nim @@ -40,7 +40,7 @@ #end proc # -#when isMainModule: +#when true: # echo renderUser(User(username: "d0m96<>", following: @[])) # echo renderMessages(@[ # Message(username: "d0m96", time: getTime(), msg: "Hello World!"), diff --git a/tests/niminaction/Chapter7/Tweeter/tests/database_test.nim b/tests/niminaction/Chapter7/Tweeter/tests/database_test.nim index da69a004c..a3cab4cba 100644 --- a/tests/niminaction/Chapter7/Tweeter/tests/database_test.nim +++ b/tests/niminaction/Chapter7/Tweeter/tests/database_test.nim @@ -4,7 +4,7 @@ outputsub: "All tests finished successfully!" import database, os, times -when isMainModule: +when true: removeFile("tweeter_test.db") var db = newDatabase("tweeter_test.db") db.setup() diff --git a/tests/osproc/ta_out.nim b/tests/osproc/ta_out.nim index 318a27d59..01b78eb11 100644 --- a/tests/osproc/ta_out.nim +++ b/tests/osproc/ta_out.nim @@ -1,14 +1,18 @@ discard """ output: ''' +start ta_out to stdout to stdout to stderr to stderr to stdout to stdout +end ta_out ''' """ +echo "start ta_out" + # This file is prefixed with an "a", because other tests # depend on it and it must be compiled first. stdout.writeLine("to stdout") @@ -25,3 +29,5 @@ stdout.writeLine("to stdout") stdout.flushFile() stdout.writeLine("to stdout") stdout.flushFile() + +echo "end ta_out" diff --git a/tests/osproc/texecps.nim b/tests/osproc/texecps.nim index 780adb7ce..10715fa0f 100644 --- a/tests/osproc/texecps.nim +++ b/tests/osproc/texecps.nim @@ -1,7 +1,3 @@ -discard """ - output: "" -""" - import osproc, streams, strutils, os const NumberOfProcesses = 13 @@ -13,8 +9,7 @@ proc execCb(idx: int, p: Process) = if exitCode < len(gResults): gResults[exitCode] = p.outputStream.readAll.strip -when isMainModule: - +when true: if paramCount() == 0: gResults = newSeq[string](NumberOfProcesses) var checks = newSeq[string](NumberOfProcesses) diff --git a/tests/osproc/tstderr.nim b/tests/osproc/tstderr.nim index 7a39522a3..55b11eba5 100644 --- a/tests/osproc/tstderr.nim +++ b/tests/osproc/tstderr.nim @@ -1,10 +1,15 @@ discard """ - output: '''-------------------------------------- + output: ''' +start tstderr +-------------------------------------- to stderr to stderr -------------------------------------- ''' """ + +echo "start tstderr" + import osproc, os, streams const filename = "ta_out".addFileExt(ExeExt) diff --git a/tests/parallel/tarray_of_channels.nim b/tests/parallel/tarray_of_channels.nim index e2a682bd5..5139920ea 100644 --- a/tests/parallel/tarray_of_channels.nim +++ b/tests/parallel/tarray_of_channels.nim @@ -34,5 +34,5 @@ proc main = sync() for ix in 1..3: channels[ix].close() -when isMainModule: +when true: main() diff --git a/tests/parallel/tgc_unsafe.nim b/tests/parallel/tgc_unsafe.nim index a4d96cd73..baf0dc24a 100644 --- a/tests/parallel/tgc_unsafe.nim +++ b/tests/parallel/tgc_unsafe.nim @@ -28,5 +28,5 @@ proc main = sync() for ix in 1..3: channels[ix].close() -when isMainModule: +when true: main() diff --git a/tests/parallel/tgc_unsafe2.nim b/tests/parallel/tgc_unsafe2.nim index 0a56a23aa..40af728fb 100644 --- a/tests/parallel/tgc_unsafe2.nim +++ b/tests/parallel/tgc_unsafe2.nim @@ -35,5 +35,5 @@ proc main = sync() for ix in 1..3: channels[ix].close() -when isMainModule: +when true: main() diff --git a/tests/parallel/tmissing_deepcopy.nim b/tests/parallel/tmissing_deepcopy.nim index 45fdf0f8f..694eb77db 100644 --- a/tests/parallel/tmissing_deepcopy.nim +++ b/tests/parallel/tmissing_deepcopy.nim @@ -36,6 +36,6 @@ proc update = for i in 0 .. people.high: spawn people[i].greet() -when isMainModule: +when true: setup() update() diff --git a/tests/parallel/tsimple_array_checks.nim b/tests/parallel/tsimple_array_checks.nim index ee9508074..5d6e87efe 100644 --- a/tests/parallel/tsimple_array_checks.nim +++ b/tests/parallel/tsimple_array_checks.nim @@ -59,5 +59,5 @@ proc maino = maino() # Doesn't work outside a proc -when isMainModule: +when true: main() diff --git a/tests/parallel/twrong_refcounts.nim b/tests/parallel/twrong_refcounts.nim index 57e0588a0..ac428762d 100644 --- a/tests/parallel/twrong_refcounts.nim +++ b/tests/parallel/twrong_refcounts.nim @@ -48,6 +48,6 @@ proc update = # --- -when isMainModule: +when true: setup() update() diff --git a/tests/statictypes/t9255.nim b/tests/statictypes/t9255.nim index bc8df6656..86bc8c7f1 100644 --- a/tests/statictypes/t9255.nim +++ b/tests/statictypes/t9255.nim @@ -8,6 +8,6 @@ type mismatch: got U): U = proc mean[T: SomeNumber](xs: seq[T]): T = xs.foldRight(0.T, (xBAZ: auto, yBAZ: auto) => xBAZ + yBAZ) / T(xs.len) -when isMainModule: +when true: let x = mean(@[1.float, 2, 3]) echo x diff --git a/tests/types/tillegaltyperecursion.nim b/tests/types/tillegaltyperecursion.nim index 6ead902b7..d8021c06f 100644 --- a/tests/types/tillegaltyperecursion.nim +++ b/tests/types/tillegaltyperecursion.nim @@ -59,7 +59,7 @@ proc Connect*(irc: var TIRC, nick: string, host: string, port: int = 6667) = -when isMainModule: +when true: var irc = initIRC() irc.Connect("AmryBot[Nim]","irc.freenode.net",6667) irc.sendRaw("JOIN #nim") diff --git a/tests/untestable/tssl.nim b/tests/untestable/tssl.nim index 664ad805c..fca6385f8 100644 --- a/tests/untestable/tssl.nim +++ b/tests/untestable/tssl.nim @@ -20,7 +20,7 @@ from strutils import contains, toHex from openssl import getOpenSSLVersion -when isMainModule: +when true: echo "version: 0x" & $getOpenSSLVersion().toHex() let client = newHttpClient() diff --git a/tests/vm/tforwardproc.nim b/tests/vm/tforwardproc.nim index 727ac6641..bcd929f0e 100644 --- a/tests/vm/tforwardproc.nim +++ b/tests/vm/tforwardproc.nim @@ -14,4 +14,4 @@ proc initArray(): array[10, int] = for f in 0..<10: result[f] = 3 -when isMainModule: echo repr(someTable) +when true: echo repr(someTable) From 8896770f8f9fa7057a11598b64160e7bce6a4266 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 6 Dec 2018 15:24:46 +0100 Subject: [PATCH 081/110] workaround against silly Windows command line length limitations for the upcoming megatest.nim --- compiler/extccomp.nim | 36 ++++++++++++++++++++++++------------ compiler/nim.nim | 8 ++++---- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index f3f74ece8..a9faefe7b 100644 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -763,6 +763,13 @@ proc execCmdsInParallel(conf: ConfigRef; cmds: seq[string]; prettyCb: proc (idx: rawMessage(conf, errGenerated, "execution of an external program failed: '$1'" % cmds.join()) +proc minimizeObjfileNameLen(fullObjName: AbsoluteFile, conf: ConfigRef): string = + # For OSes with command line length limitations we try to use relative + # paths over absolute ones: + result = relativeTo(fullObjName, getNimcacheDir(conf)).string + if result.len >= fullObjName.string.len: + result = fullObjName.string + proc callCCompiler*(conf: ConfigRef; projectfile: AbsoluteFile) = var linkCmd: string @@ -783,19 +790,24 @@ proc callCCompiler*(conf: ConfigRef; projectfile: AbsoluteFile) = if optNoLinking notin conf.globalOptions: # call the linker: var objfiles = "" - for it in conf.externalToLink: - let objFile = if noAbsolutePaths(conf): it.extractFilename else: it - add(objfiles, ' ') - add(objfiles, quoteShell( - addFileExt(objFile, CC[conf.cCompiler].objExt))) - for x in conf.toCompile: - let objFile = if noAbsolutePaths(conf): x.obj.extractFilename else: x.obj.string - add(objfiles, ' ') - add(objfiles, quoteShell(objFile)) + let oldCwd = getCurrentDir() + try: + setCurrentDir(getNimcacheDir(conf).string) + for it in conf.externalToLink: + let objFile = if noAbsolutePaths(conf): it.extractFilename else: it + add(objfiles, ' ') + let fullObjName = AbsoluteFile addFileExt(objFile, CC[conf.cCompiler].objExt) + add(objfiles, quoteShell(minimizeObjfileNameLen(fullObjName, conf))) + for x in conf.toCompile: + let objFile = if noAbsolutePaths(conf): x.obj.extractFilename.AbsoluteFile else: x.obj + add(objfiles, ' ') + add(objfiles, quoteShell(minimizeObjfileNameLen(objFile, conf))) - linkCmd = getLinkCmd(conf, projectfile, objfiles) - if optCompileOnly notin conf.globalOptions: - execLinkCmd(conf, linkCmd) + linkCmd = getLinkCmd(conf, projectfile, objfiles) + if optCompileOnly notin conf.globalOptions: + execLinkCmd(conf, linkCmd) + finally: + setCurrentDir(oldCwd) else: linkCmd = "" if optGenScript in conf.globalOptions: diff --git a/compiler/nim.nim b/compiler/nim.nim index 1c4dbd3be..cbd9d6f39 100644 --- a/compiler/nim.nim +++ b/compiler/nim.nim @@ -9,14 +9,14 @@ when defined(gcc) and defined(windows): when defined(x86): - {.link: "icons/nim.res".} + {.link: "../icons/nim.res".} else: - {.link: "icons/nim_icon.o".} + {.link: "../icons/nim_icon.o".} when defined(amd64) and defined(windows) and defined(vcc): - {.link: "icons/nim-amd64-windows-vcc.res".} + {.link: "../icons/nim-amd64-windows-vcc.res".} when defined(i386) and defined(windows) and defined(vcc): - {.link: "icons/nim-i386-windows-vcc.res".} + {.link: "../icons/nim-i386-windows-vcc.res".} import commands, lexer, condsyms, options, msgs, nversion, nimconf, ropes, From 3b783f7e131c6b5be5057127985d8ccb699d6d06 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 6 Dec 2018 16:37:56 +0100 Subject: [PATCH 082/110] Testament: refactoring; makes the test joiner green --- lib/pure/parsecfg.nim | 11 ++ testament/categories.nim | 286 ++++++++++----------------- testament/specs.nim | 13 +- testament/tester.nim | 25 +-- tests/constr/tconstr2.nim | 2 +- tests/controlflow/tcontrolflow.nim | 10 +- tests/float/tfloat3.nim | 11 +- tests/generics/tbintre2.nim | 1 + tests/generics/tbintree.nim | 2 + tests/generics/texplicitgeneric1.nim | 2 + tests/generics/texplicitgeneric2.nim | 1 + tests/generics/tgeneric0.nim | 5 +- tests/generics/tgenericprocvar.nim | 1 + tests/iter/tcountup.nim | 7 +- tests/iter/titer5.nim | 1 + tests/iter/titer6.nim | 2 + tests/iter/titer7.nim | 4 +- tests/iter/titervaropenarray.nim | 2 + tests/macros/tstringinterp.nim | 1 + tests/metatype/tmatrix1.nim | 4 +- tests/metatype/tmetatypematrix.nim | 1 + tests/misc/tack.nim | 1 + tests/misc/tpos.nim | 1 + tests/seq/tseq.nim | 1 + tests/template/annotate.nim | 2 +- tests/usingstmt/tusingstatement.nim | 2 + tests/varstmt/tvardecl.nim | 2 +- tests/vm/tvmmisc.nim | 5 +- 28 files changed, 176 insertions(+), 230 deletions(-) diff --git a/lib/pure/parsecfg.nim b/lib/pure/parsecfg.nim index efe679d67..b991dd57f 100644 --- a/lib/pure/parsecfg.nim +++ b/lib/pure/parsecfg.nim @@ -386,6 +386,17 @@ proc warningStr*(c: CfgParser, msg: string): string {.rtl, extern: "npc$1".} = result = `%`("$1($2, $3) Warning: $4", [c.filename, $getLine(c), $getColumn(c), msg]) +proc ignoreMsg*(c: CfgParser, e: CfgEvent): string {.rtl, extern: "npc$1".} = + ## returns a properly formatted warning message containing that + ## an entry is ignored. + case e.kind + of cfgSectionStart: result = c.warningStr("section ignored: " & e.section) + of cfgKeyValuePair: result = c.warningStr("key ignored: " & e.key) + of cfgOption: + result = c.warningStr("command ignored: " & e.key & ": " & e.value) + of cfgError: result = e.msg + of cfgEof: result = "" + proc getKeyValPair(c: var CfgParser, kind: CfgEventKind): CfgEvent = if c.tok.kind == tkSymbol: result.kind = kind diff --git a/testament/categories.nim b/testament/categories.nim index d9089e941..4c34eb1d1 100644 --- a/testament/categories.nim +++ b/testament/categories.nim @@ -10,6 +10,58 @@ ## Include for the tester that contains test suites that test special features ## of the compiler. +const + specialCategories = [ + "assert", + "async", + "debugger", + "dll", + "examples", + "flags", + "gc", + "io", + "js", + "lib", + "longgc", + "manyloc", + "nimble-all", + "nimble-core", + "nimble-extra", + "niminaction", + "rodfiles", + "threads", + "untestable", + "stdlib", + "testdata", + "nimcache", + "coroutines", + "osproc" + ] + + +# these tests still have bugs. At some point when the bugs are fixd +# this should become empty. + +# exclude for various reasons +const + specialDisabedTests = [ + "tests/dir with space/tspace.nim", # can't import dir with spaces. + "tests/method/tmultim.nim", # (77, 8) Error: method is not a base + "tests/system/talloc2.nim", # too much memory + "tests/collections/ttables.nim", # takes too long + "tests/system/tparams.nim", # executes itself with parameters + "tests/stdlib/tquit.nim", # not testing for obvious reasons + "tests/system/trealloc.nim", # out of memory + "tests/system/t7894.nim", # causes out of memory in later tests + "tests/types/tissues_types.nim", # causes out of memory with --gc:boehm + "tests/pragmas/tused.nim", # paths in nimout differ when imported + "tests/generics/trtree.nim", # very very ugly test + "tests/array/tarray.nim", # + "tests/destructor/turn_destroy_into_finalizer.nim", # fails when imported + "tests/misc/tnew.nim", + "tests/misc/tcmdline.nim" + ] + # included from tester.nim # ---------------- ROD file tests --------------------------------------------- @@ -327,24 +379,15 @@ proc testNimInAction(r: var TResults, cat: Category, options: string) = let filename = "tests" / test.addFileExt("nim") let testHash = getMD5(readFile(filename).string) doAssert testHash == refHashes[i], "Nim in Action test " & filename & " was changed." - - - # Run the tests. for testfile in tests: test "tests/" & testfile & ".nim" - let jsFile = "tests/niminaction/Chapter8/canvas/canvas_test.nim" testJS jsFile - let cppFile = "tests/niminaction/Chapter8/sfml/sfml_test.nim" testCPP cppFile - # ------------------------- manyloc ------------------------------------------- -#proc runSpecialTests(r: var TResults, options: string) = -# for t in ["lib/packages/docutils/highlite"]: -# testSpec(r, t, options) proc findMainFile(dir: string): string = # finds the file belonging to ".nim.cfg"; if there is no such file @@ -382,20 +425,18 @@ proc testStdlib(r: var TResults, pattern, options: string, cat: Category) = for testFile in os.walkFiles(pattern): let name = extractFilename(testFile) if name notin disabledFiles: - - let contents = readFile(testFile).string - var testObj = makeTest(testFile, options, cat) if "when isMainModule" notin contents: testObj.spec.action = actionCompile testSpec r, testObj # ----------------------------- nimble ---------------------------------------- -type PackageFilter = enum - pfCoreOnly - pfExtraOnly - pfAll +type + PackageFilter = enum + pfCoreOnly + pfExtraOnly + pfAll var nimbleDir = getEnv("NIMBLE_DIR").string if nimbleDir.len == 0: nimbleDir = getHomeDir() / ".nimble" @@ -425,7 +466,6 @@ proc getPackageDir(package: string): string = iterator listPackages(filter: PackageFilter): tuple[name, url: string] = let packageList = parseFile(packageIndex) - for package in packageList.items(): let name = package["name"].str @@ -485,19 +525,28 @@ proc `&.?`(a, b: string): string = # candidate for the stdlib? result = if b.startswith(a): b else: a & b -#proc `&?.`(a, b: string): string = # not used - # candidate for the stdlib? - #result = if a.endswith(b): a else: a & b - proc processSingleTest(r: var TResults, cat: Category, options, test: string) = let test = "tests" & DirSep &.? cat.string / test let target = if cat.string.normalize == "js": targetJS else: targetC - if existsFile(test): testSpec r, makeTest(test, options, cat), {target} - else: echo "[Warning] - ", test, " test does not exist" + else: + echo "[Warning] - ", test, " test does not exist" -proc isJoinableSpec(spec: TSpec): bool +proc isJoinableSpec(spec: TSpec): bool = + result = not spec.sortoutput and + spec.action == actionRun and + spec.file.replace('\\', '/') notin specialDisabedTests and + not fileExists(spec.file.changeFileExt("cfg")) and + not fileExists(parentDir(spec.file) / "nim.cfg") and + spec.cmd.len == 0 and + spec.err != reIgnored and + spec.exitCode == 0 and + spec.input.len == 0 and + spec.nimout.len == 0 and + spec.outputCheck != ocSubstr and + spec.ccodeCheck.len == 0 and + (spec.targets == {} or spec.targets == {targetC}) proc processCategory(r: var TResults, cat: Category, options: string, runJoinableTests: bool) = case cat.string.normalize @@ -560,191 +609,64 @@ proc processCategory(r: var TResults, cat: Category, options: string, runJoinabl if testsRun == 0: echo "[Warning] - Invalid category specified \"", cat.string, "\", no tests were run" +proc norm(s: var string) = + while true: + let tmp = s.replace("\n\n", "\n") + if tmp == s: break + s = tmp + s = s.strip -const specialCategories = [ - "async", - "debugger", - "dll", - "examples", - "flags", - "gc", - "io", - "js", - "lib", - "longgc", - "manyloc", - "nimble-all", - "nimble-core", - "nimble-extra", - "niminaction", - "rodfiles", - "threads", - "untestable", - "stdlib", -] - - -# these tests still have bugs. At some point when the bugs are fixd -# this should become empty. - -# exclude for various reasons -const specialDisabedTests = [ - "tests/dir with space/tspace.nim", # can't import dir with spaces. - "tests/method/tmultim.nim", # (77, 8) Error: method is not a base - "tests/system/talloc2.nim", # too much memory - "tests/collections/ttables.nim", # takes too long - "tests/system/tparams.nim", # executes itself with parameters - "tests/stdlib/tquit.nim", # not testing for obvious reasons - "tests/system/trealloc.nim", # out of memory - "tests/system/t7894.nim", # causes out of memory in later tests - "tests/types/tissues_types.nim", # causes out of memory with --gc:boehm - "tests/pragmas/tused.nim", # paths in nimout differ when imported - "tests/generics/trtree.nim", # very very ugly test - "tests/array/tarray.nim", # - "tests/osproc/texecps.nim", # uses getAppFileName() to start itself with arguments - "tests/destructor/turn_destroy_into_finalizer.nim", # fails when imported - "tests/osproc/texitsignal.nim", # uses getAppFileName() to start itself with arguments -] - -proc isJoinableSpec(spec: TSpec): bool = - - if spec.sortoutput: - return false - - if spec.action != actionRun: - return false - - if spec.file in specialDisabedTests: - return false - - if fileExists(spec.file & ".cfg"): - return false - - if fileExists(parentDir(spec.file) / "nim.cfg"): - return false - - if spec.cmd != cmdTemplate(): - return false - - if spec.err == reIgnored: - return false - - if spec.exitCode != 0: - return false - - if spec.input != "": - return false - - if spec.targets != {} and spec.targets != {targetC}: - return false - - return true - - -proc runJoinedTest(): bool = +proc runJoinedTest(testsDir: string): bool = ## returs a list of tests that have problems - var specs:seq[TSpec] + var specs: seq[TSpec] = @[] - for file in os.walkFiles("tests/*/t*.nim"): - let a = find(file, '/') + 1 - let b = find(file, '/', a) - let cat = file[a ..< b] - - if cat in specialCategories: - continue - - let spec = parseSpec(file) - - if isJoinableSpec(spec): - specs.add spec + for kind, dir in walkDir(testsDir): + assert testsDir.startsWith(testsDir) + let cat = dir[testsDir.len .. ^1] + if kind == pcDir and cat notin specialCategories: + for file in os.walkFiles(testsDir / cat / "t*.nim"): + let spec = parseSpec(file) + if isJoinableSpec(spec): + specs.add spec echo "joinable specs: ", specs.len var megatest: string for runSpec in specs: - megatest.add "import \"" + megatest.add "import r\"" megatest.add runSpec.file megatest.add "\"\n" writeFile("megatest.nim", megatest) - let args = ["c", "-d:testing", "--gc:boehm", "megatest.nim"] + const args = ["c", "-d:testing", "--listCmd", "megatest.nim"] var (buf, exitCode) = execCmdEx2(command = "nim", args = args, options = {poStdErrToStdOut, poUsePath}, input = "") if exitCode != 0: + echo buf quit("megatest compilation failed") echo "compilation ok" - var nimoutOK = true - for runSpec in specs: - for line in runSpec.nimout.splitLines: - if buf.find(line) < 0: - echo "could not find: ", line - echo runSpec.file - nimoutOK = false - - if nimoutOK: - echo "nimout OK" - else: - echo "nimout FAIL" - (buf, exitCode) = execCmdEx2("./megatest", [], {poStdErrToStdOut}, "") if exitCode != 0: quit("megatest execution failed") echo "run ok" - + norm buf writeFile("outputGotten.txt", buf) var outputExpected = "" - - var outputErrorCount = 0 - var currentPos = 0 - - var lastLine = "" - - # when a lot of output is skipped, this can be the cause why a later test fails. - var warnings = "" - for i, runSpec in specs: - outputExpected.add runSpec.output - if outputExpected[^1] != '\n': - outputExpected.add '\n' + outputExpected.add runSpec.output.strip + outputExpected.add '\n' + norm outputExpected - for line in runSpec.output.splitLines: - if line != "": - #if line == "2": - # echo "found the test: ", runSpec.file - let newPos = buf.find(line, currentPos) - if newPos < 0: - if outputErrorCount < 5: - echo "could not find: ", line - echo "it could be, because the test failed, or too much output is discarded by a previous search in the output." - echo warnings - warnings.setLen 0 - - # don't spam too much of this - if outputErrorCount == 0: - echo "############" - echo buf[currentPos-200 ..< currentPos] - echo "| (", current_pos, ")" - echo buf[currentPos ..< min(currentPos+200, buf.len)] - echo "############" - - inc outputErrorCount - else: - if currentPos + lastLine.len * 2 < newPos: - warnings.addLine "Warning long skip in search for: ", line - warnings.addLine "in test: ", runSpec.file - currentPos = newPos + line.len - - lastLine = line - if outputErrorCount == 0: - echo "output OK" + if buf != outputExpected: + writeFile("outputExpected.txt", outputExpected) + discard execShellCmd("diff -uNdr outputExpected.txt outputGotten.txt") + echo "output different!" + result = false else: - echo "output FAIL (", outputErrorCount, " errors)" - - writeFile("outputExpected.txt", outputExpected) - - # removeFile("megatest.nim") - return nimoutOK and outputErrorCount == 0 + echo "output OK" + removeFile("megatest.nim") + result = true diff --git a/testament/specs.nim b/testament/specs.nim index 9cbf2a9f6..6283d18d7 100644 --- a/testament/specs.nim +++ b/testament/specs.nim @@ -14,9 +14,6 @@ var compilerPrefix* = "compiler" / "nim" let isTravis* = existsEnv("TRAVIS") let isAppVeyor* = existsEnv("APPVEYOR") -proc cmdTemplate*(): string = - compilerPrefix & " $target --hints:on -d:testing --nimblePath:tests/deps $options $file" - type TTestAction* = enum actionRun = "run" @@ -70,6 +67,12 @@ type nimout*: string parseErrors*: string # when the spec definition is invalid, this is not empty. +proc getCmd*(s: TSpec): string = + if s.cmd.len == 0: + result = compilerPrefix & " $target --hints:on -d:testing --nimblePath:tests/deps $options $file" + else: + result = s.cmd + const targetToExt*: array[TTarget, string] = ["c", "cpp", "m", "js"] targetToCmd*: array[TTarget, string] = ["c", "cpp", "objc", "js"] @@ -97,9 +100,6 @@ proc extractSpec(filename: string): string = when not defined(nimhygiene): {.pragma: inject.} -proc defaultSpec*(): TSpec = - result.cmd = cmdTemplate() - proc parseTargets*(value: string): set[TTarget] = for v in value.normalize.splitWhitespace: case v @@ -119,7 +119,6 @@ proc addLine*(self: var string; a,b: string) = self.add "\n" proc parseSpec*(filename: string): TSpec = - result = defaultSpec() result.file = filename let specStr = extractSpec(filename) var ss = newStringStream(specStr) diff --git a/testament/tester.nim b/testament/tester.nim index d82d5ec0c..b290bb3b0 100644 --- a/testament/tester.nim +++ b/testament/tester.nim @@ -378,13 +378,13 @@ proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) = case expected.action of actionCompile: - var given = callCompiler(expected.cmd, test.name, test.options, target, + var given = callCompiler(expected.getCmd, test.name, test.options, target, extraOptions=" --stdout --hint[Path]:off --hint[Processing]:off") compilerOutputTests(test, target, given, expected, r) of actionRun: # In this branch of code "early return" pattern is clearer than deep # nested conditionals - the empty rows in between to clarify the "danger" - var given = callCompiler(expected.cmd, test.name, test.options, + var given = callCompiler(expected.getCmd, test.name, test.options, target) if given.err != reSuccess: @@ -438,7 +438,7 @@ proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) = bufB, reExitCodesDiffer) continue - if (expected.outputCheck == ocEqual and expected.output != bufB) or + if (expected.outputCheck == ocEqual and expected.output != bufB) or (expected.outputCheck == ocSubstr and expected.output notin bufB): given.err = reOutputsDiffer r.addResult(test, target, expected.output, bufB, reOutputsDiffer) @@ -448,7 +448,7 @@ proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) = continue of actionReject: - var given = callCompiler(expected.cmd, test.name, test.options, + var given = callCompiler(expected.getCmd, test.name, test.options, target) cmpMsgs(r, expected, given, test, target) continue @@ -458,7 +458,7 @@ proc testC(r: var TResults, test: TTest, action: TTestAction) = let tname = test.name.addFileExt(".c") inc(r.total) maybeStyledEcho "Processing ", fgCyan, extractFilename(tname) - var given = callCCompiler(cmdTemplate(), test.name & ".c", test.options, targetC) + var given = callCCompiler(getCmd(TSpec()), test.name & ".c", test.options, targetC) if given.err != reSuccess: r.addResult(test, targetC, "", given.msg, given.err) elif action == actionRun: @@ -471,7 +471,7 @@ proc testExec(r: var TResults, test: TTest) = # runs executable or script, just goes by exit code inc(r.total) let (outp, errC) = execCmdEx(test.options.strip()) - var given: TSpec = defaultSpec() + var given: TSpec if errC == 0: given.err = reSuccess else: @@ -497,15 +497,9 @@ else: # array of modules disabled from compilation test of stdlib. disabledFiles = ["-"] - - - include categories -# proc runCaasTests(r: var TResults) = -# for test, output, status, mode in caasTestsRunner(): -# r.addResult(test, "", output & "-> " & $mode, -# if status: reSuccess else: reOutputsDiffer) +const testsDir = "tests" & DirSep proc main() = os.putenv "NIMTEST_COLOR", "never" @@ -556,9 +550,8 @@ proc main() = var r = initResults() case action of "all": - doAssert runJoinedTest() + doAssert runJoinedTest(testsDir) - let testsDir = "tests" & DirSep var myself = quoteShell(findExe("testament" / "tester")) if targetsStr.len > 0: myself &= " " & quoteShell("--targets:" & targetsStr) @@ -587,7 +580,7 @@ proc main() = of "html": generateHtml(resultsFile, optFailing) of "stats": - discard runJoinedTest() + discard runJoinedTest(testsDir) else: quit Usage diff --git a/tests/constr/tconstr2.nim b/tests/constr/tconstr2.nim index b911de548..2557d7db9 100644 --- a/tests/constr/tconstr2.nim +++ b/tests/constr/tconstr2.nim @@ -18,5 +18,5 @@ const (s: "hi", x: 69, y: 45, z: 0.0, chars: {'a', 'b', 'c'}), (s: "hi", x: 69, y: 45, z: 1.0, chars: {'a'})] -write(stdout, things[0].x) +writeLine(stdout, things[0].x) #OUT 69 diff --git a/tests/controlflow/tcontrolflow.nim b/tests/controlflow/tcontrolflow.nim index 9019e55b2..258f3f50d 100644 --- a/tests/controlflow/tcontrolflow.nim +++ b/tests/controlflow/tcontrolflow.nim @@ -85,13 +85,13 @@ block tnestif: if x == 0: write(stdout, "i == 0") if y == 0: - write(stdout, x) + writeLine(stdout, x) else: - write(stdout, y) + writeLine(stdout, y) elif x == 1: - write(stdout, "i == 1") + writeLine(stdout, "i == 1") elif x == 2: - write(stdout, "i == 2") + writeLine(stdout, "i == 2") else: - write(stdout, "looks like Python") + writeLine(stdout, "looks like Python") #OUT i == 2 diff --git a/tests/float/tfloat3.nim b/tests/float/tfloat3.nim index 01f3cb9df..215470cfc 100644 --- a/tests/float/tfloat3.nim +++ b/tests/float/tfloat3.nim @@ -1,14 +1,15 @@ discard """ - output: "Nim 3.4368930843, 0.3299290698 C double: 3.4368930843, 0.3299290698" + output: ''' +Nim 3.4368930843, 0.3299290698 +C double: 3.4368930843, 0.3299290698''' """ import math, strutils {.emit: """ void printFloats(void) { - double y = 1.234567890123456789; - - printf("C double: %.10f, %.10f ", exp(y), cos(y)); + double y = 1.234567890123456789; + printf("C double: %.10f, %.10f\n", exp(y), cos(y)); } """.} @@ -16,5 +17,5 @@ proc c_printf(frmt: cstring) {.importc: "printf", header: "", varargs.} proc printFloats {.importc, nodecl.} var x: float = 1.234567890123456789 -c_printf("Nim %.10f, %.10f ", exp(x), cos(x)) +c_printf("Nim %.10f, %.10f\n", exp(x), cos(x)) printFloats() diff --git a/tests/generics/tbintre2.nim b/tests/generics/tbintre2.nim index 4f63cc5f5..dadc9a064 100644 --- a/tests/generics/tbintre2.nim +++ b/tests/generics/tbintre2.nim @@ -25,3 +25,4 @@ for y in items(r2): stdout.write(y) #OUT helloworld99110223 +stdout.write "\n" diff --git a/tests/generics/tbintree.nim b/tests/generics/tbintree.nim index 962d4f315..18af5b9af 100644 --- a/tests/generics/tbintree.nim +++ b/tests/generics/tbintree.nim @@ -101,4 +101,6 @@ when true: for y in items(r2): stdout.write(y) + stdout.write "\n" + #OUT helloworld99110223 diff --git a/tests/generics/texplicitgeneric1.nim b/tests/generics/texplicitgeneric1.nim index f093e54d4..16f4f7330 100644 --- a/tests/generics/texplicitgeneric1.nim +++ b/tests/generics/texplicitgeneric1.nim @@ -32,3 +32,5 @@ c.add('A', "12") c.add('B', "13") for k, v in items(c): stdout.write(" Key: ", $k, " value: ", v) + +stdout.write "\n" diff --git a/tests/generics/texplicitgeneric2.nim b/tests/generics/texplicitgeneric2.nim index c4af17b7b..573b10ae8 100644 --- a/tests/generics/texplicitgeneric2.nim +++ b/tests/generics/texplicitgeneric2.nim @@ -33,3 +33,4 @@ c.add('B', "13") for k, v in items(c): stdout.write(" Key: ", $k, " value: ", v) +stdout.write "\n" diff --git a/tests/generics/tgeneric0.nim b/tests/generics/tgeneric0.nim index 6698ecec0..3a35ebaba 100644 --- a/tests/generics/tgeneric0.nim +++ b/tests/generics/tgeneric0.nim @@ -1,6 +1,7 @@ discard """ output: ''' -100 0 +100 +0 ''' """ @@ -72,7 +73,7 @@ block tgeneric1: proc print[T](heap: PBinHeap[T]) = for i in countup(0, heap.last): - stdout.write($heap.heap[i].data, " ") + stdout.write($heap.heap[i].data, "\n") var heap: PBinHeap[int] diff --git a/tests/generics/tgenericprocvar.nim b/tests/generics/tgenericprocvar.nim index dca9c8538..7935d90c2 100644 --- a/tests/generics/tgenericprocvar.nim +++ b/tests/generics/tgenericprocvar.nim @@ -34,3 +34,4 @@ proc test(data: seq[int], value: int): seq[int] = for x in items(test(@[1,2,3], 2)): stdout.write(x) +stdout.write "\n" diff --git a/tests/iter/tcountup.nim b/tests/iter/tcountup.nim index 83d800c82..f93f1536e 100644 --- a/tests/iter/tcountup.nim +++ b/tests/iter/tcountup.nim @@ -2,9 +2,8 @@ discard """ output: "0123456789" """ -# Test new countup and unary < +# Test new countup -for i in 0 .. < 10'i64: +for i in 0 ..< 10'i64: stdout.write(i) - -#OUT 0123456789 +echo "\n" diff --git a/tests/iter/titer5.nim b/tests/iter/titer5.nim index 3c508dca7..cb691ffdb 100644 --- a/tests/iter/titer5.nim +++ b/tests/iter/titer5.nim @@ -10,3 +10,4 @@ for x in lines.split(): stdout.write(x) #OUT abcxyz +stdout.write "\n" diff --git a/tests/iter/titer6.nim b/tests/iter/titer6.nim index b8c2f7c66..69a10d868 100644 --- a/tests/iter/titer6.nim +++ b/tests/iter/titer6.nim @@ -31,3 +31,5 @@ proc wordWrap2(s: string, maxLineWidth = 80, result = "" for word, isSep in tokenize2(s, seps): var w = 0 + +stdout.write "\n" diff --git a/tests/iter/titer7.nim b/tests/iter/titer7.nim index c2bd9b9cb..9cba3038d 100644 --- a/tests/iter/titer7.nim +++ b/tests/iter/titer7.nim @@ -45,9 +45,9 @@ proc square(x:int): int = let list = @[1,2,3,4,5,6,7,8,9] echo ("--- evens") -for item in list / isEven : echo(item) +for item in list / isEven: echo(item) echo ("--- squares") -for item in list >> square : echo(item) +for item in list >> square: echo(item) #echo ("--- squares of evens, only") # next line doesn't compile. Generic types are not inferred #for item in list />> (isEven, square) : echo(item) diff --git a/tests/iter/titervaropenarray.nim b/tests/iter/titervaropenarray.nim index b9aa2cbca..701f652df 100644 --- a/tests/iter/titervaropenarray.nim +++ b/tests/iter/titervaropenarray.nim @@ -10,3 +10,5 @@ iterator iterAndZero(a: var openArray[int]): int = var x = [[1, 2, 3], [4, 5, 6]] for y in iterAndZero(x[0]): write(stdout, $y) #OUT 123 + +write stdout, "\n" diff --git a/tests/macros/tstringinterp.nim b/tests/macros/tstringinterp.nim index 8b8e1c3a9..74c73599b 100644 --- a/tests/macros/tstringinterp.nim +++ b/tests/macros/tstringinterp.nim @@ -70,3 +70,4 @@ var s2 = formatStyleInterpolation"Hello ${bob}, ${sum(alice.len, bob.len, 2)}$$" write(stdout, s1 & " | " & s2) +write(stdout, "\n") diff --git a/tests/metatype/tmatrix1.nim b/tests/metatype/tmatrix1.nim index 0f325a17b..15913499f 100644 --- a/tests/metatype/tmatrix1.nim +++ b/tests/metatype/tmatrix1.nim @@ -8,10 +8,10 @@ type TMatrix2x2*[T] = TMatrixNM[range[0..1], range[0..1], T] TMatrix3x3*[T] = TMatrixNM[range[0..2], range[0..2], T] -proc test*[T] (matrix: TMatrix2x2[T]) = +proc test*[T](matrix: TMatrix2x2[T]) = echo "wrong proc called" -proc test*[T] (matrix: TMatrix3x3[T]) = +proc test*[T](matrix: TMatrix3x3[T]) = echo "right proc called" var matrix: TMatrix3x3[float] diff --git a/tests/metatype/tmetatypematrix.nim b/tests/metatype/tmetatypematrix.nim index 076009eb9..4cd0aa49f 100644 --- a/tests/metatype/tmetatypematrix.nim +++ b/tests/metatype/tmetatypematrix.nim @@ -43,3 +43,4 @@ for i in 0..w-1: for i in 0..w-1: stdout.write(m[i,i]) #OUT 111 +stdout.write "\n" diff --git a/tests/misc/tack.nim b/tests/misc/tack.nim index fb89dc8b1..458395ef6 100644 --- a/tests/misc/tack.nim +++ b/tests/misc/tack.nim @@ -16,3 +16,4 @@ proc ack(x, y: int): int = # echo(ack(0, 0)) write(stdout, ack(3, 4)) #OUT 125 +write stdout, "\n" diff --git a/tests/misc/tpos.nim b/tests/misc/tpos.nim index 0c8efa43d..f7607d643 100644 --- a/tests/misc/tpos.nim +++ b/tests/misc/tpos.nim @@ -29,4 +29,5 @@ proc mypos(sub, s: string, start: int = 0): int = var sub = "hello" var s = "world hello" write(stdout, mypos(sub, s)) +write stdout, "\n" #OUT 6 diff --git a/tests/seq/tseq.nim b/tests/seq/tseq.nim index 1cb94b308..6a28bc8e6 100644 --- a/tests/seq/tseq.nim +++ b/tests/seq/tseq.nim @@ -203,3 +203,4 @@ block ttoseq: stdout.write(x) var y: type("a b c".split) y = "xzy" + stdout.write("\n") diff --git a/tests/template/annotate.nim b/tests/template/annotate.nim index 5db7e59ea..a7e2f8fdb 100644 --- a/tests/template/annotate.nim +++ b/tests/template/annotate.nim @@ -65,7 +65,7 @@ proc reindent*(value: string, preset_indent = 0): string = make([ html, xml, glsl, js, css, rst ]) -when true: +when isMainModule: ## Test tags const script = js""" diff --git a/tests/usingstmt/tusingstatement.nim b/tests/usingstmt/tusingstatement.nim index fc050ee5b..6e4998892 100644 --- a/tests/usingstmt/tusingstatement.nim +++ b/tests/usingstmt/tusingstatement.nim @@ -84,3 +84,5 @@ proc use(r: var TResource) = autoClose(r = openResource("test")): use r + +write stdout, "\n" diff --git a/tests/varstmt/tvardecl.nim b/tests/varstmt/tvardecl.nim index 664de7134..37bc4bad7 100644 --- a/tests/varstmt/tvardecl.nim +++ b/tests/varstmt/tvardecl.nim @@ -9,4 +9,4 @@ var a, b: int = 4 write(stdout, a) -write(stdout, b) #OUT 44 +writeLine(stdout, b) #OUT 44 diff --git a/tests/vm/tvmmisc.nim b/tests/vm/tvmmisc.nim index 35deea224..bd3aa2fcd 100644 --- a/tests/vm/tvmmisc.nim +++ b/tests/vm/tvmmisc.nim @@ -70,8 +70,9 @@ block: # Tests for VM ops block: static: - # for joint test, the project path is different - assert "vm" in getProjectPath() or "Nim" in getProjectPath() + # for joint test, the project path is different, so I disabled it: + when false: + assert "vm" in getProjectPath() let b = getEnv("UNSETENVVAR") assert b == "" From 1946d1a61d83bd387c6392a56bebf0a902db3198 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 6 Dec 2018 19:40:39 +0100 Subject: [PATCH 083/110] fixes extccomp regressions --- compiler/extccomp.nim | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index a9faefe7b..6b03f244a 100644 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -652,13 +652,13 @@ proc compileCFile(conf: ConfigRef; list: CFileList, script: var Rope, cmds: var add(script, compileCmd) add(script, "\n") -proc getLinkCmd(conf: ConfigRef; projectfile: AbsoluteFile, objfiles: string): string = +proc getLinkCmd(conf: ConfigRef; projectfile: AbsoluteFile, objfiles: string; base: AbsoluteDir): string = if optGenStaticLib in conf.globalOptions: var libname: string if not conf.outFile.isEmpty: libname = conf.outFile.string.expandTilde if not libname.isAbsolute(): - libname = getCurrentDir() / libname + libname = base.string / libname else: libname = (libNameTmpl(conf) % splitFile(conf.projectName).name) result = CC[conf.cCompiler].buildLib % ["libfile", quoteShell(libname), @@ -684,7 +684,7 @@ proc getLinkCmd(conf: ConfigRef; projectfile: AbsoluteFile, objfiles: string): s if not conf.outFile.isEmpty: exefile = conf.outFile.string.expandTilde if not exefile.isAbsolute(): - exefile = getCurrentDir() / exefile + exefile = base.string / exefile if not noAbsolutePaths(conf): if not exefile.isAbsolute(): exefile = string(splitFile(projectfile).dir / RelativeFile(exefile)) @@ -803,7 +803,7 @@ proc callCCompiler*(conf: ConfigRef; projectfile: AbsoluteFile) = add(objfiles, ' ') add(objfiles, quoteShell(minimizeObjfileNameLen(objFile, conf))) - linkCmd = getLinkCmd(conf, projectfile, objfiles) + linkCmd = getLinkCmd(conf, projectfile, objfiles, AbsoluteDir oldCwd) if optCompileOnly notin conf.globalOptions: execLinkCmd(conf, linkCmd) finally: @@ -877,7 +877,7 @@ proc writeJsonBuildInstructions*(conf: ConfigRef; projectfile: AbsoluteFile) = linkfiles(conf, f, buf, objfiles, conf.toCompile, conf.externalToLink) lit "],\L\"linkcmd\": " - str getLinkCmd(conf, projectfile, objfiles) + str getLinkCmd(conf, projectfile, objfiles, AbsoluteDir getCurrentDir()) lit "\L}\L" close(f) From 044c7d0921d9563affd77a81321ed4f1c7941fd4 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 6 Dec 2018 20:49:55 +0100 Subject: [PATCH 084/110] fixes extccomp regressions --- compiler/extccomp.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index 6b03f244a..65a18ce64 100644 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -683,8 +683,8 @@ proc getLinkCmd(conf: ConfigRef; projectfile: AbsoluteFile, objfiles: string; ba builddll = "" if not conf.outFile.isEmpty: exefile = conf.outFile.string.expandTilde - if not exefile.isAbsolute(): - exefile = base.string / exefile + if not exefile.isAbsolute(): + exefile = base.string / exefile if not noAbsolutePaths(conf): if not exefile.isAbsolute(): exefile = string(splitFile(projectfile).dir / RelativeFile(exefile)) From 77272ceb3c31b4ca3b1e2e9109e4b2bcddbae8b5 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 6 Dec 2018 21:39:27 +0100 Subject: [PATCH 085/110] fixes extccomp regressions --- compiler/extccomp.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index 65a18ce64..7b7af0d86 100644 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -683,11 +683,11 @@ proc getLinkCmd(conf: ConfigRef; projectfile: AbsoluteFile, objfiles: string; ba builddll = "" if not conf.outFile.isEmpty: exefile = conf.outFile.string.expandTilde - if not exefile.isAbsolute(): - exefile = base.string / exefile if not noAbsolutePaths(conf): if not exefile.isAbsolute(): exefile = string(splitFile(projectfile).dir / RelativeFile(exefile)) + if not exefile.isAbsolute(): + exefile = base.string / exefile when false: if optCDebug in conf.globalOptions: writeDebugInfo(exefile.changeFileExt("ndb")) From 46820b94a634f70f805ab033703c225182564731 Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 8 Dec 2018 22:34:42 +0100 Subject: [PATCH 086/110] the linking step doesn't mind Windows' 8K command line limit anymore --- compiler/extccomp.nim | 74 +++++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 27 deletions(-) diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index 7b7af0d86..2fe151a1c 100644 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -652,13 +652,13 @@ proc compileCFile(conf: ConfigRef; list: CFileList, script: var Rope, cmds: var add(script, compileCmd) add(script, "\n") -proc getLinkCmd(conf: ConfigRef; projectfile: AbsoluteFile, objfiles: string; base: AbsoluteDir): string = +proc getLinkCmd(conf: ConfigRef; projectfile: AbsoluteFile, objfiles: string): string = if optGenStaticLib in conf.globalOptions: var libname: string if not conf.outFile.isEmpty: libname = conf.outFile.string.expandTilde if not libname.isAbsolute(): - libname = base.string / libname + libname = getCurrentDir() / libname else: libname = (libNameTmpl(conf) % splitFile(conf.projectName).name) result = CC[conf.cCompiler].buildLib % ["libfile", quoteShell(libname), @@ -683,11 +683,11 @@ proc getLinkCmd(conf: ConfigRef; projectfile: AbsoluteFile, objfiles: string; ba builddll = "" if not conf.outFile.isEmpty: exefile = conf.outFile.string.expandTilde + if not exefile.isAbsolute(): + exefile = getCurrentDir() / exefile if not noAbsolutePaths(conf): if not exefile.isAbsolute(): exefile = string(splitFile(projectfile).dir / RelativeFile(exefile)) - if not exefile.isAbsolute(): - exefile = base.string / exefile when false: if optCDebug in conf.globalOptions: writeDebugInfo(exefile.changeFileExt("ndb")) @@ -763,12 +763,31 @@ proc execCmdsInParallel(conf: ConfigRef; cmds: seq[string]; prettyCb: proc (idx: rawMessage(conf, errGenerated, "execution of an external program failed: '$1'" % cmds.join()) -proc minimizeObjfileNameLen(fullObjName: AbsoluteFile, conf: ConfigRef): string = - # For OSes with command line length limitations we try to use relative - # paths over absolute ones: - result = relativeTo(fullObjName, getNimcacheDir(conf)).string - if result.len >= fullObjName.string.len: - result = fullObjName.string +proc linkViaResponseFile(conf: ConfigRef; cmd: string) = + # Extracting the linker.exe here is a bit hacky but the best solution + # given ``buildLib``'s design. + var i = 0 + var last = 0 + if cmd.len > 0 and cmd[0] == '"': + inc i + while i < cmd.len and cmd[i] != '"': inc i + last = i + inc i + else: + while i < cmd.len and cmd[i] != ' ': inc i + last = i + while i < cmd.len and cmd[i] == ' ': inc i + let linkerArgs = conf.projectName & "_" & "linkerArgs.txt" + let args = cmd.substr(i) + # GCC's response files don't support backslashes. Junk. + if conf.cCompiler == ccGcc: + writeFile(linkerArgs, args.replace('\\', '/')) + else: + writeFile(linkerArgs, args) + try: + execLinkCmd(conf, cmd.substr(0, last) & " @" & linkerArgs) + finally: + removeFile(linkerArgs) proc callCCompiler*(conf: ConfigRef; projectfile: AbsoluteFile) = var @@ -790,24 +809,25 @@ proc callCCompiler*(conf: ConfigRef; projectfile: AbsoluteFile) = if optNoLinking notin conf.globalOptions: # call the linker: var objfiles = "" - let oldCwd = getCurrentDir() - try: - setCurrentDir(getNimcacheDir(conf).string) - for it in conf.externalToLink: - let objFile = if noAbsolutePaths(conf): it.extractFilename else: it - add(objfiles, ' ') - let fullObjName = AbsoluteFile addFileExt(objFile, CC[conf.cCompiler].objExt) - add(objfiles, quoteShell(minimizeObjfileNameLen(fullObjName, conf))) - for x in conf.toCompile: - let objFile = if noAbsolutePaths(conf): x.obj.extractFilename.AbsoluteFile else: x.obj - add(objfiles, ' ') - add(objfiles, quoteShell(minimizeObjfileNameLen(objFile, conf))) + for it in conf.externalToLink: + let objFile = if noAbsolutePaths(conf): it.extractFilename else: it + add(objfiles, ' ') + add(objfiles, quoteShell( + addFileExt(objFile, CC[conf.cCompiler].objExt))) + for x in conf.toCompile: + let objFile = if noAbsolutePaths(conf): x.obj.extractFilename else: x.obj.string + add(objfiles, ' ') + add(objfiles, quoteShell(objFile)) - linkCmd = getLinkCmd(conf, projectfile, objfiles, AbsoluteDir oldCwd) - if optCompileOnly notin conf.globalOptions: + linkCmd = getLinkCmd(conf, projectfile, objfiles) + if optCompileOnly notin conf.globalOptions: + if defined(windows) and linkCmd.len > 8_000: + # Windows's command line limit is about 8K (don't laugh...) so C compilers on + # Windows support a feature where the command line can be passed via ``@linkcmd`` + # to them. + linkViaResponseFile(conf, linkCmd) + else: execLinkCmd(conf, linkCmd) - finally: - setCurrentDir(oldCwd) else: linkCmd = "" if optGenScript in conf.globalOptions: @@ -877,7 +897,7 @@ proc writeJsonBuildInstructions*(conf: ConfigRef; projectfile: AbsoluteFile) = linkfiles(conf, f, buf, objfiles, conf.toCompile, conf.externalToLink) lit "],\L\"linkcmd\": " - str getLinkCmd(conf, projectfile, objfiles, AbsoluteDir getCurrentDir()) + str getLinkCmd(conf, projectfile, objfiles) lit "\L}\L" close(f) From ac785b06236dbc228a3b755c11bb3b1330ccc3ab Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sun, 9 Dec 2018 13:47:03 +0100 Subject: [PATCH 087/110] testament: joinable is now an explicit concept of a test spec --- testament/categories.nim | 39 +++++-------------- testament/specs.nim | 26 +++++++------ testament/tester.nim | 14 ++++--- tests/array/tarray.nim | 1 + tests/collections/ttables.nim | 3 +- .../turn_destroy_into_finalizer.nim | 1 + tests/generics/trtree.nim | 3 ++ tests/method/tmultim.nim | 3 +- tests/misc/tcmdline.nim | 1 + tests/misc/tnew.nim | 1 + tests/pragmas/tused.nim | 2 + tests/stdlib/tquit.nim | 1 + tests/system/t7894.nim | 1 + tests/system/talloc2.nim | 1 + tests/system/tparams.nim | 5 +++ tests/system/trealloc.nim | 1 + tests/types/tissues_types.nim | 3 +- 17 files changed, 55 insertions(+), 51 deletions(-) diff --git a/testament/categories.nim b/testament/categories.nim index 4c34eb1d1..7273b6a4f 100644 --- a/testament/categories.nim +++ b/testament/categories.nim @@ -35,31 +35,9 @@ const "testdata", "nimcache", "coroutines", - "osproc" - ] - - -# these tests still have bugs. At some point when the bugs are fixd -# this should become empty. - -# exclude for various reasons -const - specialDisabedTests = [ - "tests/dir with space/tspace.nim", # can't import dir with spaces. - "tests/method/tmultim.nim", # (77, 8) Error: method is not a base - "tests/system/talloc2.nim", # too much memory - "tests/collections/ttables.nim", # takes too long - "tests/system/tparams.nim", # executes itself with parameters - "tests/stdlib/tquit.nim", # not testing for obvious reasons - "tests/system/trealloc.nim", # out of memory - "tests/system/t7894.nim", # causes out of memory in later tests - "tests/types/tissues_types.nim", # causes out of memory with --gc:boehm - "tests/pragmas/tused.nim", # paths in nimout differ when imported - "tests/generics/trtree.nim", # very very ugly test - "tests/array/tarray.nim", # - "tests/destructor/turn_destroy_into_finalizer.nim", # fails when imported - "tests/misc/tnew.nim", - "tests/misc/tcmdline.nim" + "osproc", + "shouldfail", + "dir with space" ] # included from tester.nim @@ -536,11 +514,11 @@ proc processSingleTest(r: var TResults, cat: Category, options, test: string) = proc isJoinableSpec(spec: TSpec): bool = result = not spec.sortoutput and spec.action == actionRun and - spec.file.replace('\\', '/') notin specialDisabedTests and not fileExists(spec.file.changeFileExt("cfg")) and not fileExists(parentDir(spec.file) / "nim.cfg") and spec.cmd.len == 0 and - spec.err != reIgnored and + spec.err != reDisabled and + not spec.unjoinable and spec.exitCode == 0 and spec.input.len == 0 and spec.nimout.len == 0 and @@ -600,11 +578,12 @@ proc processCategory(r: var TResults, cat: Category, options: string, runJoinabl else: var testsRun = 0 for name in os.walkFiles("tests" & DirSep &.? cat.string / "t*.nim"): - let test = makeTest(name, options, cat) + var test = makeTest(name, options, cat) if runJoinableTests or not isJoinableSpec(test.spec): - testSpec r, test + discard "run the test" else: - echo "filter out: ", test.name + test.spec.err = reJoined + testSpec r, test inc testsRun if testsRun == 0: echo "[Warning] - Invalid category specified \"", cat.string, "\", no tests were run" diff --git a/testament/specs.nim b/testament/specs.nim index 6283d18d7..df12db543 100644 --- a/testament/specs.nim +++ b/testament/specs.nim @@ -38,7 +38,8 @@ type reExeNotFound, reInstallFailed # package installation failed reBuildFailed # package building failed - reIgnored, # test is ignored + reDisabled, # test is disabled + reJoined, # test is disabled because it was joined into the megatest reSuccess # test was successful reInvalidSpec # test had problems to parse the spec @@ -66,6 +67,7 @@ type targets*: set[TTarget] nimout*: string parseErrors*: string # when the spec definition is invalid, this is not empty. + unjoinable*: bool proc getCmd*(s: TSpec): string = if s.cmd.len == 0: @@ -182,26 +184,28 @@ proc parseSpec*(filename: string): TSpec = result.action = actionReject of "nimout": result.nimout = e.value + of "joinable": + result.unjoinable = not parseCfgBool(e.value) of "disabled": case e.value.normalize - of "y", "yes", "true", "1", "on": result.err = reIgnored + of "y", "yes", "true", "1", "on": result.err = reDisabled of "n", "no", "false", "0", "off": discard of "win", "windows": - when defined(windows): result.err = reIgnored + when defined(windows): result.err = reDisabled of "linux": - when defined(linux): result.err = reIgnored + when defined(linux): result.err = reDisabled of "bsd": - when defined(bsd): result.err = reIgnored + when defined(bsd): result.err = reDisabled of "macosx": - when defined(macosx): result.err = reIgnored + when defined(macosx): result.err = reDisabled of "unix": - when defined(unix): result.err = reIgnored + when defined(unix): result.err = reDisabled of "posix": - when defined(posix): result.err = reIgnored + when defined(posix): result.err = reDisabled of "travis": - if isTravis: result.err = reIgnored + if isTravis: result.err = reDisabled of "appveyor": - if isAppVeyor: result.err = reIgnored + if isAppVeyor: result.err = reDisabled else: result.parseErrors.addLine "cannot interpret as a bool: ", e.value of "cmd": @@ -237,6 +241,4 @@ proc parseSpec*(filename: string): TSpec = result.parseErrors.addLine e.msg of cfgEof: break - - close(p) diff --git a/testament/tester.nim b/testament/tester.nim index b290bb3b0..f8a3c0336 100644 --- a/testament/tester.nim +++ b/testament/tester.nim @@ -233,8 +233,10 @@ proc addResult(r: var TResults, test: TTest, target: TTarget, r.data.addf("$#\t$#\t$#\t$#", name, expected, given, $success) if success == reSuccess: maybeStyledEcho fgGreen, "PASS: ", fgCyan, alignLeft(name, 60), fgBlue, " (", durationStr, " secs)" - elif success == reIgnored: + elif success == reDisabled: maybeStyledEcho styleDim, fgYellow, "SKIP: ", styleBright, fgCyan, name + elif success == reJoined: + maybeStyledEcho styleDim, fgYellow, "JOINED: ", styleBright, fgCyan, name else: maybeStyledEcho styleBright, fgRed, "FAIL: ", fgCyan, name maybeStyledEcho styleBright, fgCyan, "Test \"", test.name, "\"", " in category \"", test.cat.string, "\"" @@ -248,7 +250,7 @@ proc addResult(r: var TResults, test: TTest, target: TTarget, let (outcome, msg) = if success == reSuccess: ("Passed", "") - elif success == reIgnored: + elif success in {reDisabled, reJoined}: ("Skipped", "") else: ("Failed", "Failure: " & $success & "\nExpected:\n" & expected & "\n\n" & "Gotten:\n" & given) @@ -357,9 +359,9 @@ proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) = inc(r.total) return - if expected.err == reIgnored: + if expected.err in {reDisabled, reJoined}: # targetC is a lie, but parameter is required - r.addResult(test, targetC, "", "", reIgnored) + r.addResult(test, targetC, "", "", expected.err) inc(r.skipped) inc(r.total) return @@ -571,7 +573,7 @@ proc main() = of "c", "cat", "category": var cat = Category(p.key) p.next - processCategory(r, cat, p.cmdLineRest.string, runJoinableTests = false) + processCategory(r, cat, p.cmdLineRest.string, runJoinableTests = true) of "r", "run": let (dir, file) = splitPath(p.key.string) let (_, subdir) = splitPath(dir) @@ -579,7 +581,7 @@ proc main() = processSingleTest(r, cat, p.cmdLineRest.string, file) of "html": generateHtml(resultsFile, optFailing) - of "stats": + of "megatest": discard runJoinedTest(testsDir) else: quit Usage diff --git a/tests/array/tarray.nim b/tests/array/tarray.nim index 96e90c97a..2a371b788 100644 --- a/tests/array/tarray.nim +++ b/tests/array/tarray.nim @@ -28,6 +28,7 @@ dflfdjkl__abcdefgasfsgdfgsgdfggsdfasdfsafewfkljdsfajsdf kgdchlfniambejop fjpmholcibdgeakn ''' +joinable: false """ block tarray: diff --git a/tests/collections/ttables.nim b/tests/collections/ttables.nim index b22b2b237..6798e5731 100644 --- a/tests/collections/ttables.nim +++ b/tests/collections/ttables.nim @@ -6,10 +6,11 @@ And we get here 2 3 ''' +joinable: false """ import hashes, sequtils, tables - +# test should not be joined because it takes too long. block tableadds: proc main = var tab = newTable[string, string]() diff --git a/tests/destructor/turn_destroy_into_finalizer.nim b/tests/destructor/turn_destroy_into_finalizer.nim index b3f34003e..1409c1c57 100644 --- a/tests/destructor/turn_destroy_into_finalizer.nim +++ b/tests/destructor/turn_destroy_into_finalizer.nim @@ -1,5 +1,6 @@ discard """ output: "turn_destroy_into_finalizer works" + joinable: false """ type diff --git a/tests/generics/trtree.nim b/tests/generics/trtree.nim index 3fb080335..6ec1c8f6f 100644 --- a/tests/generics/trtree.nim +++ b/tests/generics/trtree.nim @@ -2,8 +2,11 @@ discard """ output: '''1 [2, 3, 4, 7] [0, 0]''' target: "c" + joinable: false """ +# don't join because the code is too messy. + # Nim RTree and R*Tree implementation # S. Salewski, 06-JAN-2018 diff --git a/tests/method/tmultim.nim b/tests/method/tmultim.nim index 310502c56..0e68b660f 100644 --- a/tests/method/tmultim.nim +++ b/tests/method/tmultim.nim @@ -4,9 +4,10 @@ collide: unit, thing collide: unit, thing collide: thing, unit collide: thing, thing -collide: unit, thing | collide: unit, thing | collide: thing, unit | +collide: unit, thing | collide: unit, thing | collide: thing, unit | do nothing ''' + joinable: false """ diff --git a/tests/misc/tcmdline.nim b/tests/misc/tcmdline.nim index 2c4768716..71e1301ca 100644 --- a/tests/misc/tcmdline.nim +++ b/tests/misc/tcmdline.nim @@ -1,5 +1,6 @@ discard """ outputsub: "Number of parameters: 0" +joinable: false """ # Test the command line diff --git a/tests/misc/tnew.nim b/tests/misc/tnew.nim index 02282dd4a..2d9a64461 100644 --- a/tests/misc/tnew.nim +++ b/tests/misc/tnew.nim @@ -3,6 +3,7 @@ outputsub: ''' Simple tree node allocation worked! Simple cycle allocation worked! ''' +joinable: false """ # Test the implementation of the new operator diff --git a/tests/pragmas/tused.nim b/tests/pragmas/tused.nim index dce854146..67a039d8a 100644 --- a/tests/pragmas/tused.nim +++ b/tests/pragmas/tused.nim @@ -4,8 +4,10 @@ compile start tused.nim(15, 8) Hint: 'tused.echoSub(a: int, b: int)[declared in tused.nim(15, 7)]' is declared but not used [XDeclaredButNotUsed] compile end''' output: "8\n8" + joinable: false """ +# not joinable because paths in nimout differ when imported static: echo "compile start" diff --git a/tests/stdlib/tquit.nim b/tests/stdlib/tquit.nim index 4f8d5fb20..1f9283ec4 100644 --- a/tests/stdlib/tquit.nim +++ b/tests/stdlib/tquit.nim @@ -2,6 +2,7 @@ discard """ output: ''' just exiting... ''' +joinable: false """ # Test the new beforeQuit variable: diff --git a/tests/system/t7894.nim b/tests/system/t7894.nim index 27ee3f220..b7ca1eec8 100644 --- a/tests/system/t7894.nim +++ b/tests/system/t7894.nim @@ -1,6 +1,7 @@ discard """ disabled: "travis" disabled: "appveyor" +joinable: false """ # CI integration servers are out of memory for this test diff --git a/tests/system/talloc2.nim b/tests/system/talloc2.nim index e40c3f93c..7e0dec9d3 100644 --- a/tests/system/talloc2.nim +++ b/tests/system/talloc2.nim @@ -1,5 +1,6 @@ discard """ disabled: "windows" +joinable: false """ # appveyor is "out of memory" diff --git a/tests/system/tparams.nim b/tests/system/tparams.nim index 015530043..dcd620b20 100644 --- a/tests/system/tparams.nim +++ b/tests/system/tparams.nim @@ -1,3 +1,8 @@ +discard """ +joinable: false +""" + +# not joinable because it executes itself with parameters import os import osproc import parseopt2 diff --git a/tests/system/trealloc.nim b/tests/system/trealloc.nim index dc5f712d6..7180b8eda 100644 --- a/tests/system/trealloc.nim +++ b/tests/system/trealloc.nim @@ -1,5 +1,6 @@ discard """ output: '''success''' + joinable: false """ # bug #4818 diff --git a/tests/types/tissues_types.nim b/tests/types/tissues_types.nim index 97c796302..d3643842e 100644 --- a/tests/types/tissues_types.nim +++ b/tests/types/tissues_types.nim @@ -9,8 +9,9 @@ ptr Foo (member: "hello world", x: ...) (member: 123.456, x: ...) ''' +joinable: false """ - +# not joinable because it causes out of memory with --gc:boehm import typetraits block t1252: From 0d99ff6113245fc105b34940ab9a111cf4576361 Mon Sep 17 00:00:00 2001 From: Araq Date: Mon, 10 Dec 2018 12:36:13 +0100 Subject: [PATCH 088/110] testament megatest: furher refactorings making more tests green --- testament/categories.nim | 149 +++++++++--------- testament/tester.nim | 17 +- .../jester-#head/jester/private/utils.nim | 2 +- tests/method/tmultim.nim | 9 +- 4 files changed, 92 insertions(+), 85 deletions(-) diff --git a/testament/categories.nim b/testament/categories.nim index 7273b6a4f..6e2789868 100644 --- a/testament/categories.nim +++ b/testament/categories.nim @@ -262,7 +262,9 @@ proc asyncTests(r: var TResults, cat: Category, options: string) = # ------------------------- debugger tests ------------------------------------ proc debuggerTests(r: var TResults, cat: Category, options: string) = - testSpec r, makeTest("tools/nimgrep", options & " --debugger:on", cat) + var t = makeTest("tools/nimgrep", options & " --debugger:on", cat) + t.spec.action = actionCompile + testSpec r, t # ------------------------- JS tests ------------------------------------------ @@ -337,20 +339,20 @@ proc testNimInAction(r: var TResults, cat: Category, options: string) = "76de5833a7cc46f96b006ce51179aeb1", "705eff79844e219b47366bd431658961", "a1e87b881c5eb161553d119be8b52f64", - "13febc363ed82585f2a60de40ddfefda", + "2d706a6ec68d2973ec7e733e6d5dce50", "c11a013db35e798f44077bc0763cc86d", "3e32e2c5e9a24bd13375e1cd0467079c", - "0b9fe7ba159623d49ae60db18a15037c", - "b2dd5293d7f784824bbf9792c6fb51ad", - "4c19d8d9026bfe151b31d7007fa3c237", - "9415c6a568cfceed08da8378e95b5cd5", + "a5452722b2841f0c1db030cf17708955", + "dc6c45eb59f8814aaaf7aabdb8962294", + "69d208d281a2e7bffd3eaf4bab2309b1", + "ec05666cfb60211bedc5e81d4c1caf3d", "da520038c153f4054cb8cc5faa617714", - "e6c6e061b6f77b2475db6fec7abfb7f4", + "59906c8cd819cae67476baa90a36b8c1", "9a8fe78c588d08018843b64b57409a02", "8b5d28e985c0542163927d253a3e4fc9", "783299b98179cc725f9c46b5e3b5381f", - "bc523f9a9921299090bac1af6c958e73", - "80f9c3e594a798225046e8a42e990daf", + "1a2b3fba1187c68d6a9bfa66854f3318", + "80f9c3e594a798225046e8a42e990daf" ] for i, test in tests: @@ -497,7 +499,7 @@ proc testNimblePackages(r: var TResults, cat: Category, filter: PackageFilter) = # ---------------------------------------------------------------------------- -const AdditionalCategories = ["debugger", "examples", "lib"] +const AdditionalCategories = ["debugger", "examples", "lib", "megatest"] proc `&.?`(a, b: string): string = # candidate for the stdlib? @@ -526,7 +528,68 @@ proc isJoinableSpec(spec: TSpec): bool = spec.ccodeCheck.len == 0 and (spec.targets == {} or spec.targets == {targetC}) -proc processCategory(r: var TResults, cat: Category, options: string, runJoinableTests: bool) = +proc norm(s: var string) = + while true: + let tmp = s.replace("\n\n", "\n") + if tmp == s: break + s = tmp + s = s.strip + +proc runJoinedTest(r: var TResults, cat: Category, testsDir: string) = + ## returs a list of tests that have problems + var specs: seq[TSpec] = @[] + + for kind, dir in walkDir(testsDir): + assert testsDir.startsWith(testsDir) + let cat = dir[testsDir.len .. ^1] + if kind == pcDir and cat notin specialCategories: + for file in os.walkFiles(testsDir / cat / "t*.nim"): + let spec = parseSpec(file) + if isJoinableSpec(spec): + specs.add spec + + echo "joinable specs: ", specs.len + + var megatest: string + for runSpec in specs: + megatest.add "import r\"" + megatest.add runSpec.file + megatest.add "\"\n" + + writeFile("megatest.nim", megatest) + + const args = ["c", "-d:testing", "--listCmd", "megatest.nim"] + var (buf, exitCode) = execCmdEx2(command = "nim", args = args, options = {poStdErrToStdOut, poUsePath}, input = "") + if exitCode != 0: + echo buf + quit("megatest compilation failed") + + (buf, exitCode) = execCmdEx2("./megatest", [], {poStdErrToStdOut}, "") + if exitCode != 0: + quit("megatest execution failed") + + norm buf + writeFile("outputGotten.txt", buf) + var outputExpected = "" + for i, runSpec in specs: + outputExpected.add runSpec.output.strip + outputExpected.add '\n' + norm outputExpected + + if buf != outputExpected: + writeFile("outputExpected.txt", outputExpected) + discard execShellCmd("diff -uNdr outputExpected.txt outputGotten.txt") + echo "output different!" + quit 1 + else: + echo "output OK" + removeFile("megatest.nim") + #testSpec r, makeTest("megatest", options, cat) + +# --------------------------------------------------------------------------- + +proc processCategory(r: var TResults, cat: Category, options, testsDir: string, + runJoinableTests: bool) = case cat.string.normalize of "rodfiles": when false: @@ -575,6 +638,8 @@ proc processCategory(r: var TResults, cat: Category, options: string, runJoinabl of "untestable": # We can't test it because it depends on a third party. discard # TODO: Move untestable tests to someplace else, i.e. nimble repo. + of "megatest": + runJoinedTest(r, cat, testsDir) else: var testsRun = 0 for name in os.walkFiles("tests" & DirSep &.? cat.string / "t*.nim"): @@ -587,65 +652,3 @@ proc processCategory(r: var TResults, cat: Category, options: string, runJoinabl inc testsRun if testsRun == 0: echo "[Warning] - Invalid category specified \"", cat.string, "\", no tests were run" - -proc norm(s: var string) = - while true: - let tmp = s.replace("\n\n", "\n") - if tmp == s: break - s = tmp - s = s.strip - -proc runJoinedTest(testsDir: string): bool = - ## returs a list of tests that have problems - var specs: seq[TSpec] = @[] - - for kind, dir in walkDir(testsDir): - assert testsDir.startsWith(testsDir) - let cat = dir[testsDir.len .. ^1] - if kind == pcDir and cat notin specialCategories: - for file in os.walkFiles(testsDir / cat / "t*.nim"): - let spec = parseSpec(file) - if isJoinableSpec(spec): - specs.add spec - - echo "joinable specs: ", specs.len - - var megatest: string - for runSpec in specs: - megatest.add "import r\"" - megatest.add runSpec.file - megatest.add "\"\n" - - writeFile("megatest.nim", megatest) - - const args = ["c", "-d:testing", "--listCmd", "megatest.nim"] - var (buf, exitCode) = execCmdEx2(command = "nim", args = args, options = {poStdErrToStdOut, poUsePath}, input = "") - if exitCode != 0: - echo buf - quit("megatest compilation failed") - - echo "compilation ok" - - (buf, exitCode) = execCmdEx2("./megatest", [], {poStdErrToStdOut}, "") - if exitCode != 0: - quit("megatest execution failed") - - echo "run ok" - - norm buf - writeFile("outputGotten.txt", buf) - var outputExpected = "" - for i, runSpec in specs: - outputExpected.add runSpec.output.strip - outputExpected.add '\n' - norm outputExpected - - if buf != outputExpected: - writeFile("outputExpected.txt", outputExpected) - discard execShellCmd("diff -uNdr outputExpected.txt outputGotten.txt") - echo "output different!" - result = false - else: - echo "output OK" - removeFile("megatest.nim") - result = true diff --git a/testament/tester.nim b/testament/tester.nim index f8a3c0336..f018910bf 100644 --- a/testament/tester.nim +++ b/testament/tester.nim @@ -552,8 +552,6 @@ proc main() = var r = initResults() case action of "all": - doAssert runJoinedTest(testsDir) - var myself = quoteShell(findExe("testament" / "tester")) if targetsStr.len > 0: myself &= " " & quoteShell("--targets:" & targetsStr) @@ -566,14 +564,21 @@ proc main() = assert testsDir.startsWith(testsDir) let cat = dir[testsDir.len .. ^1] if kind == pcDir and cat notin ["testdata", "nimcache"]: - cmds.add(myself & " cat " & quoteShell(cat) & rest) + cmds.add(myself & " pcat " & quoteShell(cat) & rest) for cat in AdditionalCategories: - cmds.add(myself & " cat " & quoteShell(cat) & rest) + cmds.add(myself & " pcat " & quoteShell(cat) & rest) quit osproc.execProcesses(cmds, {poEchoCmd, poStdErrToStdOut, poUsePath, poParentStreams}) of "c", "cat", "category": var cat = Category(p.key) p.next - processCategory(r, cat, p.cmdLineRest.string, runJoinableTests = true) + processCategory(r, cat, p.cmdLineRest.string, testsDir, runJoinableTests = true) + of "pcat": + # 'pcat' is used for running a category in parallel. Currently the only + # difference is that we don't want to run joinable tests here as they + # are covered by the 'megatest' category. + var cat = Category(p.key) + p.next + processCategory(r, cat, p.cmdLineRest.string, testsDir, runJoinableTests = false) of "r", "run": let (dir, file) = splitPath(p.key.string) let (_, subdir) = splitPath(dir) @@ -581,8 +586,6 @@ proc main() = processSingleTest(r, cat, p.cmdLineRest.string, file) of "html": generateHtml(resultsFile, optFailing) - of "megatest": - discard runJoinedTest(testsDir) else: quit Usage diff --git a/tests/deps/jester-#head/jester/private/utils.nim b/tests/deps/jester-#head/jester/private/utils.nim index 0ddc5945b..16dce61fe 100644 --- a/tests/deps/jester-#head/jester/private/utils.nim +++ b/tests/deps/jester-#head/jester/private/utils.nim @@ -188,7 +188,7 @@ when not declared(normalizePath) and not declared(normalizedPath): result = path normalizePath(result) -when true: +when false: var r = {:}.newStringTable parseUrlQuery("FirstName=Mickey", r) echo r diff --git a/tests/method/tmultim.nim b/tests/method/tmultim.nim index 0e68b660f..7023e18bf 100644 --- a/tests/method/tmultim.nim +++ b/tests/method/tmultim.nim @@ -4,7 +4,9 @@ collide: unit, thing collide: unit, thing collide: thing, unit collide: thing, thing -collide: unit, thing | collide: unit, thing | collide: thing, unit | +collide: unit, thing | +collide: unit, thing | +collide: thing, unit | do nothing ''' joinable: false @@ -56,10 +58,10 @@ method collide(a, b: Thing) {.base, inline.} = quit "to override!" method collide[T](a: Thing, b: Unit[T]) {.inline.} = - write stdout, "collide: thing, unit | " + echo "collide: thing, unit |" method collide[T](a: Unit[T], b: Thing) {.inline.} = - write stdout, "collide: unit, thing | " + echo "collide: unit, thing |" proc test(a, b: Thing) {.inline.} = collide(a, b) @@ -70,7 +72,6 @@ var collide(bbb, Thing(ccc)) test(bbb, ccc) collide(aaa, bbb) -echo "" From 4d616b5dc4ee62698d16b5227c436a4edf2e9055 Mon Sep 17 00:00:00 2001 From: Araq Date: Mon, 10 Dec 2018 15:06:01 +0100 Subject: [PATCH 089/110] make tests green; better output for when megatest execution fails --- testament/categories.nim | 1 + .../keineschweine/dependencies/genpacket/genpacket_enet.nim | 2 +- .../manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim | 2 +- tests/manyloc/keineschweine/lib/estreams.nim | 2 +- tests/manyloc/keineschweine/lib/map_filter.nim | 2 +- tests/pragmas/tused.nim | 2 +- 6 files changed, 6 insertions(+), 5 deletions(-) diff --git a/testament/categories.nim b/testament/categories.nim index 6e2789868..568a13440 100644 --- a/testament/categories.nim +++ b/testament/categories.nim @@ -566,6 +566,7 @@ proc runJoinedTest(r: var TResults, cat: Category, testsDir: string) = (buf, exitCode) = execCmdEx2("./megatest", [], {poStdErrToStdOut}, "") if exitCode != 0: + echo buf quit("megatest execution failed") norm buf diff --git a/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim b/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim index 5d844cff9..b36b49823 100644 --- a/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim +++ b/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim @@ -244,7 +244,7 @@ template forwardPacketT*(typeName: untyped; underlyingType: untyped) {.dirty.} = #writeData(s, addr p, sizeof(p)) buffer.write(underlyingType(ord)) -when true: +when false: type SomeEnum = enum A = 0'i8, diff --git a/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim b/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim index a9e1e4dbb..3341f42c2 100644 --- a/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim +++ b/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim @@ -50,7 +50,7 @@ macro `?`(a: untyped): untyped = result = ($a[1].ident)[0].lit ## echo(?F,?a,?t,?t,?y) -when true: +when false: macro foo(x: untyped) = result = newNimNode(nnkStmtList) result.add(newNimNode(nnkCall).und(!!"echo", "Hello thar".lit)) diff --git a/tests/manyloc/keineschweine/lib/estreams.nim b/tests/manyloc/keineschweine/lib/estreams.nim index 43a6d7004..99cbb63d1 100644 --- a/tests/manyloc/keineschweine/lib/estreams.nim +++ b/tests/manyloc/keineschweine/lib/estreams.nim @@ -106,7 +106,7 @@ proc readChar*(buffer: PBuffer): char {.inline.} = return readInt8(buffer).char proc readBool*(buffer: PBuffer): bool {.inline.} = return readInt8(buffer).bool -when true: +when false: var b = newBuffer(100) var str = "hello there" b.write str diff --git a/tests/manyloc/keineschweine/lib/map_filter.nim b/tests/manyloc/keineschweine/lib/map_filter.nim index e12930066..acb58c60e 100644 --- a/tests/manyloc/keineschweine/lib/map_filter.nim +++ b/tests/manyloc/keineschweine/lib/map_filter.nim @@ -17,7 +17,7 @@ template unless*(condition: untyped; body: untyped) {.dirty.} = if not condition: body -when true: +when false: proc dumpSeq[T](x: seq[T]) = for index, item in x.pairs: echo index, " ", item diff --git a/tests/pragmas/tused.nim b/tests/pragmas/tused.nim index 67a039d8a..7616c1215 100644 --- a/tests/pragmas/tused.nim +++ b/tests/pragmas/tused.nim @@ -1,7 +1,7 @@ discard """ nimout: ''' compile start -tused.nim(15, 8) Hint: 'tused.echoSub(a: int, b: int)[declared in tused.nim(15, 7)]' is declared but not used [XDeclaredButNotUsed] +tused.nim(17, 8) Hint: 'tused.echoSub(a: int, b: int)[declared in tused.nim(17, 7)]' is declared but not used [XDeclaredButNotUsed] compile end''' output: "8\n8" joinable: false From 916955dc9552456a365ad612d25ec775a5bc0d06 Mon Sep 17 00:00:00 2001 From: Araq Date: Mon, 10 Dec 2018 15:28:46 +0100 Subject: [PATCH 090/110] make more tests green --- testament/tester.nim | 20 ++------------------ tests/generics/tbintre2.nim | 28 ---------------------------- tests/generics/tbintree.nim | 16 ++++++++-------- 3 files changed, 10 insertions(+), 54 deletions(-) delete mode 100644 tests/generics/tbintre2.nim diff --git a/testament/tester.nim b/testament/tester.nim index f018910bf..368c5da6f 100644 --- a/testament/tester.nim +++ b/testament/tester.nim @@ -246,7 +246,7 @@ proc addResult(r: var TResults, test: TTest, target: TTarget, maybeStyledEcho fgYellow, "Gotten:" maybeStyledEcho styleBright, given, "\n" - if existsEnv("APPVEYOR"): + if backendLogging and existsEnv("APPVEYOR"): let (outcome, msg) = if success == reSuccess: ("Passed", "") @@ -358,26 +358,21 @@ proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) = r.addResult(test, targetC, "", expected.parseErrors, reInvalidSpec) inc(r.total) return - if expected.err in {reDisabled, reJoined}: # targetC is a lie, but parameter is required r.addResult(test, targetC, "", "", expected.err) inc(r.skipped) inc(r.total) return - expected.targets.incl targets - # still no target specified at all if expected.targets == {}: if getEnv("NIM_COMPILE_TO_CPP", "false").string == "true": expected.targets = {targetCpp} else: expected.targets = {targetC} - for target in expected.targets: inc(r.total) - case expected.action of actionCompile: var given = callCompiler(expected.getCmd, test.name, test.options, target, @@ -388,11 +383,9 @@ proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) = # nested conditionals - the empty rows in between to clarify the "danger" var given = callCompiler(expected.getCmd, test.name, test.options, target) - if given.err != reSuccess: r.addResult(test, target, "", given.msg, given.err) continue - let isJsTarget = target == targetJS var exeFile: string if isJsTarget: @@ -410,8 +403,6 @@ proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) = r.addResult(test, target, expected.output, "nodejs binary not in PATH", reExeNotFound) continue - - var exeCmd: string var args: seq[string] if isJsTarget: @@ -419,13 +410,10 @@ proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) = args.add exeFile else: exeCmd = exeFile - var (buf, exitCode) = execCmdEx2(exeCmd, args, options = {poStdErrToStdOut}, input = expected.input) - # Treat all failure codes from nodejs as 1. Older versions of nodejs used # to return other codes, but for us it is sufficient to know that it's not 0. if exitCode != 0: exitCode = 1 - let bufB = if expected.sortoutput: var x = splitLines(strip(buf.string)) @@ -433,22 +421,18 @@ proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) = join(x, "\n") else: strip(buf.string) - if exitCode != expected.exitCode: r.addResult(test, target, "exitcode: " & $expected.exitCode, "exitcode: " & $exitCode & "\n\nOutput:\n" & bufB, reExitCodesDiffer) continue - if (expected.outputCheck == ocEqual and expected.output != bufB) or (expected.outputCheck == ocSubstr and expected.output notin bufB): given.err = reOutputsDiffer r.addResult(test, target, expected.output, bufB, reOutputsDiffer) continue - compilerOutputTests(test, target, given, expected, r) continue - of actionReject: var given = callCompiler(expected.getCmd, test.name, test.options, target) @@ -523,7 +507,7 @@ proc main() = targetsStr = p.val.string targets = parseTargets(targetsStr) of "nim": - compilerPrefix = p.val.string + compilerPrefix = addFileExt(p.val.string, ExeExt) of "directory": setCurrentDir(p.val.string) of "colors": diff --git a/tests/generics/tbintre2.nim b/tests/generics/tbintre2.nim deleted file mode 100644 index dadc9a064..000000000 --- a/tests/generics/tbintre2.nim +++ /dev/null @@ -1,28 +0,0 @@ -discard """ - output: "helloworld99110223" -""" -# Same test, but check module boundaries - -import tbintree - -var - root: PBinaryTree[string] - x = newNode("hello") -add(root, x) -add(root, "world") -if find(root, "world"): - for str in items(root): - stdout.write(str) -else: - stdout.writeLine("BUG") - -var - r2: PBinaryTree[int] -add(r2, newNode(110)) -add(r2, 223) -add(r2, 99) -for y in items(r2): - stdout.write(y) - -#OUT helloworld99110223 -stdout.write "\n" diff --git a/tests/generics/tbintree.nim b/tests/generics/tbintree.nim index 18af5b9af..a1a13c7b5 100644 --- a/tests/generics/tbintree.nim +++ b/tests/generics/tbintree.nim @@ -1,5 +1,9 @@ discard """ - output: "helloworld99110223" + output: '''hello +world +99 +110 +223''' """ type TBinaryTree[T] = object # TBinaryTree is a generic type with @@ -89,9 +93,9 @@ when true: add(root, "world") if find(root, "world"): for str in items(root): - stdout.write(str) + echo(str) else: - stdout.writeLine("BUG") + echo("BUG") var r2: PBinaryTree[int] @@ -99,8 +103,4 @@ when true: add(r2, 223) add(r2, 99) for y in items(r2): - stdout.write(y) - - stdout.write "\n" - -#OUT helloworld99110223 + echo(y) From 34815a469735ef15390b034d4a806c7e69ac49e7 Mon Sep 17 00:00:00 2001 From: Araq Date: Mon, 10 Dec 2018 15:50:38 +0100 Subject: [PATCH 091/110] megatest: make it green on Linux --- tests/generics/tgenerics_issues.nim | 3 +-- tests/generics/tgenerics_various.nim | 3 +-- tests/generics/tparser_generator.nim | 1 + tests/lexer/tstrlits.nim | 3 +-- tests/macros/tsametype.nim | 1 + tests/magics/tmagics.nim | 7 ++++--- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/generics/tgenerics_issues.nim b/tests/generics/tgenerics_issues.nim index c215ea2c2..a1d464b97 100644 --- a/tests/generics/tgenerics_issues.nim +++ b/tests/generics/tgenerics_issues.nim @@ -24,12 +24,11 @@ G:0,1:0.1 G:0,1:0.1 H:1:0.1 ''' +joinable: false """ - import macros, sequtils, sets, sugar, tables, typetraits - block t88: type BaseClass[V] = object of RootObj diff --git a/tests/generics/tgenerics_various.nim b/tests/generics/tgenerics_various.nim index 5e18995f5..9e6186534 100644 --- a/tests/generics/tgenerics_various.nim +++ b/tests/generics/tgenerics_various.nim @@ -5,12 +5,11 @@ direct generic generic ''' +joinable: false """ - import algorithm, sugar, sequtils, typetraits, asyncdispatch - block tconfusing_arrow: type Deck = object value: int diff --git a/tests/generics/tparser_generator.nim b/tests/generics/tparser_generator.nim index a94506d62..8f8fea382 100644 --- a/tests/generics/tparser_generator.nim +++ b/tests/generics/tparser_generator.nim @@ -1,6 +1,7 @@ discard """ output: '''Match failed: spam Match failed: ham''' +joinable: false """ # bug #6220 diff --git a/tests/lexer/tstrlits.nim b/tests/lexer/tstrlits.nim index 004ebc0a7..8e8250a5b 100644 --- a/tests/lexer/tstrlits.nim +++ b/tests/lexer/tstrlits.nim @@ -16,5 +16,4 @@ const stdout.write(rawQuote) stdout.write(tripleEmpty) stdout.write(raw) -stdout.write(escaped) -#OUT a""long string"""""abc"def_'2'●𝌆𝌆A +stdout.writeLine(escaped) diff --git a/tests/macros/tsametype.nim b/tests/macros/tsametype.nim index 865fb4cb8..5219a3767 100644 --- a/tests/macros/tsametype.nim +++ b/tests/macros/tsametype.nim @@ -9,6 +9,7 @@ true false true false''' +joinable: false """ import macros diff --git a/tests/magics/tmagics.nim b/tests/magics/tmagics.nim index 841de56a5..fa138320c 100644 --- a/tests/magics/tmagics.nim +++ b/tests/magics/tmagics.nim @@ -8,20 +8,21 @@ true false true ''' +joinable: false """ block tlowhigh: type myEnum = enum e1, e2, e3, e4, e5 var a: array[myEnum, int] - + for i in low(a) .. high(a): a[i] = 0 - + proc sum(a: openarray[int]): int = result = 0 for i in low(a)..high(a): inc(result, a[i]) - + doAssert sum([1, 2, 3, 4]) == 10 From dc604ca762d33532a53ef0656f22ee991c67023e Mon Sep 17 00:00:00 2001 From: Araq Date: Mon, 10 Dec 2018 17:27:58 +0100 Subject: [PATCH 092/110] don't run megatest in parallel for better error messages --- testament/categories.nim | 3 ++- testament/tester.nim | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/testament/categories.nim b/testament/categories.nim index 568a13440..d23f3384e 100644 --- a/testament/categories.nim +++ b/testament/categories.nim @@ -499,7 +499,8 @@ proc testNimblePackages(r: var TResults, cat: Category, filter: PackageFilter) = # ---------------------------------------------------------------------------- -const AdditionalCategories = ["debugger", "examples", "lib", "megatest"] +const AdditionalCategories = ["debugger", "examples", "lib"] +#, "megatest"] proc `&.?`(a, b: string): string = # candidate for the stdlib? diff --git a/testament/tester.nim b/testament/tester.nim index 368c5da6f..29733e45c 100644 --- a/testament/tester.nim +++ b/testament/tester.nim @@ -536,6 +536,8 @@ proc main() = var r = initResults() case action of "all": + processCategory(r, Category"megatest", p.cmdLineRest.string, testsDir, runJoinableTests = false) + var myself = quoteShell(findExe("testament" / "tester")) if targetsStr.len > 0: myself &= " " & quoteShell("--targets:" & targetsStr) From f3d2c18a127c6dd71696ddcd169d2b308cc4667f Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 11 Dec 2018 08:49:56 +0100 Subject: [PATCH 093/110] attempt to make travis green --- testament/categories.nim | 5 ++--- testament/tester.nim | 2 +- tests/closure/tclosure.nim | 1 + 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/testament/categories.nim b/testament/categories.nim index d23f3384e..dac9db57d 100644 --- a/testament/categories.nim +++ b/testament/categories.nim @@ -499,8 +499,7 @@ proc testNimblePackages(r: var TResults, cat: Category, filter: PackageFilter) = # ---------------------------------------------------------------------------- -const AdditionalCategories = ["debugger", "examples", "lib"] -#, "megatest"] +const AdditionalCategories = ["debugger", "examples", "lib", "megatest"] proc `&.?`(a, b: string): string = # candidate for the stdlib? @@ -565,7 +564,7 @@ proc runJoinedTest(r: var TResults, cat: Category, testsDir: string) = echo buf quit("megatest compilation failed") - (buf, exitCode) = execCmdEx2("./megatest", [], {poStdErrToStdOut}, "") + (buf, exitCode) = execCmdEx("./megatest") if exitCode != 0: echo buf quit("megatest execution failed") diff --git a/testament/tester.nim b/testament/tester.nim index 29733e45c..6d9e05aa9 100644 --- a/testament/tester.nim +++ b/testament/tester.nim @@ -536,7 +536,7 @@ proc main() = var r = initResults() case action of "all": - processCategory(r, Category"megatest", p.cmdLineRest.string, testsDir, runJoinableTests = false) + #processCategory(r, Category"megatest", p.cmdLineRest.string, testsDir, runJoinableTests = false) var myself = quoteShell(findExe("testament" / "tester")) if targetsStr.len > 0: diff --git a/tests/closure/tclosure.nim b/tests/closure/tclosure.nim index c213d6a4b..cfef4193a 100644 --- a/tests/closure/tclosure.nim +++ b/tests/closure/tclosure.nim @@ -33,6 +33,7 @@ foo88 11 @[1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1] ''' +joinable: false """ From 8aa4b6b5528956522115531b74a318a255135946 Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 11 Dec 2018 08:52:59 +0100 Subject: [PATCH 094/110] remove outputGotten.txt file on success --- testament/categories.nim | 1 + 1 file changed, 1 insertion(+) diff --git a/testament/categories.nim b/testament/categories.nim index dac9db57d..c1d658537 100644 --- a/testament/categories.nim +++ b/testament/categories.nim @@ -584,6 +584,7 @@ proc runJoinedTest(r: var TResults, cat: Category, testsDir: string) = quit 1 else: echo "output OK" + removeFile("outputGotten.txt") removeFile("megatest.nim") #testSpec r, makeTest("megatest", options, cat) From 01892eee4b6d29cfa137759a76b94b54b70c0a1d Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 11 Dec 2018 16:42:13 +0100 Subject: [PATCH 095/110] don't skip tests that really were not joined --- testament/categories.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testament/categories.nim b/testament/categories.nim index c1d658537..a72602217 100644 --- a/testament/categories.nim +++ b/testament/categories.nim @@ -646,7 +646,7 @@ proc processCategory(r: var TResults, cat: Category, options, testsDir: string, var testsRun = 0 for name in os.walkFiles("tests" & DirSep &.? cat.string / "t*.nim"): var test = makeTest(name, options, cat) - if runJoinableTests or not isJoinableSpec(test.spec): + if runJoinableTests or not isJoinableSpec(test.spec) or cat.string in specialCategories: discard "run the test" else: test.spec.err = reJoined From f18fcf65b3a61b1960c14aa9503eea34fee76492 Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 11 Dec 2018 18:17:38 +0100 Subject: [PATCH 096/110] make tests green again --- tests/osproc/tstdout.nim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/osproc/tstdout.nim b/tests/osproc/tstdout.nim index 0cb5bd9c0..e3ed3986a 100644 --- a/tests/osproc/tstdout.nim +++ b/tests/osproc/tstdout.nim @@ -1,11 +1,13 @@ discard """ output: '''-------------------------------------- +start ta_out to stdout to stdout to stderr to stderr to stdout to stdout +end ta_out -------------------------------------- ''' """ From 5ffa9a8be643711662856334ff3d98ee68c85e2d Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sun, 9 Dec 2018 09:20:59 +0100 Subject: [PATCH 097/110] destructors: defensive programming against wrong generated destructor for string/seq --- compiler/commands.nim | 2 +- compiler/semasgn.nim | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/compiler/commands.nim b/compiler/commands.nim index fa17e9851..b5bcfabc5 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -480,7 +480,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; of "native", "gdb": incl(conf.globalOptions, optCDebug) conf.options = conf.options + {optLineDir} - {optEndb} - defineSymbol(conf.symbols, "nimTypeNames") # type names are used in gdb pretty printing + #defineSymbol(conf.symbols, "nimTypeNames") # type names are used in gdb pretty printing undefSymbol(conf.symbols, "endb") else: localError(conf, info, "expected endb|gdb but found " & arg) diff --git a/compiler/semasgn.nim b/compiler/semasgn.nim index 3947e4f6c..5d676dc76 100644 --- a/compiler/semasgn.nim +++ b/compiler/semasgn.nim @@ -309,11 +309,15 @@ proc liftBody(c: PContext; typ: PType; kind: TTypeAttachedOp; liftBodyAux(a, typ, body, newSymNode(dest).newDeref, newSymNode(src)) # recursion is handled explicitly, do not register the type based operation # before 'liftBodyAux': - case kind - of attachedAsgn: typ.assignment = result - of attachedSink: typ.sink = result - of attachedDeepCopy: typ.deepCopy = result - of attachedDestructor: typ.destructor = result + if c.config.selectedGC == gcDestructors and + typ.kind in {tySequence, tyString} and body.len == 0: + discard "do not cache it yet" + else: + case kind + of attachedAsgn: typ.assignment = result + of attachedSink: typ.sink = result + of attachedDeepCopy: typ.deepCopy = result + of attachedDestructor: typ.destructor = result var n = newNodeI(nkProcDef, info, bodyPos+1) for i in 0 ..< n.len: n.sons[i] = newNodeI(nkEmpty, info) From 3695819018ca7c6b981313a2a7bf91b842f5207c Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Tue, 11 Dec 2018 22:06:15 +0100 Subject: [PATCH 098/110] cleanup main.nim's code style --- compiler/main.nim | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/compiler/main.nim b/compiler/main.nim index fb8fe8443..4e28ed483 100644 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -266,20 +266,16 @@ proc mainCommand*(graph: ModuleGraph) = var libpaths = newJArray() for dir in conf.searchPaths: libpaths.elems.add(%dir.string) - var hints = block: # consider factoring with `listHints` - var ret = newJObject() - for a in hintMin..hintMax: - let key = lineinfos.HintsToStr[ord(a) - ord(hintMin)] - ret[key] = % (a in conf.notes) - ret - var warnings = block: # consider factoring with `listWarnings` - var ret = newJObject() - for a in warnMin..warnMax: - let key = lineinfos.WarningsToStr[ord(a) - ord(warnMin)] - ret[key] = % (a in conf.notes) - ret + var hints = newJObject() # consider factoring with `listHints` + for a in hintMin..hintMax: + let key = lineinfos.HintsToStr[ord(a) - ord(hintMin)] + hints[key] = %(a in conf.notes) + var warnings = newJObject() + for a in warnMin..warnMax: + let key = lineinfos.WarningsToStr[ord(a) - ord(warnMin)] + warnings[key] = %(a in conf.notes) - var dumpdata = % [ + var dumpdata = %[ (key: "version", val: %VersionAsString), (key: "project_path", val: %conf.projectFull.string), (key: "defined_symbols", val: definedSymbols), From 5dc83d0c8fbc966d35494b3f69bcb5eadaa4f7bc Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Tue, 11 Dec 2018 22:13:30 +0100 Subject: [PATCH 099/110] cleanup of excpt.nim --- lib/system/excpt.nim | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim index 800b5cd2f..84a1da343 100644 --- a/lib/system/excpt.nim +++ b/lib/system/excpt.nim @@ -458,7 +458,10 @@ when defined(nimRequiresNimFrame): proc callDepthLimitReached() {.noinline.} = writeStackTrace() - showErrorMessage("Error: call depth limit reached in a debug build (" & $nimCallDepthLimit & " function calls). You can change it with -d:nimCallDepthLimit= or switch to a release build with -d:release.\n") + showErrorMessage("Error: call depth limit reached in a debug build (" & + $nimCallDepthLimit & " function calls). You can change it with " & + "-d:nimCallDepthLimit= but really try to avoid deep " & + "recursions instead.\n") quitOrDebug() proc nimFrame(s: PFrame) {.compilerRtl, inl, exportc: "nimFrame".} = From c682671feae3ae6c90416152f84b274cb5aa4a21 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Tue, 11 Dec 2018 23:07:36 +0100 Subject: [PATCH 100/110] minor cleanups --- compiler/commands.nim | 13 ++++++------- doc/advopt.txt | 2 +- doc/contributing.rst | 11 +---------- 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/compiler/commands.nim b/compiler/commands.nim index b962e8f39..b090a09a5 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -619,13 +619,12 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; incl(conf.globalOptions, optRun) of "errormax": expectArg(conf, switch, arg, pass, info) - conf.errorMax = block: - # Note: `nim check` (etc) can overwrite this. - # `0` is meaningless, give it a useful meaning as in clang's -ferror-limit - # If user doesn't set this flag and the code doesn't either, it'd - # have the same effect as errorMax = 1 - let ret = parseInt(arg) - if ret == 0: high(int) else: ret + # Note: `nim check` (etc) can overwrite this. + # `0` is meaningless, give it a useful meaning as in clang's -ferror-limit + # If user doesn't set this flag and the code doesn't either, it'd + # have the same effect as errorMax = 1 + let ret = parseInt(arg) + conf.errorMax = if ret == 0: high(int) else: ret of "verbosity": expectArg(conf, switch, arg, pass, info) let verbosity = parseInt(arg) diff --git a/doc/advopt.txt b/doc/advopt.txt index baab4f6e5..7446775db 100644 --- a/doc/advopt.txt +++ b/doc/advopt.txt @@ -104,7 +104,7 @@ Advanced options: value = number of processors (0 for auto-detect) --incremental:on|off only recompile the changed modules (experimental!) --verbosity:0|1|2|3 set Nim's verbosity level (1 is default) - --errorMax:int stop after n errors in semantic pass; 0 means unlimited + --errorMax:N stop compilation after N errors; 0 means unlimited --experimental:$1 enable experimental language feature -v, --version show detailed version information diff --git a/doc/contributing.rst b/doc/contributing.rst index a2c95db74..e3ab697d3 100644 --- a/doc/contributing.rst +++ b/doc/contributing.rst @@ -263,17 +263,8 @@ Take advantage of no implicit bool conversion doAssert isValid() == true doAssert isValid() # preferred -.. _immediately_invoked_lambdas: -Immediately invoked lambdas (https://en.wikipedia.org/wiki/Immediately-invoked_function_expression) - -.. code-block:: nim - - let a = (proc (): auto = getFoo())() - let a = block: # preferred - getFoo() - .. _design_for_mcs: -Design with method call syntax (UFCS in other languages) chaining in mind +Design with method call syntax chaining in mind .. code-block:: nim From 22b3e9df27fc65ec49b8ba8ea8de492917988e3d Mon Sep 17 00:00:00 2001 From: Flaviu Tamas Date: Sun, 18 Nov 2018 20:25:59 -0500 Subject: [PATCH 101/110] Revert 7f49364fd0 for nre --- lib/impure/nre.nim | 12 ++++++------ lib/impure/nre/private/util.nim | 6 +++++- tests/stdlib/nre/captures.nim | 6 +++--- tests/stdlib/nre/replace.nim | 4 ++-- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/lib/impure/nre.nim b/lib/impure/nre.nim index 58594f054..4ceab2cca 100644 --- a/lib/impure/nre.nim +++ b/lib/impure/nre.nim @@ -289,7 +289,7 @@ proc `[]`*(pattern: Captures, i: int): string = let bounds = bounds.get return pattern.str.substr(bounds.a, bounds.b) else: - return "" + return nil proc match*(pattern: RegexMatch): string = return pattern.captures[-1] @@ -313,9 +313,9 @@ template toTableImpl(cond: untyped) {.dirty.} = else: result[key] = nextVal -proc toTable*(pattern: Captures, default: string = ""): Table[string, string] = +proc toTable*(pattern: Captures, default: string = nil): Table[string, string] = result = initTable[string, string]() - toTableImpl(nextVal.len == 0) + toTableImpl(nextVal == nil) proc toTable*(pattern: CaptureBounds, default = none(HSlice[int, int])): Table[string, Option[HSlice[int, int]]] = @@ -334,13 +334,13 @@ template itemsImpl(cond: untyped) {.dirty.} = iterator items*(pattern: CaptureBounds, default = none(HSlice[int, int])): Option[HSlice[int, int]] = itemsImpl(nextVal.isNone) -iterator items*(pattern: Captures, default: string = ""): string = - itemsImpl(nextVal.len == 0) +iterator items*(pattern: Captures, default: string = nil): string = + itemsImpl(nextVal == nil) proc toSeq*(pattern: CaptureBounds, default = none(HSlice[int, int])): seq[Option[HSlice[int, int]]] = accumulateResult(pattern.items(default)) -proc toSeq*(pattern: Captures, default: string = ""): seq[string] = +proc toSeq*(pattern: Captures, default: string = nil): seq[string] = accumulateResult(pattern.items(default)) proc `$`*(pattern: RegexMatch): string = diff --git a/lib/impure/nre/private/util.nim b/lib/impure/nre/private/util.nim index a3ae84007..12d2506ea 100644 --- a/lib/impure/nre/private/util.nim +++ b/lib/impure/nre/private/util.nim @@ -10,7 +10,11 @@ proc fget*[K, V](self: Table[K, V], key: K): V = const Ident = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\128'..'\255'} const StartIdent = Ident - {'0'..'9'} -template checkNil(arg: string): string = arg +proc checkNil(arg: string): string = + if arg == nil: + raise newException(ValueError, "Cannot use nil capture") + else: + return arg template formatStr*(howExpr, namegetter, idgetter): untyped = let how = howExpr diff --git a/tests/stdlib/nre/captures.nim b/tests/stdlib/nre/captures.nim index 31de71154..19c344a8d 100644 --- a/tests/stdlib/nre/captures.nim +++ b/tests/stdlib/nre/captures.nim @@ -27,7 +27,7 @@ suite "captures": let ex2 = "foo".find(re("(?foo)(?bar)?")) check(ex2.captures["foo"] == "foo") - check(ex2.captures["bar"] == "") + check(ex2.captures["bar"] == nil) test "named capture bounds": let ex1 = "foo".find(re("(?foo)(?bar)?")) @@ -41,7 +41,7 @@ suite "captures": test "named capture table": let ex1 = "foo".find(re("(?foo)(?bar)?")) - check(ex1.captures.toTable == {"foo" : "foo", "bar" : ""}.toTable()) + check(ex1.captures.toTable == {"foo" : "foo", "bar" : nil}.toTable()) check(ex1.captureBounds.toTable == {"foo" : some(0..2), "bar" : none(Slice[int])}.toTable()) check(ex1.captures.toTable("") == {"foo" : "foo", "bar" : ""}.toTable()) @@ -50,7 +50,7 @@ suite "captures": test "capture sequence": let ex1 = "foo".find(re("(?foo)(?bar)?")) - check(ex1.captures.toSeq == @["foo", ""]) + check(ex1.captures.toSeq == @["foo", nil]) check(ex1.captureBounds.toSeq == @[some(0..2), none(Slice[int])]) check(ex1.captures.toSeq("") == @["foo", ""]) diff --git a/tests/stdlib/nre/replace.nim b/tests/stdlib/nre/replace.nim index b762271a2..516fd4328 100644 --- a/tests/stdlib/nre/replace.nim +++ b/tests/stdlib/nre/replace.nim @@ -16,5 +16,5 @@ suite "replace": check("123".replace(re"(?\d)(\d)", "${foo}$#$#") == "1123") test "replacing missing captures should throw instead of segfaulting": - discard "ab".replace(re"(a)|(b)", "$1$2") - discard "b".replace(re"(a)?(b)", "$1$2") + expect ValueError: discard "ab".replace(re"(a)|(b)", "$1$2") + expect ValueError: discard "b".replace(re"(a)?(b)", "$1$2") From c0a47f7e22039100123eea34a3cb2c956a9eb829 Mon Sep 17 00:00:00 2001 From: Flaviu Tamas Date: Sun, 18 Nov 2018 21:41:40 -0500 Subject: [PATCH 102/110] Rework nil/option for nre in light of ""==nil Fixes #9243 --- changelog.md | 19 +++++ lib/impure/nre.nim | 131 +++++++++++++++++++------------- lib/impure/nre/private/util.nim | 20 +---- tests/stdlib/nre/captures.nim | 31 ++++---- tests/stdlib/nre/match.nim | 6 +- tests/stdlib/nre/replace.nim | 6 +- 6 files changed, 126 insertions(+), 87 deletions(-) diff --git a/changelog.md b/changelog.md index 093ea7ae2..9c1b218f5 100644 --- a/changelog.md +++ b/changelog.md @@ -31,6 +31,25 @@ - `options.UnpackError` is no longer a ref type and inherits from `System.Defect` instead of `System.ValueError`. +- nre's `RegexMatch.{captureBounds,captures}[]` no longer return `Option` or + `nil`/`""`, respectivly. Use the newly added `n in p.captures` method to + check if a group is captured, otherwise you'll recieve an exception. + +- nre's `RegexMatch.{captureBounds,captures}.toTable` no longer accept a + default parameter. Instead uncaptured entries are left empty. Use + `Table.getOrDefault()` if you need defaults. + +- nre's `RegexMatch.captures.{items,toSeq}` now returns an `Option[string]` + instead of a `string`. With the removal of `nil` strings, this is the only + way to indicate a missing match. Inside your loops, instead of `capture == + ""` or `capture == nil`, use `capture.isSome` to check if a capture is + present, and `capture.get` to get its value. + +- nre's `replace()` no longer throws `ValueError` when the replacement string + has missing captures. It instead throws `KeyError` for named captures, and + `IndexError` for un-named captures. This is consistant with + `RegexMatch.{captureBounds,captures}[]`. + #### Breaking changes in the compiler - The compiler now implements the "generic symbol prepass" for `when` statements diff --git a/lib/impure/nre.nim b/lib/impure/nre.nim index 4ceab2cca..94dd89db5 100644 --- a/lib/impure/nre.nim +++ b/lib/impure/nre.nim @@ -65,7 +65,7 @@ runnableExamples: let hasVowel = firstVowel.isSome() if hasVowel: let matchBounds = firstVowel.get().captureBounds[-1] - doAssert matchBounds.get().a == 1 + doAssert matchBounds.a == 1 # Type definitions {{{ @@ -167,14 +167,15 @@ type ## - ``"abc".match(re"(?\w)").get.captures["letter"] == "a"`` ## - ``"abc".match(re"(\w)\w").get.captures[-1] == "ab"`` ## - ## ``captureBounds[]: Option[HSlice[int, int]]`` + ## ``captureBounds[]: HSlice[int, int]`` ## gets the bounds of the given capture according to the same rules as ## the above. If the capture is not filled, then ``None`` is returned. ## The bounds are both inclusive. ## - ## - ``"abc".match(re"(\w)").get.captureBounds[0].get == 0 .. 0`` - ## - ``"abc".match(re"").get.captureBounds[-1].get == 0 .. -1`` - ## - ``"abc".match(re"abc").get.captureBounds[-1].get == 0 .. 2`` + ## - ``"abc".match(re"(\w)").get.captureBounds[0] == 0 .. 0`` + ## - ``0 in "abc".match(re"(\w)").get.captureBounds == true`` + ## - ``"abc".match(re"").get.captureBounds[-1] == 0 .. -1`` + ## - ``"abc".match(re"abc").get.captureBounds[-1] == 0 .. 2`` ## ## ``match: string`` ## the full text of the match. @@ -227,9 +228,10 @@ runnableExamples: doAssert "abc".match(re"(?\w)").get.captures["letter"] == "a" doAssert "abc".match(re"(\w)\w").get.captures[-1] == "ab" - doAssert "abc".match(re"(\w)").get.captureBounds[0].get == 0 .. 0 - doAssert "abc".match(re"").get.captureBounds[-1].get == 0 .. -1 - doAssert "abc".match(re"abc").get.captureBounds[-1].get == 0 .. 2 + doAssert "abc".match(re"(\w)").get.captureBounds[0] == 0 .. 0 + doAssert 0 in "abc".match(re"(\w)").get.captureBounds == true + doAssert "abc".match(re"").get.captureBounds[-1] == 0 .. -1 + doAssert "abc".match(re"abc").get.captureBounds[-1] == 0 .. 2 # }}} proc getinfo[T](pattern: Regex, opt: cint): T = @@ -269,78 +271,99 @@ proc matchesCrLf(pattern: Regex): bool = # }}} # Capture accessors {{{ -proc captureBounds*(pattern: RegexMatch): CaptureBounds = return CaptureBounds(pattern) +func captureBounds*(pattern: RegexMatch): CaptureBounds = return CaptureBounds(pattern) -proc captures*(pattern: RegexMatch): Captures = return Captures(pattern) +func captures*(pattern: RegexMatch): Captures = return Captures(pattern) -proc `[]`*(pattern: CaptureBounds, i: int): Option[HSlice[int, int]] = +func contains*(pattern: CaptureBounds, i: int): bool = let pattern = RegexMatch(pattern) - if pattern.pcreMatchBounds[i + 1].a != -1: - let bounds = pattern.pcreMatchBounds[i + 1] - return some(int(bounds.a) .. int(bounds.b-1)) - else: - return none(HSlice[int, int]) + pattern.pcreMatchBounds[i + 1].a != -1 -proc `[]`*(pattern: Captures, i: int): string = +func contains*(pattern: Captures, i: int): bool = + i in CaptureBounds(pattern) + +func `[]`*(pattern: CaptureBounds, i: int): HSlice[int, int] = + let pattern = RegexMatch(pattern) + if not (i in pattern.captureBounds): + raise newException(IndexError, "Group '" & $i & "' was not captured") + + let bounds = pattern.pcreMatchBounds[i + 1] + int(bounds.a)..int(bounds.b-1) + +func `[]`*(pattern: Captures, i: int): string = let pattern = RegexMatch(pattern) let bounds = pattern.captureBounds[i] - if bounds.isSome: - let bounds = bounds.get - return pattern.str.substr(bounds.a, bounds.b) - else: - return nil + pattern.str.substr(bounds.a, bounds.b) -proc match*(pattern: RegexMatch): string = +func match*(pattern: RegexMatch): string = return pattern.captures[-1] -proc matchBounds*(pattern: RegexMatch): HSlice[int, int] = - return pattern.captureBounds[-1].get +func matchBounds*(pattern: RegexMatch): HSlice[int, int] = + return pattern.captureBounds[-1] -proc `[]`*(pattern: CaptureBounds, name: string): Option[HSlice[int, int]] = +func contains*(pattern: CaptureBounds, name: string): bool = let pattern = RegexMatch(pattern) - return pattern.captureBounds[pattern.pattern.captureNameToId.fget(name)] + let nameToId = pattern.pattern.captureNameToId + if not (name in nameToId): + return false + nameToId[name] in pattern.captureBounds -proc `[]`*(pattern: Captures, name: string): string = +func contains*(pattern: Captures, name: string): bool = + name in CaptureBounds(pattern) + +func checkNamedCaptured(pattern: RegexMatch, name: string): void = + if not (name in pattern.captureBounds): + raise newException(KeyError, "Group '" & name & "' was not captured") + +func `[]`*(pattern: CaptureBounds, name: string): HSlice[int, int] = let pattern = RegexMatch(pattern) - return pattern.captures[pattern.pattern.captureNameToId.fget(name)] + checkNamedCaptured(pattern, name) + pattern.captureBounds[pattern.pattern.captureNameToId[name]] -template toTableImpl(cond: untyped) {.dirty.} = +func `[]`*(pattern: Captures, name: string): string = + let pattern = RegexMatch(pattern) + checkNamedCaptured(pattern, name) + return pattern.captures[pattern.pattern.captureNameToId[name]] + +template toTableImpl() {.dirty.} = for key in RegexMatch(pattern).pattern.captureNameId.keys: - let nextVal = pattern[key] - if cond: - result[key] = default - else: - result[key] = nextVal + if key in pattern: + result[key] = pattern[key] -proc toTable*(pattern: Captures, default: string = nil): Table[string, string] = +func toTable*(pattern: Captures): Table[string, string] = result = initTable[string, string]() - toTableImpl(nextVal == nil) + toTableImpl() -proc toTable*(pattern: CaptureBounds, default = none(HSlice[int, int])): - Table[string, Option[HSlice[int, int]]] = - result = initTable[string, Option[HSlice[int, int]]]() - toTableImpl(nextVal.isNone) +func toTable*(pattern: CaptureBounds): Table[string, HSlice[int, int]] = + result = initTable[string, HSlice[int, int]]() + toTableImpl() -template itemsImpl(cond: untyped) {.dirty.} = +template itemsImpl() {.dirty.} = for i in 0 ..< RegexMatch(pattern).pattern.captureCount: - let nextVal = pattern[i] # done in this roundabout way to avoid multiple yields (potential code # bloat) - let nextYieldVal = if cond: default else: nextVal + let nextYieldVal = if i in pattern: + some(pattern[i]) + else: + default + yield nextYieldVal +iterator items*(pattern: CaptureBounds, + default = none(HSlice[int, int])): Option[HSlice[int, int]] = + itemsImpl() -iterator items*(pattern: CaptureBounds, default = none(HSlice[int, int])): Option[HSlice[int, int]] = - itemsImpl(nextVal.isNone) +iterator items*(pattern: Captures, + default: Option[string] = none(string)): Option[string] = + itemsImpl() -iterator items*(pattern: Captures, default: string = nil): string = - itemsImpl(nextVal == nil) - -proc toSeq*(pattern: CaptureBounds, default = none(HSlice[int, int])): seq[Option[HSlice[int, int]]] = +proc toSeq*(pattern: CaptureBounds, + default = none(HSlice[int, int])): seq[Option[HSlice[int, int]]] = accumulateResult(pattern.items(default)) -proc toSeq*(pattern: Captures, default: string = nil): seq[string] = +proc toSeq*(pattern: Captures, + default: Option[string] = none(string)): seq[Option[string]] = accumulateResult(pattern.items(default)) proc `$`*(pattern: RegexMatch): string = @@ -652,7 +675,8 @@ proc split*(str: string, pattern: Regex, maxSplit = -1, start = 0): seq[string] for cap in match.captures: # if there are captures, include them in the result - result.add(cap) + if cap.isSome: + result.add(cap.get) if splits == maxSplit - 1: break @@ -706,7 +730,8 @@ proc replace*(str: string, pattern: Regex, ## - ``$#`` - first capture ## - ``$0`` - full match ## - ## If a given capture is missing, a ``ValueError`` exception is thrown. + ## If a given capture is missing, ``IndexError`` thrown for un-named captures + ## and ``KeyError`` for named captures. replaceImpl(str, pattern, subproc(match)) proc replace*(str: string, pattern: Regex, diff --git a/lib/impure/nre/private/util.nim b/lib/impure/nre/private/util.nim index 12d2506ea..f7d8b1d60 100644 --- a/lib/impure/nre/private/util.nim +++ b/lib/impure/nre/private/util.nim @@ -1,21 +1,9 @@ ## INTERNAL FILE FOR USE ONLY BY nre.nim. import tables -proc fget*[K, V](self: Table[K, V], key: K): V = - if self.hasKey(key): - return self[key] - else: - raise newException(KeyError, "Key does not exist in table: " & $key) - const Ident = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\128'..'\255'} const StartIdent = Ident - {'0'..'9'} -proc checkNil(arg: string): string = - if arg == nil: - raise newException(ValueError, "Cannot use nil capture") - else: - return arg - template formatStr*(howExpr, namegetter, idgetter): untyped = let how = howExpr var val = newStringOfCap(how.len) @@ -32,7 +20,7 @@ template formatStr*(howExpr, namegetter, idgetter): untyped = i += 2 elif how[i + 1] == '#': var id {.inject.} = lastNum - val.add(checkNil(idgetter)) + val.add(idgetter) lastNum += 1 i += 2 elif how[i + 1] in {'0'..'9'}: @@ -41,7 +29,7 @@ template formatStr*(howExpr, namegetter, idgetter): untyped = while i < how.len and how[i] in {'0'..'9'}: id += (id * 10) + (ord(how[i]) - ord('0')) i += 1 - val.add(checkNil(idgetter)) + val.add(idgetter) lastNum = id + 1 elif how[i + 1] in StartIdent: i += 1 @@ -49,7 +37,7 @@ template formatStr*(howExpr, namegetter, idgetter): untyped = while i < how.len and how[i] in Ident: name.add(how[i]) i += 1 - val.add(checkNil(namegetter)) + val.add(namegetter) elif how[i + 1] == '{': i += 2 var name {.inject.} = "" @@ -57,7 +45,7 @@ template formatStr*(howExpr, namegetter, idgetter): untyped = name.add(how[i]) i += 1 i += 1 - val.add(checkNil(namegetter)) + val.add(namegetter) else: raise newException(Exception, "Syntax error in format string at " & $i) val diff --git a/tests/stdlib/nre/captures.nim b/tests/stdlib/nre/captures.nim index 19c344a8d..bd5e83ecc 100644 --- a/tests/stdlib/nre/captures.nim +++ b/tests/stdlib/nre/captures.nim @@ -9,16 +9,16 @@ suite "captures": test "capture bounds are correct": let ex1 = re("([0-9])") check("1 23".find(ex1).matchBounds == 0 .. 0) - check("1 23".find(ex1).captureBounds[0].get == 0 .. 0) + check("1 23".find(ex1).captureBounds[0] == 0 .. 0) check("1 23".find(ex1, 1).matchBounds == 2 .. 2) check("1 23".find(ex1, 3).matchBounds == 3 .. 3) let ex2 = re("()()()()()()()()()()([0-9])") - check("824".find(ex2).captureBounds[0].get == 0 .. -1) - check("824".find(ex2).captureBounds[10].get == 0 .. 0) + check("824".find(ex2).captureBounds[0] == 0 .. -1) + check("824".find(ex2).captureBounds[10] == 0 .. 0) let ex3 = re("([0-9]+)") - check("824".find(ex3).captureBounds[0].get == 0 .. 2) + check("824".find(ex3).captureBounds[0] == 0 .. 2) test "named captures": let ex1 = "foobar".find(re("(?foo)(?bar)")) @@ -26,13 +26,19 @@ suite "captures": check(ex1.captures["bar"] == "bar") let ex2 = "foo".find(re("(?foo)(?bar)?")) + check("foo" in ex2.captureBounds) check(ex2.captures["foo"] == "foo") - check(ex2.captures["bar"] == nil) + check(not ("bar" in ex2.captures)) + expect KeyError: + discard ex2.captures["bar"] test "named capture bounds": let ex1 = "foo".find(re("(?foo)(?bar)?")) - check(ex1.captureBounds["foo"] == some(0..2)) - check(ex1.captureBounds["bar"] == none(Slice[int])) + check("foo" in ex1.captureBounds) + check(ex1.captureBounds["foo"] == 0..2) + check(not ("bar" in ex1.captures)) + expect KeyError: + discard ex1.captures["bar"] test "capture count": let ex1 = re("(?foo)(?bar)?") @@ -41,19 +47,18 @@ suite "captures": test "named capture table": let ex1 = "foo".find(re("(?foo)(?bar)?")) - check(ex1.captures.toTable == {"foo" : "foo", "bar" : nil}.toTable()) - check(ex1.captureBounds.toTable == {"foo" : some(0..2), "bar" : none(Slice[int])}.toTable()) - check(ex1.captures.toTable("") == {"foo" : "foo", "bar" : ""}.toTable()) + check(ex1.captures.toTable == {"foo" : "foo"}.toTable()) + check(ex1.captureBounds.toTable == {"foo" : 0..2}.toTable()) let ex2 = "foobar".find(re("(?foo)(?bar)?")) check(ex2.captures.toTable == {"foo" : "foo", "bar" : "bar"}.toTable()) test "capture sequence": let ex1 = "foo".find(re("(?foo)(?bar)?")) - check(ex1.captures.toSeq == @["foo", nil]) + check(ex1.captures.toSeq == @[some("foo"), none(string)]) check(ex1.captureBounds.toSeq == @[some(0..2), none(Slice[int])]) - check(ex1.captures.toSeq("") == @["foo", ""]) + check(ex1.captures.toSeq(some("")) == @[some("foo"), some("")]) let ex2 = "foobar".find(re("(?foo)(?bar)?")) - check(ex2.captures.toSeq == @["foo", "bar"]) + check(ex2.captures.toSeq == @[some("foo"), some("bar")]) diff --git a/tests/stdlib/nre/match.nim b/tests/stdlib/nre/match.nim index 38ee5214b..06b69fd04 100644 --- a/tests/stdlib/nre/match.nim +++ b/tests/stdlib/nre/match.nim @@ -10,9 +10,9 @@ suite "match": check("abc".match(re"(\w)").captures[0] == "a") check("abc".match(re"(?\w)").captures["letter"] == "a") check("abc".match(re"(\w)\w").captures[-1] == "ab") - check("abc".match(re"(\w)").captureBounds[0].get == 0 .. 0) - check("abc".match(re"").captureBounds[-1].get == 0 .. -1) - check("abc".match(re"abc").captureBounds[-1].get == 0 .. 2) + check("abc".match(re"(\w)").captureBounds[0] == 0 .. 0) + check("abc".match(re"").captureBounds[-1] == 0 .. -1) + check("abc".match(re"abc").captureBounds[-1] == 0 .. 2) test "match test cases": check("123".match(re"").matchBounds == 0 .. -1) diff --git a/tests/stdlib/nre/replace.nim b/tests/stdlib/nre/replace.nim index 516fd4328..812a7f384 100644 --- a/tests/stdlib/nre/replace.nim +++ b/tests/stdlib/nre/replace.nim @@ -16,5 +16,7 @@ suite "replace": check("123".replace(re"(?\d)(\d)", "${foo}$#$#") == "1123") test "replacing missing captures should throw instead of segfaulting": - expect ValueError: discard "ab".replace(re"(a)|(b)", "$1$2") - expect ValueError: discard "b".replace(re"(a)?(b)", "$1$2") + expect IndexError: discard "ab".replace(re"(a)|(b)", "$1$2") + expect IndexError: discard "b".replace(re"(a)?(b)", "$1$2") + expect KeyError: discard "b".replace(re"(a)?", "${foo}") + expect KeyError: discard "b".replace(re"(?a)?", "${foo}") From df0f0f28589c6aad9fc34a924194aa9932120e6e Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Tue, 11 Dec 2018 23:35:46 +0000 Subject: [PATCH 103/110] custom pragmas in pragma blocks --- compiler/pragmas.nim | 4 ++-- compiler/semstmts.nim | 12 +++++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 247f6ad54..f67e74f11 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -1111,8 +1111,8 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, else: sym.flags.incl sfUsed of wLiftLocals: discard else: invalidPragma(c, it) - elif sym != nil and sym.kind in {skVar, skLet, skParam, skField, skProc, - skFunc, skConverter, skMethod, skType}: + elif sym == nil or (sym != nil and sym.kind in {skVar, skLet, skParam, + skField, skProc, skFunc, skConverter, skMethod, skType}): n.sons[i] = semCustomPragma(c, it) elif sym != nil: illegalCustomPragma(c, it, sym) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 04fe91cfb..aec03b492 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1876,18 +1876,16 @@ proc setLine(n: PNode, info: TLineInfo) = n.info = info proc semPragmaBlock(c: PContext, n: PNode): PNode = + checkSonsLen(n, 2, c.config) let pragmaList = n.sons[0] pragma(c, nil, pragmaList, exprPragmas) - result = semExpr(c, n.sons[1]) - n.sons[1] = result + n[1] = semExpr(c, n[1]) + result = n + result.typ = n[1].typ for i in 0 ..< pragmaList.len: case whichPragma(pragmaList.sons[i]) of wLine: setLine(result, pragmaList.sons[i].info) - of wLocks, wGcSafe, wNosideeffect: - result = n - result.typ = n.sons[1].typ - of wNoRewrite: - incl(result.flags, nfNoRewrite) + of wNoRewrite: incl(result.flags, nfNoRewrite) else: discard proc semStaticStmt(c: PContext, n: PNode): PNode = From 9becb41e0408d6627dcc7acd735ec71147fc929e Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Tue, 11 Dec 2018 23:37:48 +0000 Subject: [PATCH 104/110] Add changelog item --- changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/changelog.md b/changelog.md index 093ea7ae2..f245ce54a 100644 --- a/changelog.md +++ b/changelog.md @@ -94,6 +94,9 @@ proc enumToString*(enums: openArray[enum]): string = - There is a new pragma block `noSideEffect` that works like the `gcsafe` pragma block. - added os.getCurrentProcessId() +- User defined pragmas are now allowed in the pragma blocks +- Pragma blocks are now longer eliminated from the typed AST tree to preserve + pragmas for further analysis by macros ### Language changes From 1d16676dd6a31de03bfc87a5dfdee482b27b51b5 Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Tue, 11 Dec 2018 23:53:59 +0000 Subject: [PATCH 105/110] add test --- tests/pragmas/tcustom_pragma.nim | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/pragmas/tcustom_pragma.nim b/tests/pragmas/tcustom_pragma.nim index ae0f39631..0bc4d2f18 100644 --- a/tests/pragmas/tcustom_pragma.nim +++ b/tests/pragmas/tcustom_pragma.nim @@ -174,3 +174,25 @@ type var foo: Something foo.cardinal = north doAssert foo.b.hasCustomPragma(thingy) == true + + +proc myproc(s: string): int = + {.thingy.}: + s.len + +doAssert myproc("123") == 3 + +let xx = compiles: + proc myproc_bad(s: string): int = + {.not_exist.}: + s.len +doAssert: xx == false + + +macro checkSym(s: typed{nkSym}): untyped = + let body = s.getImpl.body + doAssert body[1].kind == nnkPragmaBlock + doAssert body[1][0].kind == nnkPragma + doAssert body[1][0][0] == bindSym"thingy" + +checkSym(myproc) \ No newline at end of file From cc8ba356f9886d1d0bd8288e5623ff6f9e52b698 Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 12 Dec 2018 11:49:39 +0100 Subject: [PATCH 106/110] advopt.txt: minor layouting change --- doc/advopt.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/advopt.txt b/doc/advopt.txt index 7446775db..60cae7fd0 100644 --- a/doc/advopt.txt +++ b/doc/advopt.txt @@ -11,7 +11,7 @@ Advanced commands: //buildIndex build an index for the whole documentation //run run the project (with Tiny C backend; buggy!) //genDepend generate a DOT file containing the - module dependency graph + module dependency graph //dump dump all defined conditionals and search paths see also: --dump.format:json (useful with: ` | jq`) //check checks the project for syntax and semantic From 77a884f178316155d348808c2e3255a17edef16b Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 12 Dec 2018 12:03:57 +0100 Subject: [PATCH 107/110] export every field of MemFile for more low level trickery; refs #9922 --- lib/pure/memfiles.nim | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim index d2beb629a..f04cf8fee 100644 --- a/lib/pure/memfiles.nim +++ b/lib/pure/memfiles.nim @@ -36,11 +36,12 @@ type size*: int ## size of the memory mapped file when defined(windows): - fHandle: Handle - mapHandle: Handle - wasOpened: bool ## only close if wasOpened + fHandle*: Handle ## **Caution**: Windows specific public field to allow + ## even more low level trickery. + mapHandle*: Handle ## **Caution**: Windows specific public field. + wasOpened*: bool ## **Caution**: Windows specific public field. else: - handle: cint + handle*: cint ## **Caution**: Posix specific public field. proc mapMem*(m: var MemFile, mode: FileMode = fmRead, mappedSize = -1, offset = 0): pointer = From f828e5da491538b35cbd366ab67fdb347f96494e Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 12 Dec 2018 12:10:17 +0100 Subject: [PATCH 108/110] clean up the implementation of the new memfiles.resize --- lib/pure/memfiles.nim | 54 +++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim index f04cf8fee..810223d72 100644 --- a/lib/pure/memfiles.nim +++ b/lib/pure/memfiles.nim @@ -282,34 +282,34 @@ proc flush*(f: var MemFile; attempts: Natural = 3) = if lastErr != EBUSY.OSErrorCode: raiseOSError(lastErr, "error flushing mapping") -proc resize*(f: var MemFile, newFileSize: int) = - ## resize and re-map the file underlying an ``allowRemap MemFile``. NOTE: - ## this assumes the entire file is mapped read-write at offset zero. Also, - ## the value of ``.mem`` will probably change. - when defined(windows): - discard #TODO This needs to be implemented. - else: - if f.handle == -1: - raise newException(IOError, - "Cannot resize MemFile opened with allowRemap=false") - if ftruncate(f.handle, newFileSize) == -1: - raiseOSError(osLastError()) - when defined(linux): #Maybe NetBSD, too? - #On Linux this can be over 100 times faster than a munmap,mmap cycle. - proc mremap(old: pointer; oldSize,newSize: csize; flags: cint): pointer {. - importc: "mremap", header: "" .} - let newAddr = mremap(f.mem, csize(f.size), csize(newFileSize), cint(1)) - if newAddr == cast[pointer](MAP_FAILED): +when defined(posix) or defined(nimdoc): + proc resize*(f: var MemFile, newFileSize: int) {.raises: [IOError, OSError].} = + ## resize and re-map the file underlying an ``allowRemap MemFile``. + ## **Note**: this assumes the entire file is mapped read-write at offset zero. + ## Also, the value of ``.mem`` will probably change. + ## **Note**: This is not (yet) avaiable on Windows. + when defined(posix): + if f.handle == -1: + raise newException(IOError, + "Cannot resize MemFile opened with allowRemap=false") + if ftruncate(f.handle, newFileSize) == -1: raiseOSError(osLastError()) - else: - if munmap(f.mem, f.size) != 0: - raiseOSError(osLastError()) - let newAddr = mmap(nil, newFileSize, PROT_READ or PROT_WRITE, - MAP_SHARED or MAP_POPULATE, f.handle, 0) - if newAddr == cast[pointer](MAP_FAILED): - raiseOSError(osLastError()) - f.mem = newAddr - f.size = newFileSize + when defined(linux): #Maybe NetBSD, too? + #On Linux this can be over 100 times faster than a munmap,mmap cycle. + proc mremap(old: pointer; oldSize,newSize: csize; flags: cint): pointer {. + importc: "mremap", header: "" .} + let newAddr = mremap(f.mem, csize(f.size), csize(newFileSize), cint(1)) + if newAddr == cast[pointer](MAP_FAILED): + raiseOSError(osLastError()) + else: + if munmap(f.mem, f.size) != 0: + raiseOSError(osLastError()) + let newAddr = mmap(nil, newFileSize, PROT_READ or PROT_WRITE, + MAP_SHARED or MAP_POPULATE, f.handle, 0) + if newAddr == cast[pointer](MAP_FAILED): + raiseOSError(osLastError()) + f.mem = newAddr + f.size = newFileSize proc close*(f: var MemFile) = ## closes the memory mapped file `f`. All changes are written back to the From f080a15da1ef34994d38779d630a4ee7dc81715d Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 12 Dec 2018 16:17:35 +0100 Subject: [PATCH 109/110] diff.nim: massive code cleanups --- lib/std/diff.nim | 254 +++++++++++++++++------------------------------ 1 file changed, 89 insertions(+), 165 deletions(-) diff --git a/lib/std/diff.nim b/lib/std/diff.nim index 940b5888d..bffce2803 100644 --- a/lib/std/diff.nim +++ b/lib/std/diff.nim @@ -1,145 +1,90 @@ +# +# +# Nim's Runtime Library +# (c) Copyright 2018 Nim contributors +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# -## This Class implements the Difference Algorithm published in -## "An O(ND) Difference Algorithm and its Variations" by Eugene Myers -## Algorithmica Vol. 1 No. 2, 1986, p 251. -## -## There are many C, Java, Lisp implementations public available but they all seem to come -## from the same source (diffutils) that is under the (unfree) GNU public License -## and cannot be reused as a sourcecode for a commercial application. -## There are very old C implementations that use other (worse) algorithms. -## Microsoft also published sourcecode of a diff-tool (windiff) that uses some tree data. -## Also, a direct transfer from a C source to C# is not easy because there is a lot of pointer -## arithmetic in the typical C solutions and i need a managed solution. -## These are the reasons why I implemented the original published algorithm from the scratch and -## make it avaliable without the GNU license limitations. -## I do not need a high performance diff tool because it is used only sometimes. -## I will do some performace tweaking when needed. -## -## The algorithm itself is comparing 2 arrays of numbers so when comparing 2 text documents -## each line is converted into a (hash) number. See diffText(). -## -## Some chages to the original algorithm: -## The original algorithm was described using a recursive approach and comparing zero indexed arrays. -## Extracting sub-arrays and rejoining them is very performance and memory intensive so the same -## (readonly) data arrays are passed arround together with their lower and upper bounds. -## This circumstance makes the lcs and sms functions more complicate. -## I added some code to the lcs function to get a fast response on sub-arrays that are identical, -## completely deleted or inserted. -## -## The result from a comparisation is stored in 2 arrays that flag for modified (deleted or inserted) -## lines in the 2 data arrays. These bits are then analysed to produce a array of Item objects. -## -## Further possible optimizations: -## (first rule: don't do it; second: don't do it yet) -## The arrays dataA and dataB are passed as parameters, but are never changed after the creation -## so they can be members of the class to avoid the paramter overhead. -## In sms is a lot of boundary arithmetic in the for-D and for-k loops that can be done by increment -## and decrement of local variables. -## The downVector and upVector arrays are alywas created and destroyed each time the sms gets called. -## It is possible to reuse tehm when transfering them to members of the class. -## See TODO: hints. -## -## diff.cs: A port of the algorythm to C# -## Copyright (c) by Matthias Hertel, http://www.mathertel.de -## This work is licensed under a BSD style license. See http://www.mathertel.de/License.aspx -## -## Changes: -## 2002.09.20 There was a "hang" in some situations. -## Now I undestand a little bit more of the sms algorithm. -## There have been overlapping boxes; that where analyzed partial differently. -## One return-point is enough. -## A assertion was added in createDiffs when in debug-mode, that counts the number of equal (no modified) lines in both arrays. -## They must be identical. -## -## 2003.02.07 Out of bounds error in the Up/Down vector arrays in some situations. -## The two vetors are now accessed using different offsets that are adjusted using the start k-Line. -## A test case is added. -## -## 2006.03.05 Some documentation and a direct Diff entry point. -## -## 2006.03.08 Refactored the API to static methods on the Diff class to make usage simpler. -## 2006.03.10 using the standard Debug class for self-test now. -## compile with: csc /target:exe /out:diffTest.exe /d:DEBUG /d:TRACE /d:SELFTEST Diff.cs -## 2007.01.06 license agreement changed to a BSD style license. -## 2007.06.03 added the optimize method. -## 2007.09.23 upVector and downVector optimization by Jan Stoklasa (). -## 2008.05.31 Adjusted the testing code that failed because of the optimize method (not a bug in the diff algorithm). -## 2008.10.08 Fixing a test case and adding a new test case. -## 2018.12.07 Port to Nim. +## This module implements an algorithm to compute the +## `diff`:idx: between two sequences of lines. + +# code owner: Arne Döring +# +# This is based on C# code written by Matthias Hertel, http://www.mathertel.de +# +# This Class implements the Difference Algorithm published in +# "An O(ND) Difference Algorithm and its Variations" by Eugene Myers +# Algorithmica Vol. 1 No. 2, 1986, p 251. import tables, strutils type - Item* = object + Item* = object ## An Item in the list of differences. startA*: int ## Start Line number in Data A. startB*: int ## Start Line number in Data B. deletedA*: int ## Number of changes in Data A. insertedB*: int ## Number of changes in Data B. - DiffData = object - ## Data on one input file being compared. - len: int ## Number of elements (lines). + DiffData = object ## Data on one input file being compared. data: seq[int] ## Buffer of numbers that will be compared. modified: seq[bool] ## Array of booleans that flag for modified - ## data. This is the result of the diff. + ## data. This is the result of the diff. ## This means deletedA in the first Data or ## inserted in the second Data. - SMSRD = object - x,y: int + Smsrd = object + x, y: int -proc newDiffData(initData: seq[int]): DiffData = - ## Initialize the Diff-Data buffer. - result.len = initData.len - result.data = initData - result.modified = newSeq[bool](result.len + 2) +# template to avoid a seq copy. Required until ``sink`` parameters are ready. +template newDiffData(initData: seq[int]; L: int): DiffData = + DiffData( + data: initData, + modified: newSeq[bool](L + 2) + ) -proc diffCodes(aText: string; h: var Table[string,int]): seq[int] = +proc len(d: DiffData): int {.inline.} = d.data.len + +proc diffCodes(aText: string; h: var Table[string, int]): DiffData = ## This function converts all textlines of the text into unique numbers for every unique textline ## so further work can work only with simple numbers. ## ``aText`` the input text ## ``h`` This extern initialized hashtable is used for storing all ever used textlines. ## ``trimSpace`` ignore leading and trailing space characters ## Returns a array of integers. - - # get all codes of the text var lastUsedCode = h.len - var codes = newSeq[int]() + result.data = newSeq[int]() for s in aText.splitLines: if h.contains s: - codes.add h[s] + result.data.add h[s] else: inc lastUsedCode h[s] = lastUsedCode - codes.add lastUsedCode + result.data.add lastUsedCode + result.modified = newSeq[bool](result.data.len + 2) - return codes - -proc optimize(data: var DiffData): void = +proc optimize(data: var DiffData) = ## If a sequence of modified lines starts with a line that contains the same content ## as the line that appends the changes, the difference sequence is modified so that the ## appended line and not the starting line is marked as modified. ## This leads to more readable diff sequences when comparing text files. - ## ``data`` A Diff data buffer containing the identified changes. - - var startPos, endPos: int - startPos = 0 - + var startPos = 0 while startPos < data.len: - while (startPos < data.len) and (data.modified[startPos] == false): + while startPos < data.len and not data.modified[startPos]: inc startPos - endPos = startPos - while (endPos < data.len) and (data.modified[endPos] == true): + var endPos = startPos + while endPos < data.len and data.modified[endPos]: inc endPos - if (endPos < data.len) and (data.data[startPos] == data.data[endPos]): + if endPos < data.len and data.data[startPos] == data.data[endPos]: data.modified[startPos] = false data.modified[endPos] = true else: startPos = endPos proc sms(dataA: var DiffData; lowerA, upperA: int; dataB: DiffData; lowerB, upperB: int; - downVector, upVector: var openArray[int]): SMSRD = + downVector, upVector: var openArray[int]): Smsrd = ## This is the algorithm to find the Shortest Middle Snake (sms). ## ``dataA`` sequence A ## ``lowerA`` lower bound of the actual range in dataA @@ -151,10 +96,10 @@ proc sms(dataA: var DiffData; lowerA, upperA: int; dataB: DiffData; lowerB, uppe ## ``upVector`` a vector for the (u,v) to (N,M) search. Passed as a parameter for speed reasons. ## Returns a MiddleSnakeData record containing x,y and u,v. - let max: int = dataA.len + dataB.len + 1 + let max = dataA.len + dataB.len + 1 - let downK = lowerA - lowerB; # the k-line to start the forward search - let upK = upperA - upperB; # the k-line to start the reverse search + let downK = lowerA - lowerB # the k-line to start the forward search + let upK = upperA - upperB # the k-line to start the reverse search let delta = (upperA - lowerA) - (upperB - lowerB) let oddDelta = (delta and 1) != 0 @@ -166,75 +111,64 @@ proc sms(dataA: var DiffData; lowerA, upperA: int; dataB: DiffData; lowerB, uppe let maxD = ((upperA - lowerA + upperB - lowerB) div 2) + 1 - # Debug.Write(2, "sms", String.Format("Search the box: A[{0}-{1}] to B[{2}-{3}]", lowerA, upperA, lowerB, upperB)) - - # init vectors downVector[downOffset + downK + 1] = lowerA upVector[upOffset + upK - 1] = upperA for D in 0 .. maxD: - # Extend the forward path. - for k in countUp(downK - D, downK + D, 2): - # Debug.Write(0, "sms", "extend forward path " + k.ToString()) - # find the only or better starting point - var x, y: int + var x: int if k == downK - D: - x = downVector[downOffset + k + 1]; # down + x = downVector[downOffset + k + 1] # down else: - x = downVector[downOffset + k - 1] + 1; # a step to the right - if (k < downK + D) and (downVector[downOffset + k + 1] >= x): - x = downVector[downOffset + k + 1]; # down + x = downVector[downOffset + k - 1] + 1 # a step to the right + if k < downK + D and downVector[downOffset + k + 1] >= x: + x = downVector[downOffset + k + 1] # down - y = x - k + var y = x - k # find the end of the furthest reaching forward D-path in diagonal k. - while (x < upperA) and (y < upperB) and (dataA.data[x] == dataB.data[y]): + while x < upperA and y < upperB and dataA.data[x] == dataB.data[y]: inc x inc y downVector[downOffset + k] = x # overlap ? - if oddDelta and (upK - D < k) and (k < upK + D): + if oddDelta and upK - D < k and k < upK + D: if upVector[upOffset + k] <= downVector[downOffset + k]: - result.x = downVector[downOffset + k] - result.y = downVector[downOffset + k] - k - return + return Smsrd(x: downVector[downOffset + k], + y: downVector[downOffset + k] - k) # Extend the reverse path. for k in countUp(upK - D, upK + D, 2): - # Debug.Write(0, "sms", "extend reverse path " + k.ToString()) - # find the only or better starting point - var x, y: int + var x: int if k == upK + D: - x = upVector[upOffset + k - 1]; # up + x = upVector[upOffset + k - 1] # up else: - x = upVector[upOffset + k + 1] - 1; # left - if (k > upK - D) and (upVector[upOffset + k - 1] < x): - x = upVector[upOffset + k - 1]; # up - # if - y = x - k + x = upVector[upOffset + k + 1] - 1 # left + if k > upK - D and upVector[upOffset + k - 1] < x: + x = upVector[upOffset + k - 1] # up - while (x > lowerA) and (y > lowerB) and (dataA.data[x - 1] == dataB.data[y - 1]): + var y = x - k + while x > lowerA and y > lowerB and dataA.data[x - 1] == dataB.data[y - 1]: dec x dec y upVector[upOffset + k] = x # overlap ? - if (not oddDelta) and (downK - D <= k) and (k <= downK + D): + if not oddDelta and downK-D <= k and k <= downK+D: if upVector[upOffset + k] <= downVector[downOffset + k]: - result.x = downVector[downOffset + k] - result.y = downVector[downOffset + k] - k - return + return Smsrd(x: downVector[downOffset + k], + y: downVector[downOffset + k] - k) assert false, "the algorithm should never come here." -proc lcs(dataA: var DiffData; lowerA, upperA: int; dataB: var DiffData; lowerB, upperB: int; downVector, upVector: var openArray[int]): void = +proc lcs(dataA: var DiffData; lowerA, upperA: int; dataB: var DiffData; lowerB, upperB: int; + downVector, upVector: var openArray[int]) = ## This is the divide-and-conquer implementation of the longes common-subsequence (lcs) ## algorithm. ## The published algorithm passes recursively parts of the A and B sequences. @@ -247,14 +181,13 @@ proc lcs(dataA: var DiffData; lowerA, upperA: int; dataB: var DiffData; lowerB, ## ``upperB`` upper bound of the actual range in dataB (exclusive) ## ``downVector`` a vector for the (0,0) to (x,y) search. Passed as a parameter for speed reasons. ## ``upVector`` a vector for the (u,v) to (N,M) search. Passed as a parameter for speed reasons. - # make mutable copy + + # make mutable copy: var lowerA = lowerA var lowerB = lowerB var upperA = upperA var upperB = upperB - # Debug.Write(2, "lcs", String.Format("Analyse the box: A[{0}-{1}] to B[{2}-{3}]", lowerA, upperA, lowerB, upperB)) - # Fast walkthrough equal lines at the start while lowerA < upperA and lowerB < upperB and dataA.data[lowerA] == dataB.data[lowerB]: inc lowerA @@ -286,20 +219,16 @@ proc lcs(dataA: var DiffData; lowerA, upperA: int; dataB: var DiffData; lowerB, lcs(dataA, lowerA, smsrd.x, dataB, lowerB, smsrd.y, downVector, upVector) lcs(dataA, smsrd.x, upperA, dataB, smsrd.y, upperB, downVector, upVector) # 2002.09.20: no need for 2 points -# lcs() - proc createDiffs(dataA, dataB: DiffData): seq[Item] = ## Scan the tables of which lines are inserted and deleted, ## producing an edit script in forward order. - - var startA: int - var startB: int - var lineA: int - var lineB: int - + var startA = 0 + var startB = 0 + var lineA = 0 + var lineB = 0 while lineA < dataA.len or lineB < dataB.len: - if (lineA < dataA.len) and (not dataA.modified[lineA]) and - (lineB < dataB.len) and (not dataB.modified[lineB]): + if lineA < dataA.len and not dataA.modified[lineA] and + lineB < dataB.len and not dataB.modified[lineB]: # equal lines inc lineA inc lineB @@ -309,21 +238,16 @@ proc createDiffs(dataA, dataB: DiffData): seq[Item] = startB = lineB while lineA < dataA.len and (lineB >= dataB.len or dataA.modified[lineA]): - # while (lineA < dataA.len and dataA.modified[lineA]) inc lineA while lineB < dataB.len and (lineA >= dataA.len or dataB.modified[lineB]): - # while (lineB < dataB.len and dataB.modified[lineB]) inc lineB if (startA < lineA) or (startB < lineB): - # store a new difference-item - var aItem: Item - aItem.startA = startA - aItem.startB = startB - aItem.deletedA = lineA - startA - aItem.insertedB = lineB - startB - result.add aItem + result.add Item(startA: startA, + startB: startB, + deletedA: lineA - startA, + insertedB: lineB - startB) proc diffInt*(arrayA, arrayB: openArray[int]): seq[Item] = @@ -333,10 +257,10 @@ proc diffInt*(arrayA, arrayB: openArray[int]): seq[Item] = ## Returns a array of Items that describe the differences. # The A-Version of the data (original data) to be compared. - var dataA = newDiffData(@arrayA) + var dataA = newDiffData(@arrayA, arrayA.len) # The B-Version of the data (modified data) to be compared. - var dataB = newDiffData(@arrayB) + var dataB = newDiffData(@arrayB, arrayB.len) let max = dataA.len + dataB.len + 1 ## vector for the (0,0) to (x,y) search @@ -345,9 +269,9 @@ proc diffInt*(arrayA, arrayB: openArray[int]): seq[Item] = var upVector = newSeq[int](2 * max + 2) lcs(dataA, 0, dataA.len, dataB, 0, dataB.len, downVector, upVector) - return createDiffs(dataA, dataB) + result = createDiffs(dataA, dataB) -proc diffText*(textA,textB: string): seq[Item] = +proc diffText*(textA, textB: string): seq[Item] = ## Find the difference in 2 text documents, comparing by textlines. ## The algorithm itself is comparing 2 arrays of numbers so when comparing 2 text documents ## each line is converted into a (hash) number. This hash-value is computed by storing all @@ -361,12 +285,12 @@ proc diffText*(textA,textB: string): seq[Item] = ## Returns a seq of Items that describe the differences. # prepare the input-text and convert to comparable numbers. - var h = initTable[string,int]() # TextA.len + TextB.len <- probably wrong initial size + var h = initTable[string, int]() # TextA.len + TextB.len <- probably wrong initial size # The A-Version of the data (original data) to be compared. - var dataA = newDiffData(diffCodes(textA, h)) + var dataA = diffCodes(textA, h) # The B-Version of the data (modified data) to be compared. - var dataB = newDiffData(diffCodes(textB, h)) + var dataB = diffCodes(textB, h) h.clear # free up hashtable memory (maybe) @@ -380,7 +304,7 @@ proc diffText*(textA,textB: string): seq[Item] = optimize(dataA) optimize(dataB) - return createDiffs(dataA, dataB) + result = createDiffs(dataA, dataB) when isMainModule: @@ -390,7 +314,7 @@ when isMainModule: $it.deletedA & "." & $it.insertedB & "." & $it.startA & "." & $it.startB & "*" ) - proc main(): void = + proc main() = var a, b: string stdout.writeLine("Diff Self Test...") From 070bcf4cea28a3238089379f5884787b2084b2de Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 12 Dec 2018 16:27:37 +0100 Subject: [PATCH 110/110] added diff.nim to the stdlib --- changelog.md | 3 +++ doc/lib.rst | 4 ++++ tools/kochdocs.nim | 1 + 3 files changed, 8 insertions(+) diff --git a/changelog.md b/changelog.md index 62450d58e..024109df9 100644 --- a/changelog.md +++ b/changelog.md @@ -86,6 +86,9 @@ proc enumToString*(enums: openArray[enum]): string = - Added `macros.isInstantiationOf` for checking if the proc symbol is instantiation of generic proc symbol. +- There is a new stdlib mdoule `std/diff` to compute the famous "diff" + of two texts by line. + ### Library changes diff --git a/doc/lib.rst b/doc/lib.rst index 46e1f9d19..c0119d36d 100644 --- a/doc/lib.rst +++ b/doc/lib.rst @@ -154,6 +154,10 @@ String handling * `std/wordwrap `_ This module contains an algorithm to wordwrap a Unicode string. +* `std/diff `_ + This module contains an algorithm to compute the famous "diff" + of two texts by line. + Generic Operating System Services --------------------------------- diff --git a/tools/kochdocs.nim b/tools/kochdocs.nim index 7cd13b2ac..03a694449 100644 --- a/tools/kochdocs.nim +++ b/tools/kochdocs.nim @@ -129,6 +129,7 @@ lib/pure/math.nim lib/pure/matchers.nim lib/std/editdistance.nim lib/std/wordwrap.nim +lib/std/diff.nim lib/pure/algorithm.nim lib/pure/stats.nim lib/windows/winlean.nim