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 0b3708a7ce..15ce5d0741 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 b7c7f9f5a6..a288af7819 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 2d21a60199..8471d70d16 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 8471d70d16..b3ec6d5106 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 ca17057b5d..b81f6c0fca 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 b81f6c0fca..ee930018a4 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 ee930018a4..a4bed4674a 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 a4bed4674a..a26a4d379b 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 a26a4d379b..352b4aaade 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 7cf35450bd..2b595aee1e 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 34836d8431..bf1494b3d0 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 352b4aaade..4703c31dd8 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 669862c564..517356434e 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 f46a368b1a..9597d18fd5 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 4703c31dd8..82db5af7f2 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 9111ddd86c..ec0dd629ce 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 82db5af7f2..59ee5dcb63 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 59ee5dcb63..3811cccad2 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 3811cccad2..56f941514a 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 9597d18fd5..ce87deea07 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 0000000000..940b5888d8 --- /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 2b595aee1e..7cf35450bd 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 bf1494b3d0..0cb3d3ad55 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 517356434e..669862c564 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 ec0dd629ce..9111ddd86c 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 0cb3d3ad55..34836d8431 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 56f941514a..ebe8d1185c 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 ce87deea07..e7a4d1de0e 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 ebe8d1185c..158e8cc4ad 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 e7a4d1de0e..f46a368b1a 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 158e8cc4ad..74a796e7cf 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 aef4f1ce60..36319a3179 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 13887acc99..0000000000 --- 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 6dbfa1a2db..093ea7ae2e 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 12e38d8b53..b827e1aa3b 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 2fb4e52411..91d6bd7452 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 83c62b7bbf..eb9cb08aae 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 eb9cb08aae..dce8541469 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 40a05e6bf8..0247acb036 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 09a1cd436e..0f9220102b 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 874cb4bd08..ddde1be311 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 924e53b667..8332af346e 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 08917cb292..ddec457a1a 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 17f61c7dd0..09991048eb 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 48aa75528e..2e2a3a20aa 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 a011a8fc83..1e75b563ef 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 da86d63dc1..91fa26596d 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 74a796e7cf..75cf86124e 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 75cf86124e..c5f49984e4 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 b23cd598ec..d177e1f881 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 59ef05f9c5..cab2c78f5c 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 7e7ec8903c..c8784c3e7d 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 0000000000..9fd30f3319 --- /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 3d8e5645b6..247f6ad54e 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 c5f49984e4..bed60a3e01 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 bed60a3e01..b14615e408 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 91d6bd7452..db03ac2e05 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 a011a8fc83..294cabe477 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 0000000000..ca135ed50c --- /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 72c3f4f49a..45066e443c 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 ca135ed50c..fa086517f7 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 48aa75528e..7be4f6f052 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 0000000000..be82edc45b --- /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 0000000000..ef0c69db1c --- /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 0000000000..e9c9abf876 --- /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 be82edc45b..646f030a17 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 ef0c69db1c..0dd32430e9 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 e9c9abf876..2806a78ed1 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 294cabe477..4cc759e529 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 fa086517f7..b9d37b67b7 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 0000000000..7ff3d1ff73 --- /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 646f030a17..daba463744 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 9a8d38a79e..bd10224b6a 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 b14615e408..1d4cdcc9bb 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 1d4cdcc9bb..32d6c253bb 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 32d6c253bb..a090bead27 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 a090bead27..7d2bb72215 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 59ef05f9c5..6b3b9b63f1 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 3545edc88c..457a6e176e 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 5ec7022576..305ed9bcf9 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 7e9de4b73e..b283cd4b10 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 d103af710e..638e71f04d 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 d3651f6590..6f4e8ce377 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 0000000000..1c9e7c068d --- /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 03105b41b9..57ad38b85e 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 0000000000..86d3494577 --- /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 fa17e9851c..576a7dc7fe 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 7cd72f6c3a..11af58392e 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 6afe57d87f..fb8fe84437 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 7cd72f6c3a..7677ba0d31 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 576a7dc7fe..40283489c1 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 11af58392e..eca7b0a084 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 7d2bb72215..407204e515 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 e5345e645c..61eff3295d 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 a6da8f5a33..800b5cd2f0 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 407204e515..40af11e70c 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 4cc759e529..eed82adeb5 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 45066e443c..abd0bf501f 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 5ec7022576..df6298eb02 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 df2c084a19..7e61854b8d 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 4252142d73..130f28e21f 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 a9813f5c52..4d22c4224d 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 0247acb036..5f5f296cbc 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 b2671d81e5..60eecbdc5d 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 cba07446fa..f5014fa8ca 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 d05b301aeb..63fa597fff 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 bec4a59a4c..735c6f6b16 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 61eff3295d..b742423708 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 b742423708..d2beb629a2 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 e1f173c26a..6694e3f0e6 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 86fc8bed44..a86544c27f 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 59c0171b49..1c105c97f9 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 70ff591368..9f536e6c97 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 4c3c687e2b..abd115701f 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 a60831f9d0..9c8525d724 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 bd10224b6a..3f528a1b2c 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 136d65cc7a..0000000000 --- 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 986e348360..0000000000 --- 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 620e0c059e..0000000000 --- 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 378320014d..0000000000 --- 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 72ba46b044..0000000000 --- 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 4a975e5df2..0000000000 --- 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 6237c4e79e..0000000000 --- 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 0be8c7f4fb..0000000000 --- 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 21d5ea962d..0000000000 --- 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 2214bf02c1..0000000000 --- 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 177d82f20b..0000000000 --- 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 b1695b9c7a..0000000000 --- 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 05ef517dc2..0000000000 --- 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 281e562d79..0000000000 --- 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 035590dc37..0000000000 --- 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 a4bc5c0e61..0000000000 --- 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 d52f611d6c..0000000000 --- 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 e911c1360b..0000000000 --- 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 46cff6241d..0000000000 --- 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 4676ed71e2..0000000000 --- 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 6e6b21ef0f..0000000000 --- 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 12fd750deb..0000000000 --- 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 8f8b667647..0000000000 --- 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 31a2d3baaa..0000000000 --- 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 fafeff93b7..0000000000 --- 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 95fb6c6240..0000000000 --- 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 a322908ac6..0000000000 --- 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 7f8f1213da..0000000000 --- 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 69c9a39272..0000000000 --- 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 c87295092e..0000000000 --- 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 1143214922..0000000000 --- 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 1c105c97f9..60cf464237 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 385f1171c1..a1de5859a2 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 6694e3f0e6..b641430a15 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 a86544c27f..9b2347bf95 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 60cf464237..d8c0f2e112 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 2d1dd6c3cd..1abe42089f 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 b641430a15..38f61ce33f 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 9b2347bf95..3cfddc414f 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 d8c0f2e112..111b701bec 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 3cfddc414f..d4f4a73710 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 111b701bec..27a3ec0891 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 2d7ee13369..be9d0ae9c6 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 38f61ce33f..3d7b6a7d7b 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 27a3ec0891..a82467df72 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 a1de5859a2..c2658d6a00 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 a82467df72..6a6b735071 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 b991dd57f1..efe679d676 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 d4f4a73710..3583166fe2 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 6a6b735071..448471136d 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 448471136d..7dfcf9d48b 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 02e4bfd807..a8638e236c 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 3d7b6a7d7b..6ab14a2cf3 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 3583166fe2..6c9fafa130 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 d9115e16d5..bd0f41717c 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 8e288e73a7..747f1a086e 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 b25dadfd63..0558517bd0 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 67522d7c9a..aa740c38f7 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 8551d324c5..d128086687 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 9f09fd405a..b6ebe55c85 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 fce7af6691..f6ed32b58b 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 b5f2fb715d..99929f080a 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 cb03b50043..b421802aed 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 46cc23dd1d..2278957ac5 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 102a4ce4c0..ce4df1fc92 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 679831b27b..a13a171c38 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 f4e2cdcf24..55b66aaefc 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 3e30e8ba86..3c318dbf71 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 e7a2ec1d92..fcb48a1f52 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 3dac379b20..f63a879903 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 fa81235fef..8155202940 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 7aa1d7fb07..3a34478ca0 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 c7b71a2f7e..3043b680ad 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 1aeebe9b45..c038be6405 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 752bb3e75b..a87c5df959 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 2122609221..88a5eb32ec 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 0fe9efdc1a..b13c57951d 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 98fb5dfd5a..67903cc5eb 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 69ad80f470..b5772d5ac8 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 7a89866444..be6d3a1674 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 b442c05247..7dbd5a3d09 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 825acb6135..a5537d8cb8 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 94193e921a..64c5d6c269 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 6fcf954330..49c37ae2e0 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 799b143817..fc2eeda1a0 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 ecdd126038..4bcd4e39d3 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 8c3a99c97f..f16b323de3 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 9ab9e8d645..89aa4e2e86 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 ea08388eb7..1354551c1d 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 24543f1b88..4fdac8191b 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 3527c93854..e9651c69f4 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 4a9479a5f6..4a1cb3ea62 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 333700197f..465080e842 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 ffaa91ff3d..eda475d4fd 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 edf4803485..727bfbffb8 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 cd9b15e25b..86726af72b 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 4e5f61f06d..b2d8bd28d7 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 8455593098..2d58f02152 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 31c4976f88..0cbdaf39eb 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 f8d69011ad..dbbe9ba585 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 e044b9f3fa..5679a6e379 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 ff6673bba3..2f8cfece78 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 4d11f56f26..f1355e7475 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 dec1dafe07..d0bc76c20f 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 5c8e02440f..ac0c972f52 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 b9cf5d00be..a169bf4533 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 b16be6c507..b911de5489 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 3c9fdc3543..3ca01cfd5b 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 9f947f859f..abf07b21c8 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 a3f7174c92..e04f1b7157 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 e3a780dfe5..70c8445131 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 8f43c5d8f4..e0f816c7d1 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 25b001d520..23c1a3d96d 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 9cc5c7e062..ac168952e9 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 5e1a3f03ed..757f4e7273 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 8d59e7fec0..7d2997b3ff 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 5658f4ba2e..499b060091 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 16de38f603..5bdb97f375 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 ef76c9130b..767845cb44 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 0fa789869e..e4b50aba50 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 cbd11f722e..ee5470c47c 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 0025c10c5e..88cc0efa93 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 d146794b60..ff207df59e 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 e486d32e7f..ca68165616 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 5ed541300a..b2e5f3379b 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 e15fbc3d15..c3801ba286 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 ecc79580c9..d6c192cbf8 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 6d13dd162c..76f368f8a4 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 f0a97658a7..720e080c0d 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 2a05da9c0f..b7560a605b 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 00dd8ed9fc..6548192c60 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 02125d2c03..463e956135 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 7a218b4443..c5b1dd8414 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 f1acf2774c..dae1a468a5 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 6098672a22..9053d397d3 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 3aa707ff6e..feaf1bc967 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 bf26f49033..acb83d2c8a 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 79523a8835..167d09b960 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 b2a11d34f2..17a38aa534 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 f0fa2bf27c..6ca311d38f 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 b224d4c835..9c656f3d9d 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 6c9759cf54..742670cc16 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 0fb835bc6e..75d8dd0812 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 989ca8bcba..bf83ab972d 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 ed99260ea8..54d49a7c15 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 b84120fbad..130c71087e 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 a14c6c3960..01f3cb9dfb 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 68df56be8c..56280111c2 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 aa7dc6c533..0708838fc9 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 8e043a658f..c4cd6e9327 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 5fd0d43d99..a6d7af10bf 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 aa288d3423..29937a8624 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 e8aa4a1d91..c4f561f090 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 639675f35d..abf02a7568 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 8a128d828a..b1e9cbf436 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 707e981fab..1e731d1d4b 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 eb46b51573..4f63cc5f58 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 13163f7645..b4507e2988 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 ac0197c1a0..f093e54d40 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 5abcad4a9c..9b76423636 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 1559041aa3..83d800c823 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 6c410e945b..c4c7d4a163 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 cc603fd850..9dcfd7be5b 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 9b52f8055b..912883a632 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 bbd50fcb1e..3c508dca7b 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 b7c8fee80d..b8c2f7c663 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 9eea085e39..b9aa2cbcaa 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 dacdbdfd78..7b61326f41 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 33394219ba..577b8c4f15 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 6703ba2549..25d7b9bf71 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 2df15fa5ca..63e7d6128a 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 ffbde48fd1..2185c3074d 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 08ab82a222..6bf7624f34 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 bc8793e4e4..eb6efc1311 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 9c2fe69df5..e09cda54ac 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 095d9570e5..dc939bcd26 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 d13baf7ff4..004ebc0a70 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 f64f369773..1896a2898c 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 e4acdc3217..bb562cacb5 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 fa00ba9de6..e718d25f94 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 69ebe3da33..d804178bc1 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 305f40ac52..8b8e1c3a90 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 4fd32a9326..076009eb9d 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 ad6aa65896..09d505f941 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 0cfe24c709..005294d64b 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 62ccfbe162..f600238181 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 a0afab9e84..fb89dc8b17 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 a5360423dc..4b30e96e6e 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 c83235659b..ee7455d4cb 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 caf674084b..045c9fc5b0 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 6e8fdc7386..829da5173b 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 95318ce9b8..0000000000 --- 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 7819775e3a..91f6223e23 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 02607909b8..207cb17e88 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 46af2f5de3..bae0fb1853 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 66e9388ef8..dec00fd4a0 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 e2cca00248..ec125b8407 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 25ebe8dfc3..85db1e8e78 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 2831e50489..e0e8025d41 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 5c268981ef..a3669705bf 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 6516893981..cbed5d4768 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 bedb62e624..0c8efa43d1 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 55e508acc1..aa41071d53 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 037172bd5b..74a6ad4c07 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 388a465095..d063c5ebf8 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 fee0f44e43..82a82d2679 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 3e94c335bd..9a3b4407ef 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 77f0a7dd8b..b9d62e0362 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 331d69480a..555fac21ac 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 493be270a7..f1494124b0 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 de59af7d95..87c84bf0a4 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 aff3f89592..c33b6fcac6 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 0a6cc893b4..789b3ec4eb 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 f4880e3c65..f22ddaf622 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 258fb42f37..a68dddf668 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 53171e054c..2b2c405149 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 0cdde5a20f..31a0d8b827 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 40ff2b2f14..c075769975 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 0dbc5506a8..ed3a0cedbf 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 d276756bc2..3784d4bbb0 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 fec8e87b7b..83d58ac5c2 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 1e73be1087..5c63f6f982 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 887d79bfbf..780adb7ce4 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 6dc5508b55..5580177168 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 9b49ed7862..8579680abe 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 7d58d5ae6f..3a3c1b6ab2 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 20bc56a535..aef597e6ca 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 75bd4cdf5e..91b900ca4c 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 f775d2e1c5..5c440a540a 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 807b643a47..64257be77b 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 40bfbdadb4..0a56a23aa9 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 2d3ffd2419..a8f1ed4013 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 418192ac8b..9e1afd0345 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 2fddab2f87..7fca5deb7d 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 4251598b99..e3de393b87 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 a8db658eb4..46252f24e2 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 99701bdf52..7a47f69a43 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 1acd381e7f..363ad1c18a 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 aaa06f9f41..c7ab9ea153 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 61e4a35d9b..a1bd747a0b 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 41f2f9e8ae..c132c3543d 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 bf8844e66d..ce16c4649b 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 4ec7715103..0cd6ec7709 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 914e7c6e7d..f778c55eba 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 7097faed2a..e0fb71c5f4 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 f5bb2f1611..d3aae87dfd 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 24797c4a01..663973bf9c 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 6b8eb0f54c..0a92818faf 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 13a5f54e69..bde25cf81b 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 d3dc1ea861..dbf55fd882 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 8301256c44..d8c6da1d42 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 31952316c7..e8c7318be4 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 23b8b82ca7..bc177125ef 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 bf0bb3ea7c..4ba0cdecca 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 00506449f5..ada365d7d4 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 b01153553c..e13dad3078 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 a18fba0835..21a65369f7 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 243574f1a3..dd011d7773 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 9e2a5605c3..bee9bab76d 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 ac129e709c..9d57d45742 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 126020ed66..8cf8fa848e 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 ae6714de17..21f4e67439 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 18fe7e0541..33cb581ef9 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 90102d8e3a..70f0bac323 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 b2c9170e39..e3b395e058 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 6607461500..852ff4fb7c 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 64b8f8eccc..fffa85bd1a 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 a870bf6fed..111ca96a47 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 7ebbe61d91..ed87b15ace 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 aaa2f13447..eb67bea0c5 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 c1ec3ae39b..067e186a8c 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 59ecb742c1..379bd55e65 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 18dfd1c826..36f60800e5 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 b1684b0977..591716a2e3 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 8e0b32932c..57b7882502 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 df308fbc20..8c71a60920 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 a4b4237d2a..66e9da58aa 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 a93db2fc39..8bea8aa562 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 d4383c5625..e9862bd0f1 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 9eeded18ba..504ec1011d 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 9ae4648427..b7c3e727de 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 0b4281269f..ea06606f93 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 720e5d6621..c7829f9dd1 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 0b6aed8750..c502a834cd 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 2d2aad3701..19bbc2c02a 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 bdfc653a5e..9d5a311baa 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 18757140a7..7584282b6f 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 1b72a4e210..90e7a9c0c5 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 24fb9a5655..5da8189f44 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 58aaf80eae..fcca6453e0 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 a37461bb43..4759d9d9bc 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 8585bcc9e7..fc050ee5b1 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 18935a1d1b..4a700468f5 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 15938bb77a..43cc04f308 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 5a5247142a..e58d7f0836 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 53a57d882d..4ec0bb05b6 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 8fd3dfcfdc..fb7201ad27 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 1957a3e355..a8f15b232f 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 8a363dd198..58d01fd7e1 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 a6b5082953..664de7134f 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 86602aeaf6..4332667b43 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 f9d42fc548..437342a74b 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 f4046d58df..89482e6739 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 61c08d93d3..dbbdf5021c 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 07a526c68b..a6c2ad359f 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 963e44fc7f..f7a09875c5 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 a8638e236c..d35dd99ac0 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 e83b80b7c3..6c33b302d2 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 6ab14a2cf3..8bb89c0aed 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 6c9fafa130..e3bc123764 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 7dfcf9d48b..0d736fb3ed 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 d128086687..96e90c97a8 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 3043b680ad..d95850c317 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 51cf661ee8..0000000000 --- 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 30007eff01..2a7db04eb9 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 5009dfcfb4..e6dde73f62 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 4a7b2f7d7f..11ee22e2bd 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 7abc9a3919..d1723df786 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 04b37f133f..ea4a44417f 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 38fcdd844f..021fcb7289 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 85de26e39f..35deea224b 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 8bb89c0aed..9787193070 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 e3bc123764..e3ad3a4ffc 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 0d736fb3ed..73aae0bc72 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 b4087008af..8806a2f219 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 ea51ecacb6..9f6045364b 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 db41aa9019..1f04b9ecf2 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 929da88432..f83ad56331 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 34b415446a..4cb12f91ba 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 73c8af8254..5ba3a2e7ca 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 01ddd29b8b..a94506d62d 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 321b31df6a..3fb0803355 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 6f9716bb9d..3176a45961 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 7238d10c76..1e4d89d685 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 7980f51a9c..fe1603a44d 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 c2738b8a5b..0000000000 --- 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 e91ac2ffe6..b11aa2f4ec 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 9787193070..48aa5844c1 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 73aae0bc72..11489e7a63 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 8cd092639d..d736cdf8d8 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 48aa5844c1..d9089e941a 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 e3ad3a4ffc..9cbf2a9f68 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 11489e7a63..d82d5ec0c9 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 c380f93e14..9ac0e07c07 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 3a34478ca0..de61c099d3 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 c038be6405..7c12dbb0ee 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 124faee6f9..f6455749c9 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 54068652a2..5fd940d3bf 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 1fa8ec8a56..884c6962a8 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 bb3b924b94..9f3c5b446c 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 919dc3fc19..3788b9985a 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 99b38e3ec0..3b606b834f 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 d549838608..468e13366e 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 f1355e7475..b22b2b237f 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 52b0d3a15a..c827fbc7f6 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 66f0b37a62..0ddc5945b8 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 ca1979488d..274587df92 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 51aba15926..875f78283f 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 f5b7055937..b3f34003e6 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 a3dd966a06..81e17866a2 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 52728fc2b5..70e586ded3 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 59ea6d7e2a..0e977b36dd 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 134946651f..c0090a5957 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 f83ad56331..c74fea46f6 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 b4507e2988..962d4f3159 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 94f4d860d2..5ab7008281 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 f2e9cafa93..2af5a76158 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 c1830cd5aa..04bacc0d9d 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 70f14db539..bb701249c0 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 6a6afc7805..9c76b62e1d 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 b8c5327675..8d57af58dd 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 164afaeb7e..7c2839aba4 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 d42842f932..9a37ef8c91 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 625a6f5957..ebbf1933fa 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 3026cc4b9a..fe99097504 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 dccbe61ba4..5d844cff96 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 33d2a71778..a9e1e4dbb0 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 5a1dffc93d..ad0d20f1c6 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 5341c10797..83569e30ed 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 eae7c034ef..3bb2593865 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 04fec2788b..b6fd3cc191 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 00a55c6263..43a6d70043 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 f3f1df1905..e129300662 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 f3a0e8925c..9a5aa54967 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 0764759641..895f41759b 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 202dc6fe71..cfb0b03776 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 bddc74c6da..d046df9dd8 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 ff3c10a175..ebcf21d196 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 6f9d491216..7172a6b46c 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 e6dde73f62..5be89530fc 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 f360d96468..0b2a4f3e84 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 af515861c8..4c122d4cc9 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 31da74d168..fbf0e51106 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 f20e21f4de..766f07fa5b 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 dbd6356343..19b1579269 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 ce995efaf9..687177f741 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 74857367a4..2c4a59d83d 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 102dd15d34..f4bae3df54 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 f3791b4936..18f3713b32 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 da69a004c2..a3cab4cba3 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 318a27d590..01b78eb113 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 780adb7ce4..10715fa0f2 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 7a39522a33..55b11eba51 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 e2a682bd59..5139920ea7 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 a4d96cd735..baf0dc24a6 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 0a56a23aa9..40af728fbe 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 45fdf0f8f3..694eb77db1 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 ee95080748..5d6e87efe1 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 57e0588a04..ac428762df 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 bc8df66568..86bc8c7f1b 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 6ead902b79..d8021c06f3 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 664ad805cf..fca6385f87 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 727ac66415..bcd929f0ea 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 f3f74ece82..a9faefe7b7 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 1c4dbd3be9..cbd9d6f396 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 efe679d676..b991dd57f1 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 d9089e941a..4c34eb1d19 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 9cbf2a9f68..6283d18d77 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 d82d5ec0c9..b290bb3b01 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 b911de5489..2557d7db93 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 9019e55b25..258f3f50d2 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 01f3cb9dfb..215470cfc4 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 4f63cc5f58..dadc9a064f 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 962d4f3159..18af5b9af0 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 f093e54d40..16f4f7330b 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 c4af17b7b8..573b10ae8a 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 6698ecec01..3a35ebaba3 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 dca9c85381..7935d90c2e 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 83d800c823..f93f1536ea 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 3c508dca7b..cb691ffdbd 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 b8c2f7c663..69a10d8688 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 c2bd9b9cb9..9cba3038d0 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 b9aa2cbcaa..701f652df5 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 8b8e1c3a90..74c73599b7 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 0f325a17b6..15913499fb 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 076009eb9d..4cd0aa49f4 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 fb89dc8b17..458395ef67 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 0c8efa43d1..f7607d6438 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 1cb94b308d..6a28bc8e61 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 5db7e59ea6..a7e2f8fdb0 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 fc050ee5b1..6e49988921 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 664de7134f..37bc4bad7a 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 35deea224b..bd3aa2fcd7 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 a9faefe7b7..6b03f244a1 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 6b03f244a1..65a18ce643 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 65a18ce643..7b7af0d868 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 7b7af0d868..2fe151a1c3 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 4c34eb1d19..7273b6a4f7 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 6283d18d77..df12db543e 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 b290bb3b01..f8a3c03369 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 96e90c97a8..2a371b7889 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 b22b2b237f..6798e5731d 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 b3f34003e6..1409c1c576 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 3fb0803355..6ec1c8f6f8 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 310502c567..0e68b660fc 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 2c4768716f..71e1301cad 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 02282dd4a4..2d9a644618 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 dce8541469..67a039d8a4 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 4f8d5fb200..1f9283ec41 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 27ee3f2202..b7ca1eec89 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 e40c3f93ca..7e0dec9d36 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 0155300435..dcd620b20e 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 dc5f712d60..7180b8eda8 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 97c7963028..d3643842ea 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 7273b6a4f7..6e27898683 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 f8a3c03369..f018910bfe 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 0ddc5945b8..16dce61fe4 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 0e68b660fc..7023e18bf4 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 6e27898683..568a134407 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 5d844cff96..b36b49823e 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 a9e1e4dbb0..3341f42c21 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 43a6d70043..99cbb63d18 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 e129300662..acb58c60ee 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 67a039d8a4..7616c1215d 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 f018910bfe..368c5da6f3 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 dadc9a064f..0000000000 --- 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 18af5b9af0..a1a13c7b50 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 c215ea2c2e..a1d464b978 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 5e18995f5a..9e61865340 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 a94506d62d..8f8fea3820 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 004ebc0a70..8e8250a5bc 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 865fb4cb83..5219a37672 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 841de56a58..fa138320c2 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 568a134407..d23f3384ef 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 368c5da6f3..29733e45cc 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 d23f3384ef..dac9db57d9 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 29733e45cc..6d9e05aa99 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 c213d6a4bd..cfef4193ad 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 dac9db57d9..c1d6585379 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 c1d6585379..a72602217c 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 0cb5bd9c08..e3ed3986ac 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 fa17e9851c..b5bcfabc54 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 3947e4f6c0..5d676dc76d 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 fb8fe84437..4e28ed4839 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 800b5cd2f0..84a1da3438 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 b962e8f395..b090a09a50 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 baab4f6e5a..7446775db9 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 a2c95db74f..e3ab697d39 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 58594f0542..4ceab2cca2 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 a3ae840074..12d2506ea0 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 31de71154d..19c344a8db 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 b762271a29..516fd43280 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 093ea7ae2e..9c1b218f52 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 4ceab2cca2..94dd89db5e 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 12d2506ea0..f7d8b1d60a 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 19c344a8db..bd5e83ecc2 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 38ee5214b5..06b69fd042 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 516fd43280..812a7f3847 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 247f6ad54e..f67e74f111 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 04fe91cfba..aec03b492c 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 093ea7ae2e..f245ce54ac 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 ae0f396317..0bc4d2f18b 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 7446775db9..60cae7fd06 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 d2beb629a2..f04cf8feeb 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 f04cf8feeb..810223d72d 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 940b5888d8..bffce28037 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 62450d58e3..024109df93 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 46e1f9d194..c0119d36d5 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 7cd13b2ac2..03a6944492 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