Skip to content

Instantly share code, notes, and snippets.

@mjendrusch
Last active October 11, 2016 21:38
Show Gist options
  • Save mjendrusch/b09478d37ea93dee181e0b1838bfe26b to your computer and use it in GitHub Desktop.
Save mjendrusch/b09478d37ea93dee181e0b1838bfe26b to your computer and use it in GitHub Desktop.
Idea for the exportc everywhere macro
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