Skip to content

Commit

Permalink
cps: experimental support for for-loops
Browse files Browse the repository at this point in the history
For-loops are inlined using block statements, which messes with their
control flow due to #76.

Breaks "for loop with continue, break" test. On the flip side,
splitting now functions on them.

Also breaks a test in tzevv due to defer being rewritten into
try-finally, which doesn't work.

Co-authored-by: Andy Davidoff <github@andy.disruptek.com>
  • Loading branch information
alaviss and disruptek committed May 3, 2021
1 parent 73e104a commit c06b43c
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 2 deletions.
28 changes: 26 additions & 2 deletions cps.nim
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,12 @@ proc normalizingRewrites(n: NimNode): NimNode =
if n.len == 2:
n.add newEmptyNode()
elif n[1].isEmpty: # add explicit type symbol
n[1] = getTypeInst n[2]
if not n[2].isEmpty:
n[1] = getTypeInst n[2]
else:
# get the type from the symbol as the last resort.
# walkaround for #48.
n[1] = getTypeInst n[0]
result = n

proc rewriteVarLet(n: NimNode): NimNode =
Expand Down Expand Up @@ -637,13 +642,24 @@ proc normalizingRewrites(n: NimNode): NimNode =
result = n[0]
else: discard

proc rewriteFastAsgn(n: NimNode): NimNode =
## Rewrite nnkFastAsgn into nnkAsgn because sem don't like them
case n.kind
of nnkFastAsgn:
result = newNimNode(nnkAsgn, n)
for child in n.items:
result.add child
else: discard

case n.kind
of nnkIdentDefs:
rewriteIdentDefs n
of nnkLetSection, nnkVarSection:
rewriteVarLet n
of nnkHiddenAddr, nnkHiddenDeref:
rewriteHiddenAddrDeref n
of nnkFastAsgn:
rewriteFastAsgn n
else:
nil

Expand Down Expand Up @@ -854,13 +870,21 @@ proc cpsXfrm(T: NimNode, n: NimNode): NimNode =
result = copy n
result = workaroundRewrites(result)

macro cps*(T: typed, n: typed): untyped =
macro cps2(T: typed, n: typed): untyped =
# I hate doing stuff inside macros, call the proc to do the work
when defined(nimdoc):
result = n
else:
result = cpsXfrm(T, n)

macro cps*(T: typed, n: typed): untyped =
case n.kind
of nnkProcDef:
result = getImplTransformed n.name
result.addPragma newColonExpr(bindSym"cps2", T)
else:
result = cpsXfrm(T, n)

macro cpsMagic*(n: untyped): untyped =
## upgrade cps primitives to generate errors out of context
## and take continuations as input inside {.cps.} blocks
Expand Down
12 changes: 12 additions & 0 deletions tests/taste.nim
Original file line number Diff line number Diff line change
Expand Up @@ -656,3 +656,15 @@ suite "tasteful tests":
check i == 4

trampoline foo()

block:
## for-loop with splitting
r = 0
proc foo() {.cps: Cont.} =
inc r
for i in 0 ..< 3:
noop()
inc r

trampoline foo()
check r == 4

0 comments on commit c06b43c

Please sign in to comment.