diff options
28 files changed, 190 insertions, 68 deletions
diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index fb878a83e..200ff91e0 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -133,7 +133,7 @@ proc genArg(p: BProc, n: PNode, param: PSym; call: PNode): PRope = var n = if n.kind != nkHiddenAddr: n else: n.sons[0] result = openArrayLoc(p, n) elif ccgIntroducedPtr(param): - initLocExprSingleUse(p, n, a) + initLocExpr(p, n, a) result = addrLoc(a) elif p.module.compileToCpp and param.typ.kind == tyVar and n.kind == nkHiddenAddr: diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 61568c9e6..a4938c9ac 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -203,7 +203,8 @@ proc genSingleVar(p: BProc, a: PNode) = registerGcRoot(p, v) else: let imm = isAssignedImmediately(a.sons[2]) - if imm and p.module.compileToCpp and p.splitDecls == 0: + if imm and p.module.compileToCpp and p.splitDecls == 0 and + not containsHiddenPointer(v.typ): # C++ really doesn't like things like 'Foo f; f = x' as that invokes a # parameterless constructor followed by an assignment operator. So we # generate better code here: diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim index e4ce0aa6c..134619d4a 100644 --- a/compiler/ccgutils.nim +++ b/compiler/ccgutils.nim @@ -69,7 +69,20 @@ when false: proc echoStats*() = for i in countup(low(TTypeKind), high(TTypeKind)): echo i, " ", gTypeTable[i].counter - + +proc slowSearch(key: PType; k: TTypeKind): PType = + # tuples are quite horrible as C does not support them directly and + # tuple[string, string] is a (strange) subtype of + # tuple[nameA, nameB: string]. This bites us here, so we + # use 'sameBackendType' instead of 'sameType'. + if idTableHasObjectAsKey(gTypeTable[k], key): return key + for h in countup(0, high(gTypeTable[k].data)): + var t = PType(gTypeTable[k].data[h].key) + if t != nil and sameBackendType(t, key): + return t + idTablePut(gTypeTable[k], key, key) + result = key + proc getUniqueType*(key: PType): PType = # this is a hotspot in the compiler! if key == nil: return @@ -96,23 +109,20 @@ proc getUniqueType*(key: PType): PType = #if obj.sym != nil and obj.sym.name.s == "TOption": # echo "for ", typeToString(key), " I returned " # debug result + of tyPtr, tyRef, tyVar: + let elemType = lastSon(key) + if elemType.kind in {tyBool, tyChar, tyInt..tyUInt64}: + # no canonicalization for integral types, so that e.g. ``ptr pid_t`` is + # produced instead of ``ptr NI``. + result = key + else: + result = slowSearch(key, k) of tyArrayConstr, tyGenericInvocation, tyGenericBody, tyOpenArray, tyArray, tySet, tyRange, tyTuple, - tyPtr, tyRef, tySequence, tyForward, tyVarargs, tyProxy, tyVar: - # tuples are quite horrible as C does not support them directly and - # tuple[string, string] is a (strange) subtype of - # tuple[nameA, nameB: string]. This bites us here, so we - # use 'sameBackendType' instead of 'sameType'. - + tySequence, tyForward, tyVarargs, tyProxy: # we have to do a slow linear search because types may need # to be compared by their structure: - if idTableHasObjectAsKey(gTypeTable[k], key): return key - for h in countup(0, high(gTypeTable[k].data)): - var t = PType(gTypeTable[k].data[h].key) - if t != nil and sameBackendType(t, key): - return t - idTablePut(gTypeTable[k], key, key) - result = key + result = slowSearch(key, k) of tyObject: if tfFromGeneric notin key.flags: # fast case; lookup per id suffices: @@ -139,14 +149,8 @@ proc getUniqueType*(key: PType): PType = result = key else: # ugh, we need the canon here: - if idTableHasObjectAsKey(gTypeTable[k], key): return key - for h in countup(0, high(gTypeTable[k].data)): - var t = PType(gTypeTable[k].data[h].key) - if t != nil and sameBackendType(t, key): - return t - idTablePut(gTypeTable[k], key, key) - result = key - + result = slowSearch(key, k) + proc tableGetType*(tab: TIdTable, key: PType): RootRef = # returns nil if we need to declare this type result = idTableGet(tab, key) diff --git a/compiler/nimsuggest/nimsuggest.nim b/compiler/nimsuggest/nimsuggest.nim index cac078127..b45ca475c 100644 --- a/compiler/nimsuggest/nimsuggest.nim +++ b/compiler/nimsuggest/nimsuggest.nim @@ -120,13 +120,17 @@ proc serve() = server.bindAddr(gPort, gAddress) var inp = "".TaintedString server.listen() - var stdoutSocket = newSocket() - msgs.writelnHook = proc (line: string) = - stdoutSocket.send(line & "\c\L") + while true: + var stdoutSocket = newSocket() + msgs.writelnHook = proc (line: string) = + stdoutSocket.send(line & "\c\L") + accept(server, stdoutSocket) + stdoutSocket.readLine(inp) action inp.string + stdoutSocket.send("\c\L") stdoutSocket.close() diff --git a/compiler/seminst.nim b/compiler/seminst.nim index d74584096..a10f27519 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -80,13 +80,9 @@ proc freshGenSyms(n: PNode, owner: PSym, symMap: var TIdTable) = let s = n.sym var x = PSym(idTableGet(symMap, s)) if x == nil: - if s.kind == skParam: - x = owner.typ.n[s.position+1].sym - internalAssert x.kind == skParam - else: - x = copySym(s, false) - x.owner = owner - idTablePut(symMap, s, x) + x = copySym(s, false) + x.owner = owner + idTablePut(symMap, s, x) n.sym = x else: for i in 0 .. <safeLen(n): freshGenSyms(n.sons[i], owner, symMap) @@ -104,13 +100,18 @@ proc addProcDecls(c: PContext, fn: PSym) = maybeAddResult(c, fn, fn.ast) -proc instantiateBody(c: PContext, n: PNode, result: PSym) = +proc instantiateBody(c: PContext, n, params: PNode, result: PSym) = if n.sons[bodyPos].kind != nkEmpty: inc c.inGenericInst # add it here, so that recursive generic procs are possible: var b = n.sons[bodyPos] var symMap: TIdTable initIdTable symMap + if params != nil: + for i in 1 .. <params.len: + let param = params[i].sym + if sfGenSym in param.flags: + idTablePut(symMap, params[i].sym, result.typ.n[param.position+1].sym) freshGenSyms(b, result, symMap) b = semProcBody(c, b) b = hloBody(c, b) @@ -127,7 +128,7 @@ proc fixupInstantiatedSymbols(c: PContext, s: PSym) = openScope(c) var n = oldPrc.ast n.sons[bodyPos] = copyTree(s.getBody) - instantiateBody(c, n, oldPrc) + instantiateBody(c, n, nil, oldPrc) closeScope(c) popInfoContext() @@ -249,7 +250,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, pragma(c, result, n.sons[pragmasPos], allRoutinePragmas) if isNil(n.sons[bodyPos]): n.sons[bodyPos] = copyTree(fn.getBody) - instantiateBody(c, n, result) + instantiateBody(c, n, fn.typ.n, result) sideEffectsCheck(c, result) paramsTypeCheck(c, result.typ) else: diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index 47602368a..a48f045a2 100644 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -494,7 +494,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode = semParamList(c, n.sons[paramsPos], gp, s) # a template's parameters are not gensym'ed even if that was originally the # case as we determine whether it's a template parameter in the template - # body by the absence of the skGenSym flag: + # body by the absence of the sfGenSym flag: for i in 1 .. s.typ.n.len-1: s.typ.n.sons[i].sym.flags.excl sfGenSym if sonsLen(gp) > 0: diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index d9c7b6c92..4e3823f42 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -452,6 +452,7 @@ proc semCaseBranchSetElem(c: PContext, t, b: PNode, proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int, covered: var BiggestInt) = + for i in countup(0, sonsLen(branch) - 2): var b = branch.sons[i] if b.kind == nkRange: @@ -461,8 +462,11 @@ proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int, else: # constant sets and arrays are allowed: var r = semConstExpr(c, b) - # for ``{}`` we want to trigger the type mismatch in ``fitNode``: - if r.kind notin {nkCurly, nkBracket} or len(r) == 0: + if r.kind in {nkCurly, nkBracket} and len(r) == 0 and sonsLen(branch)==2: + # discarding ``{}`` and ``[]`` branches silently + delSon(branch, 0) + return + elif r.kind notin {nkCurly, nkBracket} or len(r) == 0: checkMinSonsLen(t, 1) branch.sons[i] = skipConv(fitNode(c, t.sons[0].typ, r)) inc(covered) @@ -1189,7 +1193,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = result = typeExpr.typ.base if result.isMetaType: var preprocessed = semGenericStmt(c, n) - result = makeTypeFromExpr(c, preprocessed) + result = makeTypeFromExpr(c, preprocessed.copyTree) of nkIdent, nkAccQuoted: var s = semTypeIdent(c, n) if s.typ == nil: diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index 12fce1b84..452942ec0 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -369,6 +369,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = of tyFromExpr: if cl.allowMetaTypes: return + assert t.n.typ != t var n = prepareNode(cl, t.n) n = cl.c.semConstExpr(cl.c, n) if n.typ.kind == tyTypeDesc: diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index a782658b6..30d51aa29 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -1187,8 +1187,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType, if argType.kind == tyStatic: if m.callee.kind == tyGenericBody and tfGenericTypeParam notin argType.flags: - result = newNodeI(nkType, argOrig.info) - result.typ = makeTypeFromExpr(c, arg) + result = newNodeIT(nkType, argOrig.info, makeTypeFromExpr(c, arg)) return else: var evaluated = c.semTryConstExpr(c, arg) diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim index 7fa88de6e..11d839c41 100644 --- a/compiler/vmdeps.nim +++ b/compiler/vmdeps.nim @@ -51,7 +51,12 @@ proc mapTypeToBracket(name: string; t: PType; info: TLineInfo): PNode = result = newNodeIT(nkBracketExpr, info, t) result.add atomicTypeX(name, t, info) for i in 0 .. < t.len: - result.add mapTypeToAst(t.sons[i], info) + if t.sons[i] == nil: + let void = atomicTypeX("void", t, info) + void.typ = newType(tyEmpty, t.owner) + result.add void + else: + result.add mapTypeToAst(t.sons[i], info) proc mapTypeToAst(t: PType, info: TLineInfo; allowRecursion=false): PNode = template atomicType(name): expr = atomicTypeX(name, t, info) @@ -101,7 +106,7 @@ proc mapTypeToAst(t: PType, info: TLineInfo; allowRecursion=false): PNode = of tyPtr: result = mapTypeToBracket("ptr", t, info) of tyRef: result = mapTypeToBracket("ref", t, info) of tyVar: result = mapTypeToBracket("var", t, info) - of tySequence: result = mapTypeToBracket("sequence", t, info) + of tySequence: result = mapTypeToBracket("seq", t, info) of tyProc: result = mapTypeToBracket("proc", t, info) of tyOpenArray: result = mapTypeToBracket("openArray", t, info) of tyRange: diff --git a/doc/gc.txt b/doc/gc.txt index ac8d46cfa..f51421bcd 100644 --- a/doc/gc.txt +++ b/doc/gc.txt @@ -87,14 +87,14 @@ is triggered. Time measurement ---------------- -The GC's way of measing time uses (see ``lib/system/timers.nim`` for the +The GC's way of measuring time uses (see ``lib/system/timers.nim`` for the implementation): 1) ``QueryPerformanceCounter`` and ``QueryPerformanceFrequency`` on Windows. 2) ``mach_absolute_time`` on Mac OS X. 3) ``gettimeofday`` on Posix systems. -As such it supports a resolution of nano seconds internally; however the API +As such it supports a resolution of nanoseconds internally; however the API uses microseconds for convenience. diff --git a/doc/manual/typedesc.txt b/doc/manual/typedesc.txt index 97ab18b56..5087c1204 100644 --- a/doc/manual/typedesc.txt +++ b/doc/manual/typedesc.txt @@ -25,7 +25,7 @@ For the purposes of code generation, all static params are treated as generic params - the proc will be compiled separately for each unique supplied value (or combination of values). -Furthermore, the system module defines a `semistatic[T]` type than can be +Furthermore, the system module defines a `semistatic[T]` type that can be used to declare procs accepting both static and run-time values, which can optimize their body according to the supplied param using the `isStatic(p)` predicate: diff --git a/koch.nim b/koch.nim index 535dae5ba..d365262c1 100644 --- a/koch.nim +++ b/koch.nim @@ -139,9 +139,6 @@ proc pdf(args="") = # -------------- boot --------------------------------------------------------- -const - bootOptions = "" # options to pass to the bootstrap process - proc findStartNim: string = # we try several things before giving up: # * bin/nim @@ -180,11 +177,13 @@ proc thVersion(i: int): string = proc boot(args: string) = var output = "compiler" / "nim".exe var finalDest = "bin" / "nim".exe + # default to use the 'c' command: + let bootOptions = if args.len == 0 or args.startsWith("-"): "c" else: "" copyExe(findStartNim(), 0.thVersion) for i in 0..2: echo "iteration: ", i+1 - exec i.thVersion & " c $# $# compiler" / "nim.nim" % [bootOptions, args] + exec i.thVersion & " $# $# compiler" / "nim.nim" % [bootOptions, args] if sameFileContent(output, i.thVersion): copyExe(output, finalDest) echo "executables are equal: SUCCESS!" diff --git a/lib/core/macros.nim b/lib/core/macros.nim index c6453aeaa..dbfb2ceb3 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -1,7 +1,7 @@ # # # Nim's Runtime Library -# (c) Copyright 2013 Andreas Rumpf +# (c) Copyright 2015 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -120,6 +120,8 @@ const nnkCallKinds* = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand, nnkCallStrLit} +{.push warning[deprecated]: off.} + proc `[]`*(n: PNimrodNode, i: int): PNimrodNode {.magic: "NChild", noSideEffect.} ## get `n`'s `i`'th child. @@ -808,3 +810,5 @@ when not defined(booting): macro payload: stmt {.gensym.} = result = parseStmt(e) payload() + +{.pop.} diff --git a/lib/pure/httpserver.nim b/lib/pure/httpserver.nim index 38a068ea1..5efdbe297 100644 --- a/lib/pure/httpserver.nim +++ b/lib/pure/httpserver.nim @@ -363,7 +363,7 @@ proc run*(handleRequest: proc (client: Socket, port = Port(80)) = ## encapsulates the server object and main loop var s: TServer - open(s, port) + open(s, port, reuseAddr = true) #echo("httpserver running on port ", s.port) while true: next(s) diff --git a/lib/pure/net.nim b/lib/pure/net.nim index 5e5c4f8ec..bed751542 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -454,6 +454,8 @@ proc close*(socket: Socket) = # shutdown i.e not wait for the peers "close notify" alert with a second # call to SSLShutdown let res = SSLShutdown(socket.sslHandle) + SSLFree(socket.sslHandle) + socket.sslHandle = nil if res == 0: discard elif res != 1: diff --git a/lib/pure/selectors.nim b/lib/pure/selectors.nim index 2ed53ef3f..b6bc9dd3a 100644 --- a/lib/pure/selectors.nim +++ b/lib/pure/selectors.nim @@ -48,12 +48,21 @@ when defined(nimdoc): events: set[Event]): SelectorKey {.discardable.} = ## Updates the events which ``fd`` wants notifications for. + proc unregister*(s: Selector, fd: SocketHandle): SelectorKey {.discardable.} = + ## Unregisters file descriptor ``fd`` from selector ``s``. + + proc close*(s: Selector) = + ## Closes the selector + proc select*(s: Selector, timeout: int): seq[ReadyInfo] = ## The ``events`` field of the returned ``key`` contains the original events ## for which the ``fd`` was bound. This is contrary to the ``events`` field ## of the ``TReadyInfo`` tuple which determines which events are ready ## on the ``fd``. + proc newSelector*(): Selector = + ## Creates a new selector + proc contains*(s: Selector, fd: SocketHandle): bool = ## Determines whether selector contains a file descriptor. @@ -78,8 +87,6 @@ elif defined(linux): proc register*(s: Selector, fd: SocketHandle, events: set[Event], data: RootRef): SelectorKey {.discardable.} = - ## Registers file descriptor ``fd`` to selector ``s`` with a set of TEvent - ## ``events``. var event = createEventStruct(events, fd) if events != {}: if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fd, addr(event)) != 0: @@ -92,7 +99,6 @@ elif defined(linux): proc update*(s: Selector, fd: SocketHandle, events: set[Event]): SelectorKey {.discardable.} = - ## Updates the events which ``fd`` wants notifications for. if s.fds[fd].events != events: if events == {}: # This fd is idle -- it should not be registered to epoll. @@ -204,7 +210,6 @@ elif not defined(nimdoc): proc update*(s: Selector, fd: SocketHandle, events: set[Event]): SelectorKey {.discardable.} = - ## Updates the events which ``fd`` wants notifications for. if not s.fds.hasKey(fd): raise newException(ValueError, "File descriptor not found.") diff --git a/lib/pure/sockets.nim b/lib/pure/sockets.nim index 8ac5d4f09..3afb545c8 100644 --- a/lib/pure/sockets.nim +++ b/lib/pure/sockets.nim @@ -657,6 +657,8 @@ proc close*(socket: Socket) = when defined(ssl): if socket.isSSL: discard SSLShutdown(socket.sslHandle) + SSLFree(socket.sslHandle) + socket.sslHandle = nil proc getServByName*(name, proto: string): Servent {.tags: [ReadIOEffect].} = ## Searches the database from the beginning and finds the first entry for diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim index 5d68d112e..a05398a09 100644 --- a/lib/system/sysio.nim +++ b/lib/system/sysio.nim @@ -188,7 +188,7 @@ when defined(windows) and not defined(useWinAnsi): proc wfopen(filename, mode: WideCString): pointer {. importcpp: "_wfopen((const wchar_t*)#, (const wchar_t*)#)", nodecl.} proc wfreopen(filename, mode: WideCString, stream: File): File {. - importc: "_wfreopen((const wchar_t*)#, (const wchar_t*)#)", nodecl.} + importcpp: "_wfreopen((const wchar_t*)#, (const wchar_t*)#, #)", nodecl.} else: proc wfopen(filename, mode: WideCString): pointer {. importc: "_wfopen", nodecl.} diff --git a/tests/casestmt/tcase_emptyset_when.nim b/tests/casestmt/tcase_emptyset_when.nim new file mode 100644 index 000000000..e9b1ec2df --- /dev/null +++ b/tests/casestmt/tcase_emptyset_when.nim @@ -0,0 +1,24 @@ +discard """ + file: "tcaseofwhen.nim" + outputsub: "compiles for 1\ni am always two\ndefault for 3\nset is 4 not 5\narray is 6 not 7\ndefault for 8" + exitcode: "0" +""" + +proc whenCase(a: int) = + case a + of (when compiles(whenCase(1)): 1 else: {}): echo "compiles for 1" + of {}: echo "me not fail" + of 2: echo "i am always two" + of []: echo "me neither" + of {4,5}: echo "set is 4 not 5" + of [6,7]: echo "array is 6 not 7" + of (when compiles(neverCompilesIBet()): 3 else: {}): echo "compiles for 3" + #of {},[]: echo "me neither" + else: echo "default for ", a + +whenCase(1) +whenCase(2) +whenCase(3) +whenCase(4) +whenCase(6) +whenCase(8) diff --git a/tests/macros/tmacrotypes.nim b/tests/macros/tmacrotypes.nim index f19aa2ddb..991668930 100644 --- a/tests/macros/tmacrotypes.nim +++ b/tests/macros/tmacrotypes.nim @@ -1,16 +1,16 @@ discard """ - disabled: true + nimout: '''void +int''' """ -import macros, typetraits +import macros -macro checkType(ex, expected: expr): stmt {.immediate.} = - var t = ex.typ - assert t.name == expected.strVal +macro checkType(ex: stmt; expected: expr): stmt = + var t = ex.getType() + echo t proc voidProc = echo "hello" -proc intProc(a, b): int = 10 +proc intProc(a: int, b: float): int = 10 checkType(voidProc(), "void") checkType(intProc(10, 20.0), "int") -checkType(noproc(10, 20.0), "Error Type") diff --git a/tests/macros/tnimrodnode_for_runtime.nim b/tests/macros/tnimnode_for_runtime.nim index e73c8430f..69c7aedd2 100644 --- a/tests/macros/tnimrodnode_for_runtime.nim +++ b/tests/macros/tnimnode_for_runtime.nim @@ -1,6 +1,5 @@ discard """ output: "bla" - disabled: true """ import macros diff --git a/tests/macros/tsame_name_497.nim b/tests/macros/tsame_name_497.nim index e49f9f6d8..ed5d5c6d8 100644 --- a/tests/macros/tsame_name_497.nim +++ b/tests/macros/tsame_name_497.nim @@ -1,3 +1,7 @@ +discard """ + disabled: true +""" + import macro_bug type TObj = object diff --git a/tests/macros/typesapi.nim b/tests/macros/typesapi.nim new file mode 100644 index 000000000..670b39c9e --- /dev/null +++ b/tests/macros/typesapi.nim @@ -0,0 +1,17 @@ +discard """ + nimout: '''proc (x: int): string => typeDesc[proc[string, int]] +proc (x: int): void => typeDesc[proc[void, int]] +proc (x: int) => typeDesc[proc[void, int]]''' +""" + +#2211 + +import macros + +macro showType(t:stmt): stmt = + let ty = t.getType + echo t.repr, " => ", ty.repr + +showType(proc(x:int): string) +showType(proc(x:int): void) +showType(proc(x:int)) diff --git a/tests/template/tparams_gensymed.nim b/tests/template/tparams_gensymed.nim index 33940874d..6c4413866 100644 --- a/tests/template/tparams_gensymed.nim +++ b/tests/template/tparams_gensymed.nim @@ -31,3 +31,32 @@ var x: Something testB(x) +# bug #2215 +# Test that templates in generics still work (regression to fix the +# regression...) + +template forStatic(index: expr, slice: Slice[int], predicate: stmt): + stmt {.immediate.} = + const a = slice.a + const b = slice.b + when a <= b: + template iteration(i: int) = + block: + const index = i + predicate + template iterateStartingFrom(i: int): stmt = + when i <= b: + iteration i + iterateStartingFrom i + 1 + iterateStartingFrom a + +proc concreteProc(x: int) = + forStatic i, 0..3: + echo i + +proc genericProc(x: any) = + forStatic i, 0..3: + echo i + +concreteProc(7) # This works +genericProc(7) # This doesn't compile diff --git a/tests/testament/specs.nim b/tests/testament/specs.nim index e079eed62..2a8a4ea24 100644 --- a/tests/testament/specs.nim +++ b/tests/testament/specs.nim @@ -48,6 +48,7 @@ type err*: TResultEnum substr*, sortoutput*: bool targets*: set[TTarget] + nimout*: string const targetToExt*: array[TTarget, string] = ["c", "cpp", "m", "js"] @@ -94,6 +95,7 @@ proc parseSpec*(filename: string): TSpec = result.file = filename result.msg = "" result.outp = "" + result.nimout = "" result.ccodeCheck = "" result.cmd = cmdTemplate parseSpecAux: @@ -124,6 +126,8 @@ proc parseSpec*(filename: string): TSpec = of "errormsg": result.msg = e.value result.action = actionReject + of "nimout": + result.nimout = e.value of "disabled": if parseCfgBool(e.value): result.err = reIgnored of "cmd": result.cmd = e.value diff --git a/tests/testament/tester.nim b/tests/testament/tester.nim index 45643be10..881a41ce6 100644 --- a/tests/testament/tester.nim +++ b/tests/testament/tester.nim @@ -64,7 +64,9 @@ proc callCompiler(cmdTemplate, filename, options: string, var suc = "" var err = "" var x = newStringOfCap(120) + result.nimout = "" while outp.readLine(x.TaintedString) or running(p): + result.nimout.add(x & "\n") if x =~ pegOfInterest: # `err` should contain the last error/warning message err = x @@ -112,7 +114,9 @@ proc addResult(r: var TResults, test: TTest, expected = expected, given = given) r.data.addf("$#\t$#\t$#\t$#", name, expected, given, $success) - if success notin {reSuccess, reIgnored}: + if success == reIgnored: + styledEcho styleBright, name, fgYellow, " [", $success, "]" + elif success != reSuccess: styledEcho styleBright, name, fgRed, " [", $success, "]" echo"Expected:" styledEcho styleBright, expected @@ -151,6 +155,13 @@ proc codegenCheck(test: TTest, check: string, given: var TSpec) = except IOError: given.err = reCodeNotFound +proc nimoutCheck(test: TTest; expectedNimout: string; given: var TSpec) = + if expectedNimout.len > 0: + let exp = expectedNimout.strip.replace("\C\L", "\L") + let giv = given.nimout.strip.replace("\C\L", "\L") + if exp notin giv: + given.err = reMsgsDiffer + proc makeDeterministic(s: string): string = var x = splitLines(s) sort(x, system.cmp) @@ -172,6 +183,7 @@ proc testSpec(r: var TResults, test: TTest) = test.target) if given.err == reSuccess: codegenCheck(test, expected.ccodeCheck, given) + nimoutCheck(test, expected.nimout, given) r.addResult(test, "", given.msg, given.err) if given.err == reSuccess: inc(r.passed) of actionRun: @@ -205,6 +217,7 @@ proc testSpec(r: var TResults, test: TTest) = given.err = reOutputsDiffer if given.err == reSuccess: codeGenCheck(test, expected.ccodeCheck, given) + nimoutCheck(test, expected.nimout, given) if given.err == reSuccess: inc(r.passed) r.addResult(test, expected.outp, buf.string, given.err) else: diff --git a/todo.txt b/todo.txt index 79fe9d05a..3fed10aeb 100644 --- a/todo.txt +++ b/todo.txt @@ -10,6 +10,7 @@ version 0.10.4 version 1.0 =========== +- figure out why C++ bootstrapping is so much slower - nimsuggest: auto-completion needs to work in 'class' macros - improve the docs for inheritance - The bitwise 'not' operator will be renamed to 'bnot' to |