@@ -19,30 +19,44 @@ template dirtyCpu*() {.pragma.}
1919
2020type PragmaSpec = tuple [k: NimNode , v: NimNode ]
2121
22- func pragmaTable (fn: NimNode ): seq [PragmaSpec ] =
22+ func pragmaTable (fn: NimNode ): seq [PragmaSpec ] {. compileTime .} =
2323 expectKind (fn, {nnkProcDef, nnkFuncDef})
2424 for p in fn.pragma:
2525 case p.kind:
2626 of nnkIdent, nnkSym:
27- let pp: PragmaSpec = (p, newEmptyNode ())
28- result .add (pp)
27+ result .add ((p, newEmptyNode ()))
2928 of nnkExprColonExpr:
3029 result .add ((p[0 ], p[1 ]))
3130 else :
3231 error " wrong kind: " & $ p.kind
3332
34- func getPragmaValue (p: seq [PragmaSpec ], t: string , d: NimNode = newEmptyNode ()): NimNode =
33+ func getPragmaValue (p: seq [PragmaSpec ],
34+ t: string , d: NimNode = newEmptyNode ()): NimNode {.compileTime .} =
3535 for (k, v) in p:
3636 if eqIdent (k, t):
3737 return v
3838 return d
3939
40- func hasPragma (p: seq [PragmaSpec ], t: string ): bool =
40+ func hasPragma (p: seq [PragmaSpec ], t: string ): bool {. compileTime .} =
4141 for (k, _) in p:
42- if eqIdent (k, t):
43- return true
42+ if eqIdent (k, t):
43+ return true
4444 return false
4545
46+ func copyPragmaWithout (p: NimNode , x: string ): NimNode {.compileTime .} =
47+ expectKind (p, {nnkEmpty, nnkPragma})
48+ result = newTree (nnkPragma)
49+ for e in p:
50+ expectKind (e, {nnkIdent, nnkExprColonExpr})
51+ case e.kind
52+ of nnkExprColonExpr:
53+ if not eqIdent (e[0 ], x):
54+ result .add (e)
55+ of nnkIdent:
56+ if not eqIdent (e, x):
57+ result .add (e)
58+ else : error " wrong kind"
59+
4660macro nif * (fn: untyped ): untyped =
4761 expectKind (fn, {nnkProcDef, nnkFuncDef})
4862
@@ -102,3 +116,58 @@ template exportNifs*(
102116
103117 static : genWrapper (moduleName, nifs)
104118
119+ proc genNifWrapper (nifName: NimNode , fn: NimNode ): NimNode {.compileTime .} =
120+ expectKind (nifName, nnkStrLit)
121+ expectKind (fn, {nnkProcDef, nnkFuncDef})
122+
123+ let rname = fn.name
124+ fn.name = ident (" z" & $ fn.name & " Internal" )
125+
126+ let rbody = newTree (nnkStmtList, fn)
127+ let rcall = newCall (fn.name, ident (" env" ))
128+
129+ for i in 2 ..< len (fn.params):
130+ let p = fn.params[i]
131+ let arg = newTree (nnkBracketExpr, ident (" argv" ), newLit (i- 2 ))
132+ rbody.add (newTree (nnkLetSection, newTree (nnkIdentDefs,
133+ p[0 ],
134+ newNimNode (nnkEmpty),
135+ newCall (" fromTerm" , ident (" env" ), arg, p[1 ]))))
136+ rbody.add (newTree (nnkIfStmt, newTree (nnkElifBranch,
137+ newCall (" unlikely" , newCall (" isNone" , p[0 ])),
138+ newTree (nnkReturnStmt, newCall (" enif_make_badarg" , ident (" env" ))))))
139+ rcall.add (newCall (" unsafeGet" , p[0 ]))
140+
141+ rbody.add (newTree (nnkReturnStmt, newCall (" toTerm" , ident (" env" ), rcall)))
142+
143+ let rfn = newProc (rname, [], rbody, fn.kind)
144+ rfn.params = newTree (nnkFormalParams,
145+ ident (" ErlTerm" ),
146+ newTree (nnkIdentDefs,
147+ ident (" env" ),
148+ newNimNode (nnkPtrTy).add (ident (" ErlNifEnv" )),
149+ newNimNode (nnkEmpty)),
150+ newTree (nnkIdentDefs,
151+ ident (" argc" ),
152+ ident (" cint" ),
153+ newNimNode (nnkEmpty)),
154+ newTree (nnkIdentDefs,
155+ ident (" argv" ),
156+ ident (" ErlNifArgs" ),
157+ newNimNode (nnkEmpty)))
158+
159+ rfn.pragma = copyPragmaWithout (fn.pragma, " raises" )
160+ rfn.pragma.add (ident (" nif" ))
161+ rfn.pragma.add (newTree (nnkExprColonExpr,
162+ ident (" arity" ),
163+ newLit (len (fn.params)- 2 )))
164+ rfn.pragma.add (newTree (nnkExprColonExpr, ident (" nif_name" ), nifName))
165+
166+ result = rfn
167+
168+ macro xnif * (nifName: untyped , fn: untyped ): untyped =
169+ result = genNifWrapper (nifName, fn)
170+
171+ macro xnif * (fn: untyped ): untyped =
172+ result = genNifWrapper (newLit (repr fn.name), fn)
173+
0 commit comments