Skip to content

Instantly share code, notes, and snippets.

@Varriount
Last active August 29, 2015 13:57
Show Gist options
  • Save Varriount/9925367 to your computer and use it in GitHub Desktop.
Save Varriount/9925367 to your computer and use it in GitHub Desktop.
A marvelous mutating macro which multiplies morale
import macros
import strutils
macro duoFunc(baseProc: stmt): stmt {.immediate.} =
# Assumptions:
#
# echo(treeRepr(baseProc))
result = newStmtList()
result.add(baseProc)
## Search the base procedure's params for the 'result' argument.
## Also, construct a call to the procedure.
var
resultParam: PNimrodNode
resultIndice: int
resultCall = newCall(baseProc.name.baseName)
for i in 1 .. <baseProc.params.len:
template node: expr = baseProc.params[i]
resultCall.add(node[0])
if resultParam.isNil() and "result".eqIdent(normalize($ node[0])):
resultParam = node
resultIndice = i
if node[1].kind != nnkVarTy:
macros.error("\n " & baseProc.lineInfo() & " Error: 'result' parameter not a 'var' type.")
if isNil(resultParam):
macros.error("\n " & baseProc.lineInfo() & " Error: 'result' parameter could not be found.")
# Generate a new procedure, with the type of result argument moved to the
# return value.
var otherProc = baseProc.copy()
otherProc.body= newStmtList()
otherProc.params.del(resultIndice)
otherProc.params[0] = resultParam[1][0]
# If needed, add an initial assignment to the result variable which represents
# the default value.
if resultParam[2].kind != nnkEmpty:
otherProc.body.add(
newAssignment(
newIdentNode("result"),
resultParam[2].copy()
)
)
# Generate the body of the new procedure, which is a call to the base
# Procedure.
otherProc.body.add(resultCall)
result.add(otherProc)
# echo(repr(result))
# echo(treeRepr(result))
proc testFunc*(s: string, result: var string) {.duoFunc.} =
result = ""
result.add(s)
result.add(s)
when isMainModule:
var x = testFunc("Hello")
var y: string
testFunc("Hello", y)
echo(x)
echo(y)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment