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.