reworked emit pragma; fixes #4730
This commit is contained in:
parent
14b9eaee06
commit
b013430929
5 changed files with 70 additions and 10 deletions
|
|
@ -973,7 +973,11 @@ proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false): Rope =
|
||||||
r = mangleName(sym)
|
r = mangleName(sym)
|
||||||
sym.loc.r = r # but be consequent!
|
sym.loc.r = r # but be consequent!
|
||||||
res.add($r)
|
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:
|
if isAsmStmt and hasGnuAsm in CC[cCompiler].props:
|
||||||
for x in splitLines(res):
|
for x in splitLines(res):
|
||||||
|
|
|
||||||
|
|
@ -460,8 +460,22 @@ proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode =
|
||||||
result = newNode(nkAsmStmt, n.info)
|
result = newNode(nkAsmStmt, n.info)
|
||||||
|
|
||||||
proc pragmaEmit(c: PContext, n: PNode) =
|
proc pragmaEmit(c: PContext, n: PNode) =
|
||||||
discard getStrLitNode(c, n)
|
if n.kind != nkExprColonExpr:
|
||||||
n.sons[1] = semAsmOrEmit(c, n, '`')
|
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) =
|
proc noVal(n: PNode) =
|
||||||
if n.kind == nkExprColonExpr: invalidPragma(n)
|
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
|
Stream = ref object
|
||||||
{.deprecated: [TFile: File, PStream: Stream].}
|
{.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
|
noSideEffect pragma
|
||||||
-------------------
|
-------------------
|
||||||
|
|
@ -678,14 +675,15 @@ Example:
|
||||||
{.push stackTrace:off.}
|
{.push stackTrace:off.}
|
||||||
proc embedsC() =
|
proc embedsC() =
|
||||||
var nimVar = 89
|
var nimVar = 89
|
||||||
# use backticks to access Nim symbols within an emit section:
|
# access Nim symbols within an emit section outside of string literals:
|
||||||
{.emit: """fprintf(stdout, "%d\n", cvariable + (int)`nimVar`);""".}
|
{.emit: ["""fprintf(stdout, "%d\n", cvariable + (int)""", nimVar, ");"].}
|
||||||
{.pop.}
|
{.pop.}
|
||||||
|
|
||||||
embedsC()
|
embedsC()
|
||||||
|
|
||||||
As can be seen from the example, to Nim symbols can be referred via backticks.
|
For backwards compatibility, if the argument to the ``emit`` statement
|
||||||
Use two backticks to produce a single verbatim backtick.
|
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
|
For a toplevel emit statement the section where in the generated C/C++ file
|
||||||
the code should be emitted can be influenced via the
|
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
|
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
|
Bugfixes
|
||||||
--------
|
--------
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue