Skip to content

Commit 4f88928

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 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 c1a0c20 commit 4f88928

3 files changed

Lines changed: 38 additions & 17 deletions

File tree

cps.nim

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -941,13 +941,21 @@ proc cpsXfrm(T: NimNode, n: NimNode): NimNode =
941941
result = copy n
942942
result = workaroundRewrites(result)
943943

944-
macro cps*(T: typed, n: typed): untyped =
944+
macro cps2(T: typed, n: typed): untyped =
945945
# I hate doing stuff inside macros, call the proc to do the work
946946
when defined(nimdoc):
947947
result = n
948948
else:
949949
result = cpsXfrm(T, n)
950950

951+
macro cps*(T: typed, n: typed): untyped =
952+
case n.kind
953+
of nnkProcDef:
954+
result = getImplTransformed n.name
955+
result.addPragma newColonExpr(bindSym"cps2", T)
956+
else:
957+
result = cpsXfrm(T, n)
958+
951959
macro cpsMagic*(n: untyped): untyped =
952960
## upgrade cps primitives to generate errors out of context
953961
## and take continuations as input inside {.cps.} blocks

cps/spec.nim

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,12 @@ proc normalizingRewrites*(n: NimNode): NimNode =
324324
if n.len == 2:
325325
n.add newEmptyNode()
326326
elif n[1].isEmpty: # add explicit type symbol
327-
n[1] = getTypeInst n[2]
327+
if not n[2].isEmpty:
328+
n[1] = getTypeInst n[2]
329+
else:
330+
# get the type from the symbol as the last resort.
331+
# walkaround for #48.
332+
n[1] = getTypeInst n[0]
328333
n[2] = normalizingRewrites n[2]
329334
result = n
330335

@@ -439,6 +444,15 @@ proc normalizingRewrites*(n: NimNode): NimNode =
439444
else:
440445
discard
441446

447+
proc rewriteFastAsgn(n: NimNode): NimNode =
448+
## Rewrite nnkFastAsgn into nnkAsgn because sem don't like them
449+
case n.kind
450+
of nnkFastAsgn:
451+
result = newNimNode(nnkAsgn, n)
452+
for child in n.items:
453+
result.add child
454+
else: discard
455+
442456
case n.kind
443457
of nnkIdentDefs:
444458
rewriteIdentDefs n
@@ -452,6 +466,8 @@ proc normalizingRewrites*(n: NimNode): NimNode =
452466
rewriteReturn n
453467
of CallNodes:
454468
rewriteHidden n
469+
of nnkFastAsgn:
470+
rewriteFastAsgn n
455471
else:
456472
nil
457473

tests/taste.nim

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -998,19 +998,16 @@ suite "tasteful tests":
998998

999999
block:
10001000
## for loops with continue, break and a split
1001-
when true:
1002-
skip"pending #48"
1003-
else:
1004-
r = 0
1005-
proc foo() {.cps: Cont.} =
1006-
inc r
1007-
for i in 0 .. 3:
1008-
noop()
1009-
if i == 0:
1010-
continue
1011-
if i > 2:
1012-
break
1013-
r.inc i
1001+
r = 0
1002+
proc foo() {.cps: Cont.} =
1003+
inc r
1004+
for i in 0 .. 3:
1005+
noop()
1006+
if i == 0:
1007+
continue
1008+
if i > 2:
1009+
break
1010+
r.inc i
10141011

1015-
trampoline foo()
1016-
check r == 4
1012+
trampoline foo()
1013+
check r == 4

0 commit comments

Comments
 (0)