-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
summary
-
A1
emit: "foo `someNimVar` bar".}can sometimes give wrong runtime results (which is worse than CT errors); the newer syntaxemit: [..]doesn't have that issue though; EDIT: this happens in particular in templates and is related to "undeclared identifier" error when using fmt from strformat on devel inside a template #10977 and asm code in templates fail #2362 -
A2
emitdoesn't work withvarvariables, but works withresultpseudo-var-variable -
A3 block scope
emitshould not be relocated -
A4
{.emit:"/*HERE*/ do not move me".}should be introduced (trivial change); would be useful for module-scope emit's even ifblock scopeemit bug is fixed -
A5
tsizeof.c_sizeofshows a seemingly correct usage ofemitthat is in fact incorrect and would be easily fixed with/*HERE*/ -
A6 nim cpp differs from nim c (related to A2)
Example 1
import unittest
template testEmit0(cond: string, body) =
{.emit: ["""#if """, cond, "\n"].} # OK: this works
body
{.emit: "#endif\n".}
template testEmit1(cond: string, body) =
# {.emit: ["""#if """, cond, "\n"].} # OK: this works
{.emit: "#if `cond`\n".} # BUG: `cond` generated as `cond` litteral!!
body
{.emit: "#endif\n".}
proc testEmit2(count: var int) =
{.emit: """`count` = 3;""".}
proc testEmit3(count: int): int =
var x = 0
{.emit: """`x` = `count`;""".}
return x
proc testEmit4(count: int): int =
{.emit: """`result` = `count`;""".}
proc main() =
var count = 0
# BUG1 D20200409T213938:here quote replacement doesn't work in templates
testEmit1("true"):
count = 7
check count == 7
# ok: quote replacement works inside procs
doAssert testEmit3(11) == 11
# ok: emit with `[]` works in side templates
testEmit0("true"):
count = 9
doAssert count == 9
# BUG2 D20200409T214500:here (or at least caveat that should be documented): emit replacement doesn't work with `var` variables
testEmit2(count)
check count == 3
# ok: it works with `result` magic variable even though it's kind of like a var variable
doAssert testEmit4(4) == 4
main()
Current Output
/Users/timothee/git_clone/nim/timn/tests/nim/all/t10528.nim(35, 14): Check failed: count == 7
count was 0
/Users/timothee/git_clone/nim/timn/tests/nim/all/t10528.nim(47, 14): Check failed: count == 3
count was 9
Expected Output
works
Example 2
# D20200409T215527:here
template cstaticIf(cond: string, body) =
echo "#if " & cond
{.emit: ["""#if """, cond, "\n"].} # {.emit: "#if `cond`\n".} would hit D20200409T213938
body
{.emit: "#endif\n".}
echo "#endif " & cond & "\n"
template fun() =
cstaticIf "__cplusplus >= 201703L":
echo "enabled"
cstaticIf "__cplusplus < 201703L":
echo "enabled"
echo "moduleLevel"
fun()
template blockLevel()=
block:
echo "blockLevel"
fun()
blockLevel()
proc procLevel()=
echo "procLevel"
fun()
procLevel()this prints:
moduleLevel
#if __cplusplus >= 201703L
enabled
#endif __cplusplus >= 201703L
#if __cplusplus < 201703L
enabled
#endif __cplusplus < 201703L
blockLevel
#if __cplusplus >= 201703L
enabled
#endif __cplusplus >= 201703L
#if __cplusplus < 201703L
enabled
#endif __cplusplus < 201703L
procLevel
#if __cplusplus >= 201703L
#endif __cplusplus >= 201703L
#if __cplusplus < 201703L
enabled
#endif __cplusplus < 201703L
-
the
procLeveloutput is correct: the code is emitted where the emit is declared -
BUG: the
blockLeveloutput is incorrect: the code should not be moved around to a separate section because it's inside a block
it results in buggy behavior as illustrated here -
the
moduleLeveloutput is technically correct: the code is moved around to a separate section. However we need a new type section modifier:
{.emit: "/*HERE*/ don't move this around".}
in addition to the existing /*TYPESECTION*/, /*VARSECTION*/, /*INCLUDESECTION*/.
It should be a trivial change in determineSection
Example 3
this is related to Example 2.
Here's the implementation from tsizeof.c_sizeof:
# D20200409T220623:here
import macros
macro c_sizeof(a: typed): int32 =
## Bullet proof implementation that works using the sizeof operator
## in the c backend. Assuming of course this implementation is
## correct.
result = quote do:
var res: int32
{.emit: [res, " = sizeof(", `a`, ");"] .}
res
block:
let a = c_sizeof(cint)
echo anim c -r -f --stacktrace:off $timn_D/tests/nim/all/t10527b.nim
works, but shouldn't, because warnings are squashed => we really need #11591 which would enable showing those warnings via --warning:BackendWarning:on
nim cpp -r -f --stacktrace:off $timn_D/tests/nim/all/t10527b.nim
this one fails (as it should) and illustrates the bug, which is that emit gets moved around to another section even though it's inside a block:
here's the generated code:
...
resX60gensym16846041___RP9bMW8EVqo5H9c0lD6uqxDQ = sizeof(int);
...
N_LIB_PRIVATE NI32 resX60gensym16846041___RP9bMW8EVqo5H9c0lD6uqxDQ;
and here's the cgen error:
/Users/timothee/git_clone/nim/timn/build/nimcache/@mt10527b.nim.cpp:36:1: error: C++ requires a type specifier for all declarations
resX60gensym16846041___RP9bMW8EVqo5H9c0lD6uqxDQ = sizeof(int);
^
/Users/timothee/git_clone/nim/timn/build/nimcache/@mt10527b.nim.cpp:47:20: error: redefinition of 'resX60gensym16846041___RP9bMW8EVqo5H9c0lD6uqxDQ'
N_LIB_PRIVATE NI32 resX60gensym16846041___RP9bMW8EVqo5H9c0lD6uqxDQ;
example 4: nim cpp differs from nim c
nim c returns a: 262398120 (incorrect)
nim cpp returns a: 10 (correct)
when true: # D20200414T195401:here
{.emit: "#include <stdio.h>".}
proc testEmit1b(a: var cint) =
{.emit: """printf("a: %d\n", `a`);""".}
var a = 10.cint
testEmit1b(a)Additional Information
- devel 3036ec9
- maybe A1 is related to asm code in templates fail #2362