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.

Reply via email to