diff options
-rw-r--r-- | compiler/ccgstmts.nim | 6 | ||||
-rw-r--r-- | compiler/pragmas.nim | 18 | ||||
-rw-r--r-- | doc/manual/pragmas.txt | 12 | ||||
-rw-r--r-- | tests/cpp/temitlist.nim | 22 | ||||
-rw-r--r-- | web/news/e029_version_0_16_0.rst | 22 |
5 files changed, 70 insertions, 10 deletions
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 10b5641c5..1838562d4 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -973,7 +973,11 @@ proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false): Rope = r = mangleName(sym) sym.loc.r = r # but be consequent! res.add($r) - else: internalError(t.sons[i].info, "genAsmOrEmitStmt()") + else: + var a: TLoc + initLocExpr(p, t.sons[i], a) + res.add($a.rdLoc) + #internalError(t.sons[i].info, "genAsmOrEmitStmt()") if isAsmStmt and hasGnuAsm in CC[cCompiler].props: for x in splitLines(res): diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index ffb2aa812..f93d33353 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -460,8 +460,22 @@ proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode = result = newNode(nkAsmStmt, n.info) proc pragmaEmit(c: PContext, n: PNode) = - discard getStrLitNode(c, n) - n.sons[1] = semAsmOrEmit(c, n, '`') + if n.kind != nkExprColonExpr: + localError(n.info, errStringLiteralExpected) + else: + let n1 = n[1] + if n1.kind == nkBracket: + var b = newNodeI(nkBracket, n1.info, n1.len) + for i in 0..<n1.len: + b.sons[i] = c.semExpr(c, n1[i]) + n.sons[1] = b + else: + n.sons[1] = c.semConstExpr(c, n1) + case n.sons[1].kind + of nkStrLit, nkRStrLit, nkTripleStrLit: + n.sons[1] = semAsmOrEmit(c, n, '`') + else: + localError(n.info, errStringLiteralExpected) proc noVal(n: PNode) = if n.kind == nkExprColonExpr: invalidPragma(n) diff --git a/doc/manual/pragmas.txt b/doc/manual/pragmas.txt index a19f41a34..2a276c2e7 100644 --- a/doc/manual/pragmas.txt +++ b/doc/manual/pragmas.txt @@ -26,9 +26,6 @@ It can also be used as a statement, in that case it takes a list of *renamings*. Stream = ref object {.deprecated: [TFile: File, PStream: Stream].} -The ``nimfix`` tool can be used to, without effort, automatically update your -code and refactor it by performing these renamings. - noSideEffect pragma ------------------- @@ -678,14 +675,15 @@ Example: {.push stackTrace:off.} proc embedsC() = var nimVar = 89 - # use backticks to access Nim symbols within an emit section: - {.emit: """fprintf(stdout, "%d\n", cvariable + (int)`nimVar`);""".} + # access Nim symbols within an emit section outside of string literals: + {.emit: ["""fprintf(stdout, "%d\n", cvariable + (int)""", nimVar, ");"].} {.pop.} embedsC() -As can be seen from the example, to Nim symbols can be referred via backticks. -Use two backticks to produce a single verbatim backtick. +For backwards compatibility, if the argument to the ``emit`` statement +is a single string literal, Nim symbols can be referred to via backticks. +This usage is however deprecated. For a toplevel emit statement the section where in the generated C/C++ file the code should be emitted can be influenced via the diff --git a/tests/cpp/temitlist.nim b/tests/cpp/temitlist.nim new file mode 100644 index 000000000..cef0fc52d --- /dev/null +++ b/tests/cpp/temitlist.nim @@ -0,0 +1,22 @@ +discard """ + cmd: "nim cpp $file" + output: '''6.0''' +""" + +# bug #4730 + +type Vector* {.importcpp: "std::vector", header: "<vector>".}[T] = object + +template `[]=`*[T](v: var Vector[T], key: int, val: T) = + {.emit: [v, "[", key, "] = ", val, ";"].} + +proc setLen*[T](v: var Vector[T]; size: int) {.importcpp: "resize", nodecl.} +proc `[]`*[T](v: var Vector[T], key: int): T {.importcpp: "(#[#])", nodecl.} + +proc main = + var v: Vector[float] + v.setLen 1 + v[0] = 6.0 + echo v[0] + +main() diff --git a/web/news/e029_version_0_16_0.rst b/web/news/e029_version_0_16_0.rst index 2a0c81b46..905504791 100644 --- a/web/news/e029_version_0_16_0.rst +++ b/web/news/e029_version_0_16_0.rst @@ -55,6 +55,28 @@ Compiler Additions Language Additions ------------------ +- The ``emit`` pragma now takes a list of Nim expressions instead + of a single string literal. This list can easily contain non-strings + like template parameters. This means ``emit`` works out of the + box with templates and no new quoting rules needed to be introduced. + The old way with backtick quoting is still supported but will be + deprecated. + +.. code-block:: nim + type Vector* {.importcpp: "std::vector", header: "<vector>".}[T] = object + + template `[]=`*[T](v: var Vector[T], key: int, val: T) = + {.emit: [v, "[", key, "] = ", val, ";"].} + + proc setLen*[T](v: var Vector[T]; size: int) {.importcpp: "resize", nodecl.} + proc `[]`*[T](v: var Vector[T], key: int): T {.importcpp: "(#[#])", nodecl.} + + proc main = + var v: Vector[float] + v.setLen 1 + v[0] = 6.0 + echo v[0] + Bugfixes -------- |