Skip to content

Commit c06b43c

Browse files
alavissdisruptek
andcommitted
cps: experimental support for for-loops
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>
1 parent 73e104a commit c06b43c

File tree

2 files changed

+38
-2
lines changed

2 files changed

+38
-2
lines changed

cps.nim

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,12 @@ proc normalizingRewrites(n: NimNode): NimNode =
603603
if n.len == 2:
604604
n.add newEmptyNode()
605605
elif n[1].isEmpty: # add explicit type symbol
606-
n[1] = getTypeInst n[2]
606+
if not n[2].isEmpty:
607+
n[1] = getTypeInst n[2]
608+
else:
609+
# get the type from the symbol as the last resort.
610+
# walkaround for #48.
611+
n[1] = getTypeInst n[0]
607612
result = n
608613

609614
proc rewriteVarLet(n: NimNode): NimNode =
@@ -637,13 +642,24 @@ proc normalizingRewrites(n: NimNode): NimNode =
637642
result = n[0]
638643
else: discard
639644

645+
proc rewriteFastAsgn(n: NimNode): NimNode =
646+
## Rewrite nnkFastAsgn into nnkAsgn because sem don't like them
647+
case n.kind
648+
of nnkFastAsgn:
649+
result = newNimNode(nnkAsgn, n)
650+
for child in n.items:
651+
result.add child
652+
else: discard
653+
640654
case n.kind
641655
of nnkIdentDefs:
642656
rewriteIdentDefs n
643657
of nnkLetSection, nnkVarSection:
644658
rewriteVarLet n
645659
of nnkHiddenAddr, nnkHiddenDeref:
646660
rewriteHiddenAddrDeref n
661+
of nnkFastAsgn:
662+
rewriteFastAsgn n
647663
else:
648664
nil
649665

@@ -854,13 +870,21 @@ proc cpsXfrm(T: NimNode, n: NimNode): NimNode =
854870
result = copy n
855871
result = workaroundRewrites(result)
856872

857-
macro cps*(T: typed, n: typed): untyped =
873+
macro cps2(T: typed, n: typed): untyped =
858874
# I hate doing stuff inside macros, call the proc to do the work
859875
when defined(nimdoc):
860876
result = n
861877
else:
862878
result = cpsXfrm(T, n)
863879

880+
macro cps*(T: typed, n: typed): untyped =
881+
case n.kind
882+
of nnkProcDef:
883+
result = getImplTransformed n.name
884+
result.addPragma newColonExpr(bindSym"cps2", T)
885+
else:
886+
result = cpsXfrm(T, n)
887+
864888
macro cpsMagic*(n: untyped): untyped =
865889
## upgrade cps primitives to generate errors out of context
866890
## and take continuations as input inside {.cps.} blocks

tests/taste.nim

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,3 +656,15 @@ suite "tasteful tests":
656656
check i == 4
657657

658658
trampoline foo()
659+
660+
block:
661+
## for-loop with splitting
662+
r = 0
663+
proc foo() {.cps: Cont.} =
664+
inc r
665+
for i in 0 ..< 3:
666+
noop()
667+
inc r
668+
669+
trampoline foo()
670+
check r == 4

0 commit comments

Comments
 (0)