reworked emit pragma; fixes #4730

This commit is contained in:
Andreas Rumpf
2016-12-17 14:20:57 +01:00
parent 14b9eaee06
commit b013430929
5 changed files with 70 additions and 10 deletions

View File

@@ -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):

View File

@@ -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)

View File

@@ -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

22
tests/cpp/temitlist.nim Normal file
View File

@@ -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()

View File

@@ -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
--------