From c0f78ec0121c2578759e1b7cff561b75a58e3f97 Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Mon, 30 Jul 2018 05:02:18 -0700 Subject: [PATCH 01/11] fixes #8419 fixes #8420 ; workaround #6071 workaround nim-lang/website#98 (#8423) add --git.devel option to override doc generated "edit" links; add --nimCompiler option to nimweb --- compiler/docgen.nim | 9 ++-- compiler/options.nim | 4 +- config/nimdoc.cfg | 4 +- koch.nim | 1 + tools/nimweb.nim | 104 +++++++++++++++++++++++++------------------ 5 files changed, 70 insertions(+), 52 deletions(-) diff --git a/compiler/docgen.nim b/compiler/docgen.nim index 75b599ae91..63883af5cb 100644 --- a/compiler/docgen.nim +++ b/compiler/docgen.nim @@ -517,12 +517,11 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) = path = path[cwd.len+1 .. ^1].replace('\\', '/') let gitUrl = getConfigVar(d.conf, "git.url") if gitUrl.len > 0: - var commit = getConfigVar(d.conf, "git.commit") - if commit.len == 0: commit = "master" + let commit = getConfigVar(d.conf, "git.commit", "master") + let develBranch = getConfigVar(d.conf, "git.devel", "devel") dispA(d.conf, seeSrcRope, "$1", "", [ropeFormatNamedVars(d.conf, docItemSeeSrc, - ["path", "line", "url", "commit"], [rope path, - rope($n.info.line), rope gitUrl, - rope commit])]) + ["path", "line", "url", "commit", "devel"], [rope path, + rope($n.info.line), rope gitUrl, rope commit, rope develBranch])]) add(d.section[k], ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.item"), ["name", "header", "desc", "itemID", "header_plain", "itemSym", diff --git a/compiler/options.nim b/compiler/options.nim index 7cca403212..fcbb98fe63 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -406,8 +406,8 @@ proc mainCommandArg*(conf: ConfigRef): string = proc existsConfigVar*(conf: ConfigRef; key: string): bool = result = hasKey(conf.configVars, key) -proc getConfigVar*(conf: ConfigRef; key: string): string = - result = conf.configVars.getOrDefault key +proc getConfigVar*(conf: ConfigRef; key: string, default = ""): string = + result = conf.configVars.getOrDefault(key, default) proc setConfigVar*(conf: ConfigRef; key, val: string) = conf.configVars[key] = val diff --git a/config/nimdoc.cfg b/config/nimdoc.cfg index 6b6ec2d833..96e91283a4 100644 --- a/config/nimdoc.cfg +++ b/config/nimdoc.cfg @@ -55,6 +55,8 @@ doc.item.toc = """ # HTML rendered for doc.item's seeSrc variable. Note that this will render to # the empty string if you don't pass anything through --docSeeSrcURL. Available # substitutaion variables here are: +# * $commit: branch/commit to use in source link. +# * $devel: branch to use in edit link. # * $path: relative path to the file being processed. # * $line: line of the item in the original source file. # * $url: whatever you did pass through the --docSeeSrcUrl switch (which also @@ -62,7 +64,7 @@ doc.item.toc = """ doc.item.seesrc = """  Source -Edit +Edit """ doc.toc = """ diff --git a/koch.nim b/koch.nim index 9411a95de3..133c7e32bd 100644 --- a/koch.nim +++ b/koch.nim @@ -50,6 +50,7 @@ Boot options: Commands for core developers: web [options] generates the website and the full documentation + (see `nimweb.nim` for cmd line options) website [options] generates only the website csource -d:release builds the C sources for installation pdf builds the PDF documentation diff --git a/tools/nimweb.nim b/tools/nimweb.nim index 6e1d9d3596..e74b081eaf 100644 --- a/tools/nimweb.nim +++ b/tools/nimweb.nim @@ -13,16 +13,18 @@ import from xmltree import escape -const gitRepo = "https://github.com/nim-lang/Nim" - type TKeyValPair = tuple[key, id, val: string] TConfigData = object of RootObj tabs, links: seq[TKeyValPair] doc, srcdoc, srcdoc2, webdoc, pdf: seq[string] - authors, projectName, projectTitle, logo, infile, outdir, ticker: string + authors, projectName, projectTitle, logo, infile, ticker: string vars: StringTableRef + nimCompiler: string nimArgs: string + gitURL: string + docHTMLOutput: string + webUploadOutput: string quotations: Table[string, tuple[quote, author: string]] numProcessors: int # Set by parallelBuild:n, only works for values > 0. gaId: string # google analytics ID, nil means analytics are disabled @@ -51,8 +53,10 @@ proc initConfigData(c: var TConfigData) = c.webdoc = @[] c.pdf = @[] c.infile = "" - c.outdir = "" c.nimArgs = "--hint[Conf]:off --hint[Path]:off --hint[Processing]:off -d:boot " + c.gitURL = "https://github.com/nim-lang/Nim" + c.docHTMLOutput = "doc/html" + c.webUploadOutput = "web/upload" c.authors = "" c.projectTitle = "" c.projectName = "" @@ -79,14 +83,19 @@ const Usage: nimweb [options] ini-file[.ini] [compile_options] Options: - -o, --output:dir set the output directory (default: same as ini-file) - --var:name=value set the value of a variable -h, --help shows this help -v, --version shows the version + -o, --output overrides output directory instead of default + web/upload and doc/html + --nimCompiler overrides nim compiler; default = bin/nim + --var:name=value set the value of a variable --website only build the website, not the full documentation --pdf build the PDF version of the documentation --json2 build JSON of the documentation --onlyDocs build only the documentation + --git.url override base url in generated doc links + --git.commit override commit/branch in generated doc links 'source' + --git.devel override devel branch in generated doc links 'edit' Compile_options: will be passed to the Nim compiler """ @@ -145,7 +154,11 @@ proc parseCmdLine(c: var TConfigData) = of "version", "v": stdout.write(version & "\n") quit(0) - of "o", "output": c.outdir = val + of "output", "o": + c.webUploadOutput = val + c.docHTMLOutput = val / "docs" + of "nimcompiler": + c.nimCompiler = val of "parallelbuild": try: let num = parseInt(val) @@ -163,8 +176,14 @@ proc parseCmdLine(c: var TConfigData) = of "googleanalytics": c.gaId = val c.nimArgs.add("--doc.googleAnalytics:" & val & " ") + of "git.url": + c.gitURL = val + of "git.commit": + c.nimArgs.add("--git.commit:" & val & " ") + of "git.devel": + c.nimArgs.add("--git.devel:" & val & " ") else: - echo("Invalid argument $1" % [key]) + echo("Invalid argument '$1'" % [key]) quit(usage) of cmdEnd: break if c.infile.len == 0: quit(usage) @@ -244,15 +263,14 @@ proc parseIniFile(c: var TConfigData) = close(p) if c.projectName.len == 0: c.projectName = changeFileExt(extractFilename(c.infile), "") - if c.outdir.len == 0: - c.outdir = splitFile(c.infile).dir # ------------------- main ---------------------------------------------------- proc exe(f: string): string = return addFileExt(f, ExeExt) -proc findNim(): string = +proc findNim(c: TConfigData): string = + if c.nimCompiler.len > 0: return c.nimCompiler var nim = "nim".exe result = "bin" / nim if existsFile(result): return @@ -289,9 +307,9 @@ proc buildDocSamples(c: var TConfigData, destPath: string) = ## it didn't make much sense to integrate into the existing generic ## documentation builders. const src = "doc"/"docgen_sample.nim" - exec(findNim() & " doc $# -o:$# $#" % + exec(findNim(c) & " doc $# -o:$# $#" % [c.nimArgs, destPath / "docgen_sample.html", src]) - exec(findNim() & " doc2 $# -o:$# $#" % + exec(findNim(c) & " doc2 $# -o:$# $#" % [c.nimArgs, destPath / "docgen_sample2.html", src]) proc pathPart(d: string): string = splitFile(d).dir.replace('\\', '/') @@ -302,23 +320,23 @@ proc buildDoc(c: var TConfigData, destPath: string) = commands = newSeq[string](len(c.doc) + len(c.srcdoc) + len(c.srcdoc2)) i = 0 for d in items(c.doc): - commands[i] = findNim() & " rst2html $# --git.url:$# -o:$# --index:on $#" % - [c.nimArgs, gitRepo, + commands[i] = findNim(c) & " rst2html $# --git.url:$# -o:$# --index:on $#" % + [c.nimArgs, c.gitURL, destPath / changeFileExt(splitFile(d).name, "html"), d] i.inc for d in items(c.srcdoc): - commands[i] = findNim() & " doc0 $# --git.url:$# -o:$# --index:on $#" % - [c.nimArgs, gitRepo, + commands[i] = findNim(c) & " doc0 $# --git.url:$# -o:$# --index:on $#" % + [c.nimArgs, c.gitURL, destPath / changeFileExt(splitFile(d).name, "html"), d] i.inc for d in items(c.srcdoc2): - commands[i] = findNim() & " doc2 $# --git.url:$# -o:$# --index:on $#" % - [c.nimArgs, gitRepo, + commands[i] = findNim(c) & " doc2 $# --git.url:$# -o:$# --index:on $#" % + [c.nimArgs, c.gitURL, destPath / changeFileExt(splitFile(d).name, "html"), d] i.inc mexec(commands, c.numProcessors) - exec(findNim() & " buildIndex -o:$1/theindex.html $1" % [destPath]) + exec(findNim(c) & " buildIndex -o:$1/theindex.html $1" % [destPath]) proc buildPdfDoc(c: var TConfigData, destPath: string) = createDir(destPath) @@ -327,7 +345,7 @@ proc buildPdfDoc(c: var TConfigData, destPath: string) = else: const pdflatexcmd = "pdflatex -interaction=nonstopmode " for d in items(c.pdf): - exec(findNim() & " rst2tex $# $#" % [c.nimArgs, d]) + exec(findNim(c) & " rst2tex $# $#" % [c.nimArgs, d]) # call LaTeX twice to get cross references right: exec(pdflatexcmd & changeFileExt(d, "tex")) exec(pdflatexcmd & changeFileExt(d, "tex")) @@ -347,8 +365,8 @@ proc buildAddDoc(c: var TConfigData, destPath: string) = # build additional documentation (without the index): var commands = newSeq[string](c.webdoc.len) for i, doc in pairs(c.webdoc): - commands[i] = findNim() & " doc2 $# --git.url:$# -o:$# $#" % - [c.nimArgs, gitRepo, + commands[i] = findNim(c) & " doc2 $# --git.url:$# -o:$# $#" % + [c.nimArgs, c.gitURL, destPath / changeFileExt(splitFile(doc).name, "html"), doc] mexec(commands, c.numProcessors) @@ -431,9 +449,9 @@ proc buildNewsRss(c: var TConfigData, destPath: string) = generateRss(destFilename, parseNewsTitles(srcFilename)) -proc buildJS(destPath: string) = - exec(findNim() & " js -d:release --out:$1 web/nimblepkglist.nim" % - [destPath / "nimblepkglist.js"]) +proc buildJS(c: TConfigData) = + exec(findNim(c) & " js -d:release --out:$1 web/nimblepkglist.nim" % + [c.webUploadOutput / "nimblepkglist.js"]) proc readSponsors(sponsorsFile: string): seq[Sponsor] = result = @[] @@ -464,7 +482,7 @@ const cmdRst2Html = " rst2html --compileonly $1 -o:web/$2.temp web/$2.rst" proc buildPage(c: var TConfigData, file, title, rss: string, assetDir = "") = - exec(findNim() & cmdRst2Html % [c.nimArgs, file]) + exec(findNim(c) & cmdRst2Html % [c.nimArgs, file]) var temp = "web" / changeFileExt(file, "temp") var content: string try: @@ -472,7 +490,7 @@ proc buildPage(c: var TConfigData, file, title, rss: string, assetDir = "") = except IOError: quit("[Error] cannot open: " & temp) var f: File - var outfile = "web/upload/$#.html" % file + var outfile = c.webUploadOutput / "$#.html" % file if not existsDir(outfile.splitFile.dir): createDir(outfile.splitFile.dir) if open(f, outfile, fmWrite): @@ -502,27 +520,25 @@ proc buildWebsite(c: var TConfigData) = let rss = if file in ["news", "index"]: extractFilename(rssUrl) else: "" if '.' in file: continue buildPage(c, file, if file == "question": "FAQ" else: file, rss) - copyDir("web/assets", "web/upload/assets") - buildNewsRss(c, "web/upload") - buildSponsors(c, "web/upload") - buildNews(c, "web/news", "web/upload/news") + copyDir("web/assets", c.webUploadOutput / "assets") + buildNewsRss(c, c.webUploadOutput) + buildSponsors(c, c.webUploadOutput) + buildNews(c, "web/news", c.webUploadOutput / "news") + +proc onlyDocs(c: var TConfigData) = + createDir(c.docHTMLOutput) + buildDocSamples(c, c.docHTMLOutput) + buildDoc(c, c.docHTMLOutput) proc main(c: var TConfigData) = buildWebsite(c) - buildJS("web/upload") - const docup = "web/upload/" & NimVersion + buildJS(c) + let docup = c.webUploadOutput / NimVersion createDir(docup) buildAddDoc(c, docup) buildDocSamples(c, docup) buildDoc(c, docup) - createDir("doc/html") - buildDocSamples(c, "doc/html") - buildDoc(c, "doc/html") - -proc onlyDocs(c: var TConfigData) = - createDir("doc/html") - buildDocSamples(c, "doc/html") - buildDoc(c, "doc/html") + onlyDocs(c) proc json2(c: var TConfigData) = const destPath = "web/json2" @@ -530,8 +546,8 @@ proc json2(c: var TConfigData) = var i = 0 for d in items(c.srcdoc2): createDir(destPath / splitFile(d).dir) - commands[i] = findNim() & " jsondoc2 $# --git.url:$# -o:$# --index:on $#" % - [c.nimArgs, gitRepo, + commands[i] = findNim(c) & " jsondoc2 $# --git.url:$# -o:$# --index:on $#" % + [c.nimArgs, c.gitURL, destPath / changeFileExt(d, "json"), d] i.inc From e11d52a4e8e3b7522a26721f604692691a5fbeca Mon Sep 17 00:00:00 2001 From: Euan T Date: Mon, 30 Jul 2018 13:39:32 +0100 Subject: [PATCH 02/11] Update example code for UDP sockets --- lib/pure/net.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/net.nim b/lib/pure/net.nim index 5d2efebee6..771e7de10d 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -41,7 +41,7 @@ ## immediately. ## ## .. code-block:: Nim -## var socket = newSocket() +## var socket = newSocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP) ## socket.sendTo("192.168.0.1", Port(27960), "status\n") ## ## Creating a server From 5491f1f53b4011785b41b30897b73538d564fd55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Nihlg=C3=A5rd?= Date: Mon, 30 Jul 2018 15:24:16 +0200 Subject: [PATCH 03/11] Deprecate the dot style for import paths (#8474) --- changelog.md | 2 ++ compiler/modulepaths.nim | 1 + doc/manual.rst | 23 ++++++++++++----------- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/changelog.md b/changelog.md index 43b351ef11..e0027d5044 100644 --- a/changelog.md +++ b/changelog.md @@ -22,6 +22,8 @@ become an error in the future. - The ``'c`` and ``'C'`` prefix for octal literals is now deprecated to bring the language in line with the standard library (e.g. ``parseOct``). +- The dot style for import paths (e.g ``import path.to.module`` instead of + ``import path/to/module``) has been deprecated. #### Breaking changes in the standard library diff --git a/compiler/modulepaths.nim b/compiler/modulepaths.nim index ef0831ad6f..e5cbf3a2c7 100644 --- a/compiler/modulepaths.nim +++ b/compiler/modulepaths.nim @@ -155,6 +155,7 @@ proc getModuleName*(conf: ConfigRef; n: PNode): string = # hacky way to implement 'x / y /../ z': result = renderTree(n, {renderNoComments}).replace(" ") of nkDotExpr: + localError(conf, n.info, warnDeprecated, "using '.' instead of '/' in import paths") result = renderTree(n, {renderNoComments}).replace(".", "/") of nkImportAs: result = getModuleName(conf, n.sons[0]) diff --git a/doc/manual.rst b/doc/manual.rst index 7298b02a30..abdc4ce695 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -6229,10 +6229,10 @@ imported: :test: "nim c $1" :status: 1 - import strutils except `%`, toUpper + import strutils except `%`, toUpperAscii # doesn't work then: - echo "$1" % "abc".toUpper + echo "$1" % "abc".toUpperAscii It is not checked that the ``except`` list is really exported from the module. @@ -6261,24 +6261,24 @@ A module alias can be introduced via the ``as`` keyword: echo su.format("$1", "lalelu") -The original module name is then not accessible. The -notations ``path/to/module`` or ``path.to.module`` or ``"path/to/module"`` -can be used to refer to a module in subdirectories: +The original module name is then not accessible. The notations +``path/to/module`` or ``"path/to/module"`` can be used to refer to a module +in subdirectories: .. code-block:: nim - import lib.pure.strutils, lib/pure/os, "lib/pure/times" + import lib/pure/os, "lib/pure/times" -Note that the module name is still ``strutils`` and not ``lib.pure.strutils`` +Note that the module name is still ``strutils`` and not ``lib/pure/strutils`` and so one **cannot** do: .. code-block:: nim - import lib.pure.strutils - echo lib.pure.strutils + import lib/pure/strutils + echo lib/pure/strutils.toUpperAscii("abc") Likewise the following does not make sense as the name is ``strutils`` already: .. code-block:: nim - import lib.pure.strutils as strutils + import lib/pure/strutils as strutils Collective imports from a directory @@ -6297,7 +6297,8 @@ name is not a valid Nim identifier it needs to be a string literal: Pseudo import/include paths ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -A directory can also be a so called "pseudo directory". +A directory can also be a so called "pseudo directory". They can be used to +avoid ambiguity when there are multiple modules with the same path. There are two pseudo directories: From 931273cc6be25a4d2bc79e8a0eff8781c1f4855e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Nihlg=C3=A5rd?= Date: Mon, 30 Jul 2018 22:28:24 +0200 Subject: [PATCH 04/11] Fix ref bug in vmgen (#8424) --- compiler/vm.nim | 9 +---- compiler/vmgen.nim | 88 ++++++++++++++++++++++------------------------ tests/vm/tref.nim | 7 +++- 3 files changed, 50 insertions(+), 54 deletions(-) diff --git a/compiler/vm.nim b/compiler/vm.nim index 373a64e39d..d7e1b5da30 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -616,19 +616,12 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = let rc = instr.regC case regs[ra].kind of rkNodeAddr: - # XXX: Workaround for vmgen bug: let n = regs[rc].regToNode - if (nfIsRef in regs[ra].nodeAddr[].flags or - regs[ra].nodeAddr[].kind == nkNilLit) and nfIsRef notin n.flags: - if regs[ra].nodeAddr[].kind == nkNilLit: - stackTrace(c, tos, pc, errNilAccess) - regs[ra].nodeAddr[][] = n[] - regs[ra].nodeAddr[].flags.incl nfIsRef # `var object` parameters are sent as rkNodeAddr. When they are mutated # vmgen generates opcWrDeref, which means that we must dereference # twice. # TODO: This should likely be handled differently in vmgen. - elif (nfIsRef notin regs[ra].nodeAddr[].flags and + if (nfIsRef notin regs[ra].nodeAddr[].flags and nfIsRef notin n.flags): regs[ra].nodeAddr[][] = n[] else: diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index d2243376c1..31e04a6c07 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -37,7 +37,9 @@ when hasFFI: import evalffi type - TGenFlag = enum gfAddrOf, gfFieldAccess + TGenFlag = enum + gfNode # Affects how variables are loaded - always loads as rkNode + gfNodeAddr # Affects how variables are loaded - always loads as rkNodeAddr TGenFlags = set[TGenFlag] proc debugInfo(c: PCtx; info: TLineInfo): string = @@ -563,7 +565,7 @@ proc genIndex(c: PCtx; n: PNode; arr: PType): TRegister = proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) = case le.kind of nkBracketExpr: - let dest = c.genx(le.sons[0], {gfAddrOf, gfFieldAccess}) + let dest = c.genx(le.sons[0], {gfNode}) let idx = c.genIndex(le.sons[1], le.sons[0].typ) c.gABC(le, opcWrArr, dest, idx, value) c.freeTemp(dest) @@ -571,17 +573,17 @@ proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) = of nkDotExpr, nkCheckedFieldExpr: # XXX field checks here let left = if le.kind == nkDotExpr: le else: le.sons[0] - let dest = c.genx(left.sons[0], {gfAddrOf, gfFieldAccess}) + let dest = c.genx(left.sons[0], {gfNode}) let idx = genField(c, left.sons[1]) c.gABC(left, opcWrObj, dest, idx, value) c.freeTemp(dest) of nkDerefExpr, nkHiddenDeref: - let dest = c.genx(le.sons[0], {gfAddrOf}) + let dest = c.genx(le.sons[0], {gfNode}) c.gABC(le, opcWrDeref, dest, 0, value) c.freeTemp(dest) of nkSym: if le.sym.isGlobal: - let dest = c.genx(le, {gfAddrOf}) + let dest = c.genx(le, {gfNodeAddr}) c.gABC(le, opcWrDeref, dest, 0, value) c.freeTemp(dest) else: @@ -1252,41 +1254,21 @@ proc canElimAddr(n: PNode): PNode = # addr ( deref ( x )) --> x result = n.sons[0].sons[0] -proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode; - flags: TGenFlags) = - # a nop for certain types - let isAddr = opc in {opcAddrNode, opcAddrReg} - if isAddr and (let m = canElimAddr(n); m != nil): +proc genAddr(c: PCtx, n: PNode, dest: var TDest, flags: TGenFlags) = + if (let m = canElimAddr(n); m != nil): gen(c, m, dest, flags) return - let af = if n[0].kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr}: {gfAddrOf, gfFieldAccess} - else: {gfAddrOf} - let newflags = if isAddr: flags+af else: flags - # consider: - # proc foo(f: var ref int) = - # f = new(int) - # proc blah() = - # var x: ref int - # foo x - # - # The type of 'f' is 'var ref int' and of 'x' is 'ref int'. Hence for - # nkAddr we must not use 'unneededIndirection', but for deref we use it. - if not isAddr and unneededIndirection(n.sons[0]): - gen(c, n.sons[0], dest, newflags) - if gfAddrOf notin flags and fitsRegister(n.typ): - c.gABC(n, opcNodeToReg, dest, dest) - elif isAddr and isGlobal(n.sons[0]): + let af = if n[0].kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr}: {gfNode} + else: {gfNodeAddr} + let newflags = flags-{gfNode, gfNodeAddr}+af + + if isGlobal(n.sons[0]): gen(c, n.sons[0], dest, flags+af) else: let tmp = c.genx(n.sons[0], newflags) if dest < 0: dest = c.getTemp(n.typ) - if not isAddr: - gABC(c, n, opc, dest, tmp) - assert n.typ != nil - if gfAddrOf notin flags and fitsRegister(n.typ): - c.gABC(n, opcNodeToReg, dest, dest) - elif c.prc.slots[tmp].kind >= slotTempUnknown: + if c.prc.slots[tmp].kind >= slotTempUnknown: gABC(c, n, opcAddrNode, dest, tmp) # hack ahead; in order to fix bug #1781 we mark the temporary as # permanent, so that it's not used for anything else: @@ -1297,6 +1279,19 @@ proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode; gABC(c, n, opcAddrReg, dest, tmp) c.freeTemp(tmp) +proc genDeref(c: PCtx, n: PNode, dest: var TDest, flags: TGenFlags) = + if unneededIndirection(n.sons[0]): + gen(c, n.sons[0], dest, flags) + if {gfNodeAddr, gfNode} * flags == {} and fitsRegister(n.typ): + c.gABC(n, opcNodeToReg, dest, dest) + else: + let tmp = c.genx(n.sons[0], flags) + if dest < 0: dest = c.getTemp(n.typ) + gABC(c, n, opcLdDeref, dest, tmp) + assert n.typ != nil + if {gfNodeAddr, gfNode} * flags == {} and fitsRegister(n.typ): + c.gABC(n, opcNodeToReg, dest, dest) + proc whichAsgnOpc(n: PNode): TOpcode = case n.typ.skipTypes(abstractRange-{tyTypeDesc}).kind of tyBool, tyChar, tyEnum, tyOrdinal, tyInt..tyInt64, tyUInt..tyUInt64: @@ -1382,7 +1377,7 @@ proc preventFalseAlias(c: PCtx; n: PNode; opc: TOpcode; proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) = case le.kind of nkBracketExpr: - let dest = c.genx(le.sons[0], {gfAddrOf, gfFieldAccess}) + let dest = c.genx(le.sons[0], {gfNode}) let idx = c.genIndex(le.sons[1], le.sons[0].typ) let tmp = c.genx(ri) if le.sons[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind in { @@ -1394,13 +1389,13 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) = of nkDotExpr, nkCheckedFieldExpr: # XXX field checks here let left = if le.kind == nkDotExpr: le else: le.sons[0] - let dest = c.genx(left.sons[0], {gfAddrOf, gfFieldAccess}) + let dest = c.genx(left.sons[0], {gfNode}) let idx = genField(c, left.sons[1]) let tmp = c.genx(ri) c.preventFalseAlias(left, opcWrObj, dest, idx, tmp) c.freeTemp(tmp) of nkDerefExpr, nkHiddenDeref: - let dest = c.genx(le.sons[0], {gfAddrOf}) + let dest = c.genx(le.sons[0], {gfNode}) let tmp = c.genx(ri) c.preventFalseAlias(le, opcWrDeref, dest, 0, tmp) c.freeTemp(tmp) @@ -1409,7 +1404,7 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) = checkCanEval(c, le) if s.isGlobal: withTemp(tmp, le.typ): - c.gen(le, tmp, {gfAddrOf}) + c.gen(le, tmp, {gfNodeAddr}) let val = c.genx(ri) c.preventFalseAlias(le, opcWrDeref, tmp, 0, val) c.freeTemp(val) @@ -1427,7 +1422,7 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) = else: gen(c, ri, dest) else: - let dest = c.genx(le, {gfAddrOf}) + let dest = c.genx(le, {gfNodeAddr}) genAsgn(c, dest, ri, requiresCopy) proc genTypeLit(c: PCtx; t: PType; dest: var TDest) = @@ -1463,6 +1458,8 @@ proc genGlobalInit(c: PCtx; n: PNode; s: PSym) = c.freeTemp(tmp) proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) = + # gfNodeAddr and gfNode are mutually exclusive + assert card(flags * {gfNodeAddr, gfNode}) < 2 let s = n.sym if s.isGlobal: if sfCompileTime in s.flags or c.mode == emRepl: @@ -1474,13 +1471,13 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) = else: genGlobalInit(c, n, s) if dest < 0: dest = c.getTemp(n.typ) assert s.typ != nil - if gfAddrOf notin flags and fitsRegister(s.typ): + if gfNodeAddr in flags: + c.gABx(n, opcLdGlobalAddr, dest, s.position) + elif fitsRegister(s.typ) and gfNode notin flags: var cc = c.getTemp(n.typ) c.gABx(n, opcLdGlobal, cc, s.position) c.gABC(n, opcNodeToReg, dest, cc) c.freeTemp(cc) - elif {gfAddrOf, gfFieldAccess} * flags == {gfAddrOf}: - c.gABx(n, opcLdGlobalAddr, dest, s.position) else: c.gABx(n, opcLdGlobal, dest, s.position) else: @@ -1498,7 +1495,8 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) = cannotEval(c, n) template needsRegLoad(): untyped = - gfAddrOf notin flags and fitsRegister(n.typ.skipTypes({tyVar, tyLent})) + {gfNode, gfNodeAddr} * flags == {} and + fitsRegister(n.typ.skipTypes({tyVar, tyLent})) proc genArrAccess2(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode; flags: TGenFlags) = @@ -1634,7 +1632,7 @@ proc genVarSection(c: PCtx; n: PNode) = c.globals.add(sa) s.position = c.globals.len if a.sons[2].kind != nkEmpty: - let tmp = c.genx(a.sons[0], {gfAddrOf}) + let tmp = c.genx(a.sons[0], {gfNodeAddr}) let val = c.genx(a.sons[2]) c.genAdditionalCopy(a.sons[2], opcWrDeref, tmp, 0, val) c.freeTemp(val) @@ -1839,8 +1837,8 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) = of nkDotExpr: genObjAccess(c, n, dest, flags) of nkCheckedFieldExpr: genCheckedObjAccess(c, n, dest, flags) of nkBracketExpr: genArrAccess(c, n, dest, flags) - of nkDerefExpr, nkHiddenDeref: genAddrDeref(c, n, dest, opcLdDeref, flags) - of nkAddr, nkHiddenAddr: genAddrDeref(c, n, dest, opcAddrNode, flags) + of nkDerefExpr, nkHiddenDeref: genDeref(c, n, dest, flags) + of nkAddr, nkHiddenAddr: genAddr(c, n, dest, flags) of nkIfStmt, nkIfExpr: genIf(c, n, dest) of nkWhenStmt: # This is "when nimvm" node. Chose the first branch. diff --git a/tests/vm/tref.nim b/tests/vm/tref.nim index 27b7bf3132..f5cd23da5d 100644 --- a/tests/vm/tref.nim +++ b/tests/vm/tref.nim @@ -54,4 +54,9 @@ static: new(s) var ss = s s[] = 1 - doAssert ss[] == 1 \ No newline at end of file + doAssert ss[] == 1 + +static: # bug #8402 + type R = ref object + var empty: R + let otherEmpty = empty \ No newline at end of file From 818d9be31117a90c0707fdbb9e471abca2abac40 Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Tue, 31 Jul 2018 14:02:04 -0700 Subject: [PATCH 05/11] `lineInfoObj` (and `check`, `expect`) now return absolute paths (#8466) --- changelog.md | 3 ++- compiler/vm.nim | 2 +- lib/core/macros.nim | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/changelog.md b/changelog.md index e0027d5044..3dfe63f3bd 100644 --- a/changelog.md +++ b/changelog.md @@ -25,7 +25,6 @@ - The dot style for import paths (e.g ``import path.to.module`` instead of ``import path/to/module``) has been deprecated. - #### Breaking changes in the standard library - ``re.split`` for empty regular expressions now yields every character in @@ -61,6 +60,8 @@ 1-based coordinates on POSIX for correct behaviour; the Windows behaviour was always correct). +- ``lineInfoObj`` now returns absolute path instead of project path. + It's used by ``lineInfo``, ``check``, ``expect``, ``require``, etc. #### Breaking changes in the compiler diff --git a/compiler/vm.nim b/compiler/vm.nim index d7e1b5da30..f8b1cee731 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -1409,7 +1409,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = of opcNGetFile: decodeB(rkNode) let n = regs[rb].node - regs[ra].node = newStrNode(nkStrLit, toFilename(c.config, n.info)) + regs[ra].node = newStrNode(nkStrLit, toFullPath(c.config, n.info)) regs[ra].node.info = n.info regs[ra].node.typ = n.typ of opcNGetLine: diff --git a/lib/core/macros.nim b/lib/core/macros.nim index 345c53b088..17178a6342 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -425,6 +425,7 @@ proc getColumn(arg: NimNode): int {.magic: "NLineInfo", noSideEffect.} proc getFile(arg: NimNode): string {.magic: "NLineInfo", noSideEffect.} proc lineInfoObj*(n: NimNode): LineInfo {.compileTime.} = + ## returns ``LineInfo`` of ``n``, using absolute path for ``filename`` result.filename = n.getFile result.line = n.getLine result.column = n.getColumn From 9e37e3e5e85a7be33b8d1a22c64540415282bafb Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Wed, 1 Aug 2018 00:22:51 -0700 Subject: [PATCH 06/11] add hintCC to optionally disable printing 'CC: filename' (#8479) --- compiler/extccomp.nim | 5 +++-- compiler/lineinfos.nim | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index f4ef930707..a90442369e 100644 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -645,7 +645,7 @@ proc compileCFile(conf: ConfigRef; list: CFileList, script: var Rope, cmds: var if optCompileOnly notin conf.globalOptions: add(cmds, compileCmd) let (_, name, _) = splitFile(it.cname) - add(prettyCmds, "CC: " & name) + add(prettyCmds, if hintCC in conf.notes: "CC: " & name else: "") if optGenScript in conf.globalOptions: add(script, compileCmd) add(script, "\n") @@ -773,7 +773,8 @@ proc callCCompiler*(conf: ConfigRef; projectfile: string) = var prettyCmds: TStringSeq = @[] let prettyCb = proc (idx: int) = when declared(echo): - echo prettyCmds[idx] + let cmd = prettyCmds[idx] + if cmd != "": echo cmd compileCFile(conf, conf.toCompile, script, cmds, prettyCmds) if optCompileOnly notin conf.globalOptions: execCmdsInParallel(conf, cmds, prettyCb) diff --git a/compiler/lineinfos.nim b/compiler/lineinfos.nim index b8678e6ba7..261dcb44e2 100644 --- a/compiler/lineinfos.nim +++ b/compiler/lineinfos.nim @@ -37,7 +37,7 @@ type warnProveInit, warnProveField, warnProveIndex, warnGcUnsafe, warnGcUnsafe2, warnUninit, warnGcMem, warnDestructor, warnLockLevel, warnResultShadowed, warnInconsistentSpacing, warnUser, - hintSuccess, hintSuccessX, + hintSuccess, hintSuccessX, hintCC, hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded, hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled, hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath, @@ -94,6 +94,7 @@ const warnUser: "$1", hintSuccess: "operation successful", hintSuccessX: "operation successful ($# lines compiled; $# sec total; $#; $#)", + hintCC: "CC: \'$1\'", # unused hintLineTooLong: "line too long", hintXDeclaredButNotUsed: "'$1' is declared but not used", hintConvToBaseNotNeeded: "conversion to base object is not needed", @@ -136,7 +137,7 @@ const "Spacing", "User"] HintsToStr* = [ - "Success", "SuccessX", "LineTooLong", + "Success", "SuccessX", "CC", "LineTooLong", "XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded", "ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf", "Path", "CondTrue", "Name", "Pattern", "Exec", "Link", "Dependency", From 8f4c5a8955594b4f2dc31f9629af9ad3d4780c2c Mon Sep 17 00:00:00 2001 From: jcosborn Date: Wed, 1 Aug 2018 03:57:35 -0500 Subject: [PATCH 07/11] fixed #7894 (#8496) make system tests run properly --- lib/system/alloc.nim | 3 ++- tests/system/t7894.nim | 18 ++++++++++++++++ tests/system/talloc.nim | 43 ++++++++++++++++++++------------------ tests/system/talloc2.nim | 3 +++ tests/system/tdeepcopy.nim | 6 +++--- tests/system/tio.nim | 5 ++++- tests/system/tparams.nim | 15 +++++++------ 7 files changed, 62 insertions(+), 31 deletions(-) create mode 100644 tests/system/t7894.nim diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim index ca2d76225b..ffb7aaf86c 100644 --- a/lib/system/alloc.nim +++ b/lib/system/alloc.nim @@ -436,8 +436,9 @@ proc requestOsChunks(a: var MemRegion, size: int): PBigChunk = a.nextChunkSize = PageSize*4 else: a.nextChunkSize = min(roundup(usedMem shr 2, PageSize), a.nextChunkSize * 2) - var size = size + a.nextChunkSize = min(a.nextChunkSize, MaxBigChunkSize) + var size = size if size > a.nextChunkSize: result = cast[PBigChunk](osAllocPages(size)) else: diff --git a/tests/system/t7894.nim b/tests/system/t7894.nim new file mode 100644 index 0000000000..2808e50200 --- /dev/null +++ b/tests/system/t7894.nim @@ -0,0 +1,18 @@ +discard """ +""" + +import os + +const size = 250000000 +var saved = newSeq[seq[int8]]() + +for i in 0..22: + # one of these is 0.25GB. + #echo i + var x = newSeq[int8](size) + sleep(10) + saved.add(x) + +for x in saved: + #echo x.len + doAssert x.len == size diff --git a/tests/system/talloc.nim b/tests/system/talloc.nim index 18396041d0..bf2cd97a86 100644 --- a/tests/system/talloc.nim +++ b/tests/system/talloc.nim @@ -1,54 +1,57 @@ +discard """ +""" + var x: ptr int x = cast[ptr int](alloc(7)) -assert x != nil +doAssert x != nil x = cast[ptr int](x.realloc(2)) -assert x != nil +doAssert x != nil x.dealloc() x = createU(int, 3) -assert x != nil +doAssert x != nil x.dealloc() x = create(int, 4) -assert cast[ptr array[4, int]](x)[0] == 0 -assert cast[ptr array[4, int]](x)[1] == 0 -assert cast[ptr array[4, int]](x)[2] == 0 -assert cast[ptr array[4, int]](x)[3] == 0 +doAssert cast[ptr array[4, int]](x)[0] == 0 +doAssert cast[ptr array[4, int]](x)[1] == 0 +doAssert cast[ptr array[4, int]](x)[2] == 0 +doAssert cast[ptr array[4, int]](x)[3] == 0 x = x.resize(4) -assert x != nil +doAssert x != nil x.dealloc() x = cast[ptr int](allocShared(100)) -assert x != nil +doAssert x != nil deallocShared(x) x = createSharedU(int, 3) -assert x != nil +doAssert x != nil x.deallocShared() x = createShared(int, 3) -assert x != nil -assert cast[ptr array[3, int]](x)[0] == 0 -assert cast[ptr array[3, int]](x)[1] == 0 -assert cast[ptr array[3, int]](x)[2] == 0 +doAssert x != nil +doAssert cast[ptr array[3, int]](x)[0] == 0 +doAssert cast[ptr array[3, int]](x)[1] == 0 +doAssert cast[ptr array[3, int]](x)[2] == 0 -assert x != nil +doAssert x != nil x = cast[ptr int](x.resizeShared(2)) -assert x != nil +doAssert x != nil x.deallocShared() x = create(int, 10) -assert x != nil +doAssert x != nil x = x.resize(12) -assert x != nil +doAssert x != nil x.dealloc() x = createShared(int, 1) -assert x != nil +doAssert x != nil x = x.resizeShared(1) -assert x != nil +doAssert x != nil x.deallocShared() x = cast[ptr int](alloc0(125 shl 23)) diff --git a/tests/system/talloc2.nim b/tests/system/talloc2.nim index c8cab78a1c..0757c07246 100644 --- a/tests/system/talloc2.nim +++ b/tests/system/talloc2.nim @@ -1,3 +1,6 @@ +discard """ +""" + const nmax = 2*1024*1024*1024 diff --git a/tests/system/tdeepcopy.nim b/tests/system/tdeepcopy.nim index f7a6e87fa4..383d2e8d13 100644 --- a/tests/system/tdeepcopy.nim +++ b/tests/system/tdeepcopy.nim @@ -65,7 +65,7 @@ proc main() = for val in table.values(): if myObj2.isNil: myObj2 = val - assert(myObj == myObj2) # passes + doAssert(myObj == myObj2) # passes var tableCopy: ListTableRef[int, SomeObj] deepCopy(tableCopy, table) @@ -80,7 +80,7 @@ proc main() = #echo cast[int](myObjCopy) #echo cast[int](myObjCopy2) - assert(myObjCopy == myObjCopy2) # fails + doAssert(myObjCopy == myObjCopy2) # fails type @@ -88,7 +88,7 @@ type counter, max: int data: array[0..99, (pointer, pointer)] -assert(sizeof(PtrTable) == 2*sizeof(int)+sizeof(pointer)*2*100) +doAssert(sizeof(PtrTable) == 2*sizeof(int)+sizeof(pointer)*2*100) main() echo "ok" diff --git a/tests/system/tio.nim b/tests/system/tio.nim index 3d4df806bd..7e9e189500 100644 --- a/tests/system/tio.nim +++ b/tests/system/tio.nim @@ -1,3 +1,6 @@ +discard """ +""" + import unittest, osproc, streams, os, strformat const STRING_DATA = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet." @@ -36,7 +39,7 @@ proc verifyFileSize(sz: int64) = discard execProcess(&"dd if=/dev/zero of={fn} bs=1000000 count={size_in_mb}") doAssert os.getFileSize(fn) == sz # Verify OS filesize by string - + var f = open(fn) doAssert f.getFileSize() == sz # Verify file handle filesize f.close() diff --git a/tests/system/tparams.nim b/tests/system/tparams.nim index 1358212f2f..dd5511b8f7 100644 --- a/tests/system/tparams.nim +++ b/tests/system/tparams.nim @@ -1,3 +1,6 @@ +discard """ +""" + import os import osproc import parseopt2 @@ -7,12 +10,12 @@ let argv = commandLineParams() if argv == @[]: # this won't work with spaces - assert execShellCmd(getAppFilename() & " \"foo bar\" --aa:bar=a --a=c:d --ab -c --a[baz]:doo") == 0 + doAssert execShellCmd(getAppFilename() & " \"foo bar\" --aa:bar=a --a=c:d --ab -c --a[baz]:doo") == 0 else: let f = toSeq(getopt()) echo f.repr - assert f[0].kind == cmdArgument and f[0].key == "foo bar" and f[0].val == "" - assert f[1].kind == cmdLongOption and f[1].key == "aa" and f[1].val == "bar=a" - assert f[2].kind == cmdLongOption and f[2].key == "a=c" and f[2].val == "d" - assert f[3].kind == cmdLongOption and f[3].key == "ab" and f[3].val == "" - assert f[4].kind == cmdShortOption and f[4].key == "c" and f[4].val == "" + doAssert f[0].kind == cmdArgument and f[0].key == "foo bar" and f[0].val == "" + doAssert f[1].kind == cmdLongOption and f[1].key == "aa" and f[1].val == "bar=a" + doAssert f[2].kind == cmdLongOption and f[2].key == "a=c" and f[2].val == "d" + doAssert f[3].kind == cmdLongOption and f[3].key == "ab" and f[3].val == "" + doAssert f[4].kind == cmdShortOption and f[4].key == "c" and f[4].val == "" From 674bd7bfad100a07e051e0a310bcf0a64c355a79 Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Wed, 1 Aug 2018 16:19:29 -0700 Subject: [PATCH 08/11] fix wrong arch defined(osx) (#8492) --- tests/stdlib/tos.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/stdlib/tos.nim b/tests/stdlib/tos.nim index 6ccc29bf65..10f439dfad 100644 --- a/tests/stdlib/tos.nim +++ b/tests/stdlib/tos.nim @@ -145,7 +145,7 @@ else: echo getLastModificationTime("a") == tm removeFile("a") -when defined(Linux) or defined(osx): +when defined(posix): block normalizedPath: block relative: From 78c0ac54070e860ec0ed8ac0b58658f7ad52227a Mon Sep 17 00:00:00 2001 From: andri lim Date: Thu, 2 Aug 2018 17:56:44 +0700 Subject: [PATCH 09/11] fixes #7827, bindSym enhancement (#8499) * bindSym power up, working prototype * update bindSym doc * add bindSym test * fix some typo * fix bindSym doc * get rid of specialops field from vm * add experimental: dynamicBindSym --- changelog.md | 5 +++ compiler/options.nim | 3 +- compiler/semmagic.nim | 67 ++++++++++++++++++++++++++++++++++++++- compiler/semtypes.nim | 1 + compiler/vm.nim | 18 ++++++++++- compiler/vmdef.nim | 5 +-- compiler/vmgen.nim | 45 ++++++++++++++++++++++---- lib/core/macros.nim | 10 +++++- tests/macros/tbindsym.nim | 42 ++++++++++++++++++++++++ 9 files changed, 183 insertions(+), 13 deletions(-) diff --git a/changelog.md b/changelog.md index 3dfe63f3bd..045286ef9c 100644 --- a/changelog.md +++ b/changelog.md @@ -196,4 +196,9 @@ - Nintendo Switch was added as a new platform target. See [the compiler user guide](https://nim-lang.org/docs/nimc.html) for more info. +- macros.bindSym now capable to accepts not only literal string or string constant expression. + bindSym enhancement make it also can accepts computed string or ident node inside macros / + compile time functions / static blocks. Only in templates / regular code it retains it's old behavior. + This new feature can be accessed via {.experimental: "dynamicBindSym".} pragma/switch + ### Bugfixes diff --git a/compiler/options.nim b/compiler/options.nim index fcbb98fe63..598adf27d2 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -116,7 +116,8 @@ type callOperator, parallel, destructor, - notnil + notnil, + dynamicBindSym SymbolFilesOption* = enum disabledSf, writeOnlySf, readOnlySf, v2Sf diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index b5875c67a9..8bfa5545e6 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -207,6 +207,67 @@ proc semBindSym(c: PContext, n: PNode): PNode = else: errorUndeclaredIdentifier(c, n.sons[1].info, sl.strVal) +proc opBindSym(c: PContext, scope: PScope, n: PNode, isMixin: int, info: PNode): PNode = + if n.kind notin {nkStrLit, nkRStrLit, nkTripleStrLit, nkIdent}: + localError(c.config, info.info, errStringOrIdentNodeExpected) + return errorNode(c, n) + + if isMixin < 0 or isMixin > high(TSymChoiceRule).int: + localError(c.config, info.info, errConstExprExpected) + return errorNode(c, n) + + let id = if n.kind == nkIdent: n + else: newIdentNode(getIdent(c.cache, n.strVal), info.info) + + let tmpScope = c.currentScope + c.currentScope = scope + let s = qualifiedLookUp(c, id, {checkUndeclared}) + if s != nil: + # we need to mark all symbols: + result = symChoice(c, id, s, TSymChoiceRule(isMixin)) + else: + errorUndeclaredIdentifier(c, info.info, if n.kind == nkIdent: n.ident.s + else: n.strVal) + c.currentScope = tmpScope + +proc semDynamicBindSym(c: PContext, n: PNode): PNode = + # inside regular code, bindSym resolves to the sym-choice + # nodes (see tinspectsymbol) + if not (c.inStaticContext > 0 or getCurrOwner(c).isCompileTimeProc): + return semBindSym(c, n) + + if c.graph.vm.isNil: + setupGlobalCtx(c.module, c.graph) + + let + vm = PCtx c.graph.vm + # cache the current scope to + # prevent it lost into oblivion + scope = c.currentScope + + # cannot use this + # vm.config.features.incl dynamicBindSym + + proc bindSymWrapper(a: VmArgs) = + # capture PContext and currentScope + # param description: + # 0. ident, a string literal / computed string / or ident node + # 1. bindSym rule + # 2. info node + a.setResult opBindSym(c, scope, a.getNode(0), a.getInt(1).int, a.getNode(2)) + + let + # altough we use VM callback here, it is not + # executed like 'normal' VM callback + idx = vm.registerCallback("bindSymImpl", bindSymWrapper) + # dummy node to carry idx information to VM + idxNode = newIntTypeNode(nkIntLit, idx, c.graph.getSysType(TLineInfo(), tyInt)) + + result = copyNode(n) + for x in n: result.add x + result.add n # info node + result.add idxNode + proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode proc semOf(c: PContext, n: PNode): PNode = @@ -270,7 +331,11 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode, of mOf: result = semOf(c, n) of mHigh, mLow: result = semLowHigh(c, n, n[0].sym.magic) of mShallowCopy: result = semShallowCopy(c, n, flags) - of mNBindSym: result = semBindSym(c, n) + of mNBindSym: + if dynamicBindSym notin c.features: + result = semBindSym(c, n) + else: + result = semDynamicBindSym(c, n) of mProcCall: result = n result.typ = n[1].typ diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 24896e9444..972c8c709b 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -11,6 +11,7 @@ # included from sem.nim const + errStringOrIdentNodeExpected = "string or ident node expected" errStringLiteralExpected = "string literal expected" errIntLiteralExpected = "integer literal expected" errWrongNumberOfVariables = "wrong number of variables" diff --git a/compiler/vm.nim b/compiler/vm.nim index f8b1cee731..a6ec4788b3 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -1222,9 +1222,25 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = node.typ.callConv == ccClosure and node.sons[0].kind == nkNilLit and node.sons[1].kind == nkNilLit)) of opcNBindSym: + # cannot use this simple check + # if dynamicBindSym notin c.config.features: + + # bindSym with static input decodeBx(rkNode) regs[ra].node = copyTree(c.constants.sons[rbx]) regs[ra].node.flags.incl nfIsRef + of opcNDynBindSym: + # experimental bindSym + let + rb = instr.regB + rc = instr.regC + idx = int(regs[rb+rc-1].intVal) + callback = c.callbacks[idx].value + args = VmArgs(ra: ra, rb: rb, rc: rc, slots: cast[pointer](regs), + currentException: c.currentExceptionB, + currentLineInfo: c.debug[pc]) + callback(args) + regs[ra].node.flags.incl nfIsRef of opcNChild: decodeBC(rkNode) let idx = regs[rc].intVal.int @@ -1773,7 +1789,7 @@ proc getGlobalValue*(c: PCtx; s: PSym): PNode = include vmops -proc setupGlobalCtx(module: PSym; graph: ModuleGraph) = +proc setupGlobalCtx*(module: PSym; graph: ModuleGraph) = if graph.vm.isNil: graph.vm = newCtx(module, graph.cache, graph) registerAdditionalOps(PCtx graph.vm) diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim index f7466b3929..866b79568f 100644 --- a/compiler/vmdef.nim +++ b/compiler/vmdef.nim @@ -136,7 +136,7 @@ type opcLdGlobalAddr, # dest = addr(globals[Bx]) opcLdImmInt, # dest = immediate value - opcNBindSym, + opcNBindSym, opcNDynBindSym, opcSetType, # dest.typ = types[Bx] opcTypeTrait, opcMarshalLoad, opcMarshalStore, @@ -229,7 +229,8 @@ proc refresh*(c: PCtx, module: PSym) = c.prc = PProc(blocks: @[]) c.loopIterations = MaxLoopIterations -proc registerCallback*(c: PCtx; name: string; callback: VmCallback) = +proc registerCallback*(c: PCtx; name: string; callback: VmCallback): int {.discardable.} = + result = c.callbacks.len c.callbacks.add((name, callback)) const diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 31e04a6c07..3b5ea4beb1 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -817,6 +817,43 @@ proc genVoidABC(c: PCtx, n: PNode, dest: TDest, opcode: TOpcode) = c.freeTemp(tmp2) c.freeTemp(tmp3) +proc genBindSym(c: PCtx; n: PNode; dest: var TDest) = + # nah, cannot use c.config.features because sempass context + # can have local experimental switch + # if dynamicBindSym notin c.config.features: + if n.len == 2: # hmm, reliable? + # bindSym with static input + if n[1].kind in {nkClosedSymChoice, nkOpenSymChoice, nkSym}: + let idx = c.genLiteral(n[1]) + if dest < 0: dest = c.getTemp(n.typ) + c.gABx(n, opcNBindSym, dest, idx) + else: + localError(c.config, n.info, "invalid bindSym usage") + else: + # experimental bindSym + if dest < 0: dest = c.getTemp(n.typ) + let x = c.getTempRange(n.len, slotTempUnknown) + + # callee symbol + var tmp0 = TDest(x) + c.genLit(n.sons[0], tmp0) + + # original parameters + for i in 1.. Date: Thu, 2 Aug 2018 04:33:46 -0700 Subject: [PATCH 10/11] fixes #8509 disable 4GB allocating test on windows that crashed appveyor (#8510) --- tests/fragmentation/tfragment_alloc.nim | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/fragmentation/tfragment_alloc.nim b/tests/fragmentation/tfragment_alloc.nim index 5a44b7434d..80341d2dcb 100644 --- a/tests/fragmentation/tfragment_alloc.nim +++ b/tests/fragmentation/tfragment_alloc.nim @@ -16,9 +16,12 @@ proc main = dealloc p # c_fprintf(stdout, "iteration: %ld size: %ld\n", i, size) when defined(cpu64): - # bug #7120 - var x = alloc(((1 shl 29) - 4) * 8) - dealloc x + # see https://github.com/nim-lang/Nim/issues/8509 + # this often made appveyor (on windows) fail with out of memory + when defined(posix): + # bug #7120 + var x = alloc(((1 shl 29) - 4) * 8) + dealloc x main() From e403ef25aceed929a3118e0dc2104c29e824dfcd Mon Sep 17 00:00:00 2001 From: Charlie Barto Date: Fri, 3 Aug 2018 19:18:27 -0400 Subject: [PATCH 11/11] fix shell quoting error for static libraries (#8532) --- compiler/extccomp.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index a90442369e..16b0d614da 100644 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -659,7 +659,7 @@ proc getLinkCmd(conf: ConfigRef; projectfile, objfiles: string): string = libname = getCurrentDir() / libname else: libname = (libNameTmpl(conf) % splitFile(conf.projectName).name) - result = CC[conf.cCompiler].buildLib % ["libfile", libname, + result = CC[conf.cCompiler].buildLib % ["libfile", quoteShell(libname), "objfiles", objfiles] else: var linkerExe = getConfigVar(conf, conf.cCompiler, ".linkerexe")