The following code works for let variables and literals but gets compile errors for expressions. I want to be able to trap the expressions to treat them separately from let variables (as I do literals).
#!/usr/bin/env -S nim r
## :File: test2.nim
##
import sugar
import strutils
template test2(src:string, lab: string = "Inner tmpl") =
when src is static:
# This traps literals
let s = src
let pi1 = cast[int](addr(s))
else:
# This works for let values but fails for expressions
let pi1 = cast[int](addr(src))
let pa1 = pi1.toHex
debugEcho lab, ": ", src, " <= ", $pa1
let s1 = "Test string"
# The following works because it is a let variable
test2 s1, "Original s1"
let s2 = s1
# The following also works because it is also a let variable
test2 s2, "Copy s1"
# The following works because it is trapped by the when branch as a literal
test2 "Literal abc", "Literal template"
# Uncomment the following and you get a compiler error because you cannot get
# the addr of an expression.
# test2 "--- $1" % s1, "Expression"
Thanks to Orc/Arc cursors and COW string literals in this example you can likely use the following:
import sugar
import strutils
template test2(src:string, lab: string = "Inner tmpl") =
let s {.cursor.} = src
# This works for let values but fails for expressions
let pi1 = cast[int](addr(s))
let pa1 = pi1.toHex
debugEcho lab, ": ", src, " <= ", $pa1
var s1 = "Test string"
# The following works because it is a let variable
test2 s1, "Original s1"
prepareMutation(s1) # This rewrites the literal so we can see cursors in action.
let s2 = s1
# The following also works because it is also a let variable
test2 s2, "Copy s1"
# The following works because it is trapped by the when branch as a literal
test2 "Literal abc", "Literal template"
test2 "--- $1" % s1, "Expression"
@ElegantBeef
Alas, if I understand what you are doing there correctly, it is exactly what I don't want to do.
Aside from what I can tell, the cursor pragma is deliberately undocumented so is likely to change or be deprecated in future versions; but my intention in what I was doing was to identify in what situations I can get away with passing pointers to values (so save the overheads on copying large strings but just copying and using the pointers to the strings).
Obviously, with literals and expressions the string does not exist on the stack so copying is necessary (which is why I was trying to identify when those situations arose and treat those as exceptional cases).
It is certainly documented https://nim-lang.org/docs/destructors.html#the-cursor-pragma
There is no copying in the above code. As can be seen by the pointers.
Obviously, with literals and expressions the string does not exist on the stack so copying is necessary
Strings never exist on the stack they're always a (ptr StringData, len) even in the case they point to a COW literal. So I'm uncertain what you think you're avoiding.