Is it possible to convert c code:
#define TO__STR(n) #n
#define TO_STR(n) H2O_TO__STR(n)
#define STRLIT(s) (s), sizeof(s) - 1
into Nim code? If yes, then how to do it?
Arguments in that macros are
const char *
The stringify C macro is not supported currently by c2nim. I tried six months ago something with my own Nim stringify macro like:
macro stringify*(n: expr): string =
result = newNimNode(nnkStmtList, n)
result.add(toStrLit(n))
with that macro something like
template TO_STR(n): string = stringify(n)
may work. Can not really remember details, I was working on the strange gobject macros to get GTK3 application10 to work, but my macro skills are bad. You have to import macros, and with that macro something like this works:
echo(TO_STR(1 + 2)) # gives 1 + 2
For the other two defines, c2nim may give you
template TO_STR*(n: expr): expr =
H2O_TO__STR(n)
template STRLIT*(s: expr): expr =
(s)
sizeof((s)) - 1
You have to see how useful that is. Two underscores may be a problem for Nim, you may have to replace that.
For the second line something like
const TO_STR = H2O_TO__STR
may be a solution, but care for the two underscores. That is an proc alias, you have to check if that is what is really desired.Thanks for your reply.
#define STRLIT(s) (s), sizeof(s) - 1
That macro is used to make parameters to functions.
For example:
vec_init(STRLIT("localhost"))
will produce
vec_init("localhost",9)
How to make it in Nim? Please.
Can not help you, sorry. Basically something like
template STRLIT(s: static[string]): expr =
s, sizeof(s) - 1
But that does snot compile. Maybe a macro is required, so we have to wait for an answer of the experts.
Or you may do a plain text substitution of course, maybe replace "STRLIT(s)" with "s, sizeof(s) - 1"
Wrong:
prog.nim(2, 4) Error: invalid indentation
In Nim c code sizeof(s) is len s for strings
AFAIK you can't create 2 parameters from 1 with a template anyway.
Something like this will work but is probably not of any help:
template STRLIT(s: static[string]): expr = (s, s.len - 1)
proc test(s: string, n: int) =
echo s & " (" & $n & ")"
proc test(x: tuple[s: string, n: int]) = test(x.s, x.n)
const a = "test"
test(STRLIT(a))
What you can do is something like what we do for the wxcnim module to "fake" the possibility to have a proc which accepts special parameters, but for this you need to wrap the whole call with a helper macro:
import macros
#proc point*(x, y: int) = discard
#proc rect*(a, b, c, d: int) = discard
template unpackingArgs(nimname,extname) =
macro nimname*(n: varargs[untyped]): expr =
var call = newCall(!astToStr(extname))
for x in n.children:
var unpack = false
if x.kind in nnkCallKinds:
case $x[0]
of "point":
expectLen(x, 3)
unpack = true
of "rect":
expectLen(x, 5)
unpack = true
else: discard
if unpack:
for i in 1..<x.len:
call.add(x[i])
else:
call.add(x)
result = newStmtList(call)
proc takesSeven(left,top,width,height,col,x,y: int) =
echo $left & " " & $top & " / " & $width & " " & $height
echo col
echo $x & " " & $y
# create a version which supports "define style parameters"
unpackingArgs(takesStuff, takesSeven)
echo "Takes Seven:"
takesSeven(1,2,3,4,5,6,7)
echo "Takes Stuff 1 (OK):"
takesStuff(rect(1,2,3,4),5,point(6,7))
echo "Takes Stuff 2 (MEH):"
takesStuff(rect(1,2,3,4),point(5,6),7)