Skip to content

Instantly share code, notes, and snippets.

@cipharius
Created June 7, 2018 21:46
Show Gist options
  • Save cipharius/79facf7c8d04219543b296edbf2a819c to your computer and use it in GitHub Desktop.
Save cipharius/79facf7c8d04219543b296edbf2a819c to your computer and use it in GitHub Desktop.
Macro for unrolling for loop with generic range iterators
import macros
proc replaceIdent(node, ident: NimNode, replacement: NimNode) =
for i, child in node:
if child == ident:
node[i] = replacement.copy()
if child.len > 0:
child.replaceIdent(ident, replacement)
macro unrollLoop(statements: untyped): typed =
result = newNimNode(nnkStmtList)
let loop = statements[0]
loop.expectKind(nnkForStmt)
loop.expectLen(3)
let
loopIndex = loop[0]
loopRange = loop[1]
loopBody = loop.body
loopRange.expectKind(nnkInfix)
let
a = int(loopRange[1].intVal)
b = int(loopRange[2].intVal)
echo loopRange[0].kind
var unrollRange: Slice[int]
if loopRange[0].eqIdent("..<"):
unrollRange = a..<b
elif loopRange[0].eqIdent(".."):
unrollRange = a..b
else:
error("Unsupported iterator")
for i in unrollRange:
var newStmt = loopBody.copy()
newStmt.replaceIdent(loopIndex, i.newLit())
result.add(newStmt)
var someSequence = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
var accumulate = 0
unrollLoop:
for i in 0..<10:
echo someSequence[i]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment