summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ccgstmts.nim6
-rw-r--r--compiler/pragmas.nim18
-rw-r--r--doc/manual/pragmas.txt12
-rw-r--r--tests/cpp/temitlist.nim22
-rw-r--r--web/news/e029_version_0_16_0.rst22
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
 --------