Last active
October 11, 2016 21:38
-
-
Save mjendrusch/b09478d37ea93dee181e0b1838bfe26b to your computer and use it in GitHub Desktop.
Idea for the exportc everywhere macro
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import macros | |
# Takes a pragma identifier, together with a typesection | |
macro pragmaTypeSection*(prag, x : untyped): untyped = | |
result = newNimNode(nnkTypeSection) | |
for child in x[0].children: | |
var | |
name = child[0] | |
rawBody = child[2] | |
body = rawBody | |
objectPragma: NimNode | |
intermediate: NimNode | |
recList = newNimNode(nnkRecList) | |
# We first construct the object-type | |
# and bind it to a temporary, from which we then construct | |
# the real deal. | |
internal = newIdentNode(!("internal" & lineInfo(child))) | |
# Yank the object body from the `PtrTy` or `RefTy` node, if necessary | |
if rawBody.kind in { nnkPtrTy, nnkRefTy }: | |
body = rawBody[0] | |
if body[0].kind == nnkPragma: | |
objectPragma = body[0] | |
else: | |
objectPragma = newNimNode(nnkEmpty) | |
intermediate = newNimNode(nnkObjectTy).add( | |
newNimNode(nnkEmpty) | |
).add(body[1]) | |
else: | |
intermediate = newNimNode(nnkObjectTy).add(body[0]).add(body[1]) | |
# for every record in the object definition body, if it already has pragmas, | |
# add the chosen pragma, else create a `PragmaExpr` and attach the chosen | |
# pragma there. | |
for rec in body[2]: | |
for elem in 0..rec.len-3: | |
var generalizedIdent: NimNode | |
if rec[elem].kind == nnkPragmaExpr: | |
rec[elem][1].add(prag) | |
generalizedIdent = rec[elem] | |
else: | |
generalizedIdent = newNimNode(nnkPragmaExpr).add( | |
rec[elem] | |
).add(newNimNode(nnkPragma).add( | |
prag | |
)) | |
recList.add( | |
newNimNode(nnkIdentDefs).add( | |
generalizedIdent | |
).add(rec[^2]).add(rec[^1]) | |
) | |
intermediate.add(recList) | |
result.add( | |
newNimNode(nnkTypeDef).add(internal).add( | |
child[1] | |
).add( | |
intermediate | |
) | |
) | |
# If we want to have a pragma on the whole ref/ptr object | |
# (not on the fields), we have to lift that to the | |
# ref/ptr, which is what we do here: | |
if rawBody.kind in { nnkPtrTy, nnkRefTy }: | |
var generalizedName: NimNode | |
if objectPragma.kind != nnkEmpty: | |
generalizedName = newNimNode(nnkPragmaExpr).add( | |
name | |
).add(objectPragma) | |
else: | |
generalizedName = name | |
result.add( | |
newNimNode(nnkTypeDef).add( | |
generalizedName | |
).add(newNimNode(nnkEmpty)).add( | |
newNimNode(rawBody.kind).add( | |
internal | |
) | |
) | |
) | |
pragmaTypeSection exportc: | |
type | |
Foo* = ref object | |
a, b, c, d, e: int |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment