diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index b0595a7a7..194396ddd 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -949,7 +949,7 @@ proc liftLambdas*(fn: PSym, body: PNode): PNode = discard transformOuterProcBody(o, body, initIter(fn)) result = ex finishEnvironments(o) - #if fn.name.s == "cbOuter": + #if fn.name.s == "parseLong": # echo rendertree(result, {renderIds}) proc liftLambdasForTopLevel*(module: PSym, body: PNode): PNode = diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim index e90ef9376..8e5ffd48a 100644 --- a/compiler/lowerings.nim +++ b/compiler/lowerings.nim @@ -56,6 +56,7 @@ proc lowerTupleUnpacking*(n: PNode; owner: PSym): PNode = result.add newAsgnStmt(newSymNode(temp), value) for i in 0 .. n.len-3: + if n.sons[i].kind == nkSym: v.addVar(n.sons[i]) result.add newAsgnStmt(n.sons[i], newTupleAccess(value, i)) proc createObj*(owner: PSym, info: TLineInfo): PType = diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim index acf5277c6..6673d0bd2 100644 --- a/compiler/vmdeps.nim +++ b/compiler/vmdeps.nim @@ -12,11 +12,11 @@ import ast, types, msgs, osproc, streams, options proc readOutput(p: Process): string = result = "" var output = p.outputStream - discard p.waitForExit while not output.atEnd: result.add(output.readLine) result.add("\n") result.setLen(result.len - "\n".len) + discard p.waitForExit proc opGorge*(cmd, input: string): string = var p = startCmd(cmd) diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 3921a69fe..e7f7ad742 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -46,7 +46,6 @@ proc debugInfo(info: TLineInfo): string = proc codeListing(c: PCtx, result: var string, start=0; last = -1) = # first iteration: compute all necessary labels: var jumpTargets = initIntSet() - let last = if last < 0: c.code.len-1 else: min(last, c.code.len-1) for i in start..last: let x = c.code[i] diff --git a/doc/basicopt.txt b/doc/basicopt.txt index 8080e380e..e8aaa2e4c 100644 --- a/doc/basicopt.txt +++ b/doc/basicopt.txt @@ -35,3 +35,5 @@ Options: -r, --run run the compiled program with given arguments --advanced show advanced command line switches -h, --help show this help + +Note: Even single letter options require the colon: -p:PATH. diff --git a/doc/koch.txt b/doc/koch.txt index a3b7f0df8..7da137458 100644 --- a/doc/koch.txt +++ b/doc/koch.txt @@ -138,6 +138,13 @@ from rst to HTML. It also repeats the same operation but places the result in the ``web/upload`` which can be used to update the website at http://nim-lang.org. +By default the documentation will be built in parallel using the number of +available CPU cores. If any documentation build sub commands fail, they will +be rerun in serial fashion so that meaninful error output can be gathered for +inspection. The ``--parallelBuild:n`` switch or configuration option can be +used to force a specific number of parallel jobs or run everything serially +from the start (``n == 1``). + zip command ----------- diff --git a/examples/0mq/client.nim b/examples/0mq/client.nim deleted file mode 100644 index e75e5c7a2..000000000 --- a/examples/0mq/client.nim +++ /dev/null @@ -1,14 +0,0 @@ -import zmq - -var connection = zmq.open("tcp://localhost:5555", server=false) - -echo("Connecting...") - -for i in 0..10: - echo("Sending hello...", i) - send(connection, "Hello") - - var reply = receive(connection) - echo("Received ...", reply) - -close(connection) diff --git a/examples/0mq/server.nim b/examples/0mq/server.nim deleted file mode 100644 index 0fadf8b97..000000000 --- a/examples/0mq/server.nim +++ /dev/null @@ -1,11 +0,0 @@ -import zmq - -var connection = zmq.open("tcp://*:5555", server=true) - -while True: - var request = receive(connection) - echo("Received: ", request) - send(connection, "World") - -close(connection) - diff --git a/lib/pure/cookies.nim b/lib/pure/cookies.nim index c85f60915..6247efed2 100644 --- a/lib/pure/cookies.nim +++ b/lib/pure/cookies.nim @@ -28,8 +28,9 @@ proc parseCookies*(s: string): StringTableRef = if s[i] == '\0': break inc(i) # skip ';' -proc setCookie*(key, value: string, domain = "", path = "", - expires = "", noName = false): string = +proc setCookie*(key, value: string, domain = "", path = "", + expires = "", noName = false, + secure = false, httpOnly = false): string = ## Creates a command in the format of ## ``Set-Cookie: key=value; Domain=...; ...`` result = "" @@ -38,22 +39,23 @@ proc setCookie*(key, value: string, domain = "", path = "", if domain != "": result.add("; Domain=" & domain) if path != "": result.add("; Path=" & path) if expires != "": result.add("; Expires=" & expires) + if secure: result.add("; secure") + if httpOnly: result.add("; HttpOnly") proc setCookie*(key, value: string, expires: TimeInfo, - domain = "", path = "", noName = false): string = + domain = "", path = "", noName = false, + secure = false, httpOnly = false): string = ## Creates a command in the format of ## ``Set-Cookie: key=value; Domain=...; ...`` ## - ## **Note:** UTC is assumed as the timezone for ``expires``. - + ## **Note:** UTC is assumed as the timezone for ``expires``. return setCookie(key, value, domain, path, - format(expires, "ddd',' dd MMM yyyy HH:mm:ss 'UTC'"), noName) - + format(expires, "ddd',' dd MMM yyyy HH:mm:ss 'UTC'"), + noname, secure, httpOnly) + when isMainModule: var tim = Time(int(getTime()) + 76 * (60 * 60 * 24)) echo(setCookie("test", "value", tim.getGMTime())) echo parseCookies("uid=1; kp=2") - - diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index 2fdf72011..55a204b4c 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -803,6 +803,36 @@ proc rfind*(s, sub: string, start: int = -1): int {.noSideEffect.} = if result != -1: return return -1 +proc count*(s: string, sub: string, overlapping: bool = false): int {.noSideEffect, + rtl, extern: "nsuCountString".} = + ## Count the occurences of a substring `sub` in the string `s`. + ## Overlapping occurences of `sub` only count when `overlapping` + ## is set to true. + var i = 0 + while true: + i = s.find(sub, i) + if i < 0: + break + if overlapping: + inc i + else: + i += sub.len + inc result + +proc count*(s: string, sub: char): int {.noSideEffect, + rtl, extern: "nsuCountChar".} = + ## Count the occurences of the character `sub` in the string `s`. + for c in s: + if c == sub: + inc result + +proc count*(s: string, subs: set[char]): int {.noSideEffect, + rtl, extern: "nsuCountCharSet".} = + ## Count the occurences of the group of character `subs` in the string `s`. + for c in s: + if c in subs: + inc result + proc quoteIfContainsWhite*(s: string): string {.deprecated.} = ## Returns ``'"' & s & '"'`` if `s` contains a space and does not ## start with a quote, else returns `s`. @@ -1356,3 +1386,8 @@ when isMainModule: doAssert parseEnum[MyEnum]("enu_D") == enuD doAssert parseEnum("invalid enum value", enC) == enC + + doAssert count("foofoofoo", "foofoo") == 1 + doAssert count("foofoofoo", "foofoo", overlapping = true) == 2 + doAssert count("foofoofoo", 'f') == 3 + doAssert count("foofoofoobar", {'f','b'}) == 4 diff --git a/lib/pure/times.nim b/lib/pure/times.nim index dcc5617fd..1cabd381b 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -514,7 +514,7 @@ elif defined(JS): result.setFullYear(timeInfo.year) result.setDate(timeInfo.monthday) - proc `$`(timeInfo: TimeInfo): string = return $(TimeInfoToTIme(timeInfo)) + proc `$`(timeInfo: TimeInfo): string = return $(timeInfoToTime(timeInfo)) proc `$`(time: Time): string = return $time.toLocaleString() proc `-` (a, b: Time): int64 = diff --git a/lib/pure/xmltree.nim b/lib/pure/xmltree.nim index 37f591f1e..b84da9586 100644 --- a/lib/pure/xmltree.nim +++ b/lib/pure/xmltree.nim @@ -154,6 +154,8 @@ proc addEscaped*(result: var string, s: string) = of '>': result.add(">") of '&': result.add("&") of '"': result.add(""") + of '\'': result.add("'") + of '/': result.add("/") else: result.add(c) proc escape*(s: string): string = @@ -167,6 +169,8 @@ proc escape*(s: string): string = ## ``>`` ``>`` ## ``&`` ``&`` ## ``"`` ``"`` + ## ``'`` ``'`` + ## ``/`` ``/`` ## ------------ ------------------- result = newStringOfCap(s.len) addEscaped(result, s) diff --git a/lib/system/threads.nim b/lib/system/threads.nim index 95fa353dd..7dac9d9aa 100644 --- a/lib/system/threads.nim +++ b/lib/system/threads.nim @@ -354,7 +354,6 @@ when hostOS == "windows": addr(t), 0'i32, dummyThreadId) if t.sys <= 0: raise newException(ResourceExhaustedError, "cannot create thread") - else: proc createThread*[TArg](t: var TThread[TArg], tp: proc (arg: TArg) {.thread.}, diff --git a/tools/nimweb.nim b/tools/nimweb.nim index cd679a299..5dd21c98f 100644 --- a/tools/nimweb.nim +++ b/tools/nimweb.nim @@ -21,6 +21,7 @@ type nimrodArgs: string gitCommit: string quotations: TTable[string, tuple[quote, author: string]] + numProcessors: int # Set by parallelBuild:n, only works for values > 0. TRssItem = object year, month, day, title: string @@ -42,6 +43,7 @@ proc initConfigData(c: var TConfigData) = c.ticker = "" c.vars = newStringTable(modeStyleInsensitive) c.gitCommit = "master" + c.numProcessors = countProcessors() # Attempts to obtain the git current commit. let (output, code) = execCmdEx("git log -n 1 --format=%H") if code == 0 and output.strip.len == 40: @@ -121,6 +123,12 @@ proc parseCmdLine(c: var TConfigData) = stdout.write(Version & "\n") quit(0) of "o", "output": c.outdir = val + of "parallelbuild": + try: + let num = parseInt(val) + if num != 0: c.numProcessors = num + except EInvalidValue: + quit("invalid numeric value for --parallelBuild") of "var": var idx = val.find('=') if idx < 0: quit("invalid command line") @@ -187,6 +195,12 @@ proc parseIniFile(c: var TConfigData) = of "srcdoc": addFiles(c.srcdoc, "lib", ".nim", split(v, {';'})) of "srcdoc2": addFiles(c.srcdoc2, "lib", ".nim", split(v, {';'})) of "webdoc": addFiles(c.webdoc, "lib", ".nim", split(v, {';'})) + of "parallelbuild": + try: + let num = parseInt(v) + if num != 0: c.numProcessors = num + except EInvalidValue: + quit("invalid numeric value for --parallelBuild in config") else: quit(errorStr(p, "unknown variable: " & k.key)) of "quotations": let vSplit = v.split('-') @@ -215,6 +229,20 @@ proc exec(cmd: string) = echo(cmd) if os.execShellCmd(cmd) != 0: quit("external program failed") +proc sexec(cmds: openarray[string]) = + ## Serial queue wrapper around exec. + for cmd in cmds: exec(cmd) + +proc mexec(cmds: openarray[string], processors: int) = + ## Multiprocessor version of exec + if processors < 2: + sexec(cmds) + return + + if 0 != execProcesses(cmds, {poStdErrToStdOut, poParentStreams, poEchoCmd}): + echo "external program failed, retrying serial work queue for logs!" + sexec(cmds) + proc buildDocSamples(c: var TConfigData, destPath: string) = ## Special case documentation sample proc. ## @@ -229,18 +257,26 @@ proc buildDocSamples(c: var TConfigData, destPath: string) = proc buildDoc(c: var TConfigData, destPath: string) = # call nim for the documentation: + var + commands = newSeq[string](len(c.doc) + len(c.srcdoc) + len(c.srcdoc2)) + i = 0 for d in items(c.doc): - exec("nimrod rst2html $# --docSeeSrcUrl:$# -o:$# --index:on $#" % + commands[i] = "nimrod rst2html $# --docSeeSrcUrl:$# -o:$# --index:on $#" % [c.nimrodArgs, c.gitCommit, - destPath / changeFileExt(splitFile(d).name, "html"), d]) + destPath / changeFileExt(splitFile(d).name, "html"), d] + i.inc for d in items(c.srcdoc): - exec("nimrod doc $# --docSeeSrcUrl:$# -o:$# --index:on $#" % + commands[i] = "nimrod doc $# --docSeeSrcUrl:$# -o:$# --index:on $#" % [c.nimrodArgs, c.gitCommit, - destPath / changeFileExt(splitFile(d).name, "html"), d]) + destPath / changeFileExt(splitFile(d).name, "html"), d] + i.inc for d in items(c.srcdoc2): - exec("nimrod doc2 $# --docSeeSrcUrl:$# -o:$# --index:on $#" % + commands[i] = "nimrod doc2 $# --docSeeSrcUrl:$# -o:$# --index:on $#" % [c.nimrodArgs, c.gitCommit, - destPath / changeFileExt(splitFile(d).name, "html"), d]) + destPath / changeFileExt(splitFile(d).name, "html"), d] + i.inc + + mexec(commands, c.numProcessors) exec("nimrod buildIndex -o:$1/theindex.html $1" % [destPath]) proc buildPdfDoc(c: var TConfigData, destPath: string) = @@ -264,10 +300,12 @@ proc buildPdfDoc(c: var TConfigData, destPath: string) = proc buildAddDoc(c: var TConfigData, destPath: string) = # build additional documentation (without the index): - for d in items(c.webdoc): - exec("nimrod doc $# --docSeeSrcUrl:$# -o:$# $#" % + var commands = newSeq[string](c.webdoc.len) + for i, doc in pairs(c.webdoc): + commands[i] = "nimrod doc $# --docSeeSrcUrl:$# -o:$# $#" % [c.nimrodArgs, c.gitCommit, - destPath / changeFileExt(splitFile(d).name, "html"), d]) + destPath / changeFileExt(splitFile(doc).name, "html"), doc] + mexec(commands, c.numProcessors) proc parseNewsTitles(inputFilename: string): seq[TRssItem] = # parses the file for titles and returns them as TRssItem blocks.