Skip to content

Commit 9ace437

Browse files
committed
Nimpretty
1 parent 97861e3 commit 9ace437

File tree

6 files changed

+252
-165
lines changed

6 files changed

+252
-165
lines changed

nimler.nim

Lines changed: 76 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,30 +19,44 @@ template dirtyCpu*() {.pragma.}
1919

2020
type 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+
4660
macro 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

Comments
 (0)