mirror of
https://github.com/nim-lang/Nim.git
synced 2026-07-22 08:51:21 +00:00
reworked emit pragma; fixes #4730
This commit is contained in:
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
22
tests/cpp/temitlist.nim
Normal 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()
|
||||
@@ -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
|
||||
--------
|
||||
|
||||
Reference in New Issue
Block a user