import macros
macro function(x) =
var params: seq[NimNode]
expectKind x, nnkCommand
expectKind x[0], nnkPar
expectKind x[0][0], nnkExprColonExpr
params.add newIdentDefs(x[0][0][0], x[0][0][1])
expectKind x[1], nnkCommand
expectKind x[1][0], nnkIdent
let name = x[1][0]
expectKind x[1][1], nnkCommand
expectKind x[1][1][0], nnkPar
for it in x[1][1][0]:
case it.kind
of nnkExprColonExpr:
params.add newIdentDefs(it[0], it[1])
of nnkExprEqExpr:
params.add newIdentDefs(it[0], newEmptyNode(), it[1])
else:
raiseAssert ":-("
let x = x[1][1][1]
expectKind x, nnkCall
var pragmas, body = newEmptyNode()
case x[0].kind
of nnkPragmaExpr:
expectKind x[0][0], nnkIdent
expectKind x[0][1], nnkPragma
expectKind x[1], nnkStmtList
params.insert x[0][0], 0 # return type
pragmas = x[0][1]
body = x[1]
of nnkIdent:
params.insert x[0], 0 # return type
body = x[1]
of nnkStmtList:
params.insert newEmptyNode(), 0 # return type
body = x[0]
else:
raiseAssert ":-("
newProc(name, params, body, nnkProcDef, pragmas)
var x = 0
function (a: int) foo (b: int, c = 42) int {.exportc, cdecl, dynlib.} do:
inc x
a + b + c
assert 2.foo(3) == 47
assert x == 1
Run
Most of the code is just checking the arguments anyway.