Skip to content

Commit

Permalink
undo #258 pending alternatives
Browse files Browse the repository at this point in the history
This reverts commit e1f829e.
  • Loading branch information
disruptek committed Nov 13, 2021
1 parent c2b1466 commit 4ec3364
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 58 deletions.
4 changes: 0 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -412,10 +412,6 @@ yet demonstrates different exploits of `cps`.
See [this list of open Nim issues surfaced by CPS
development](https://github.com/nim-lang/Nim/issues?q=is%3Aopen+is%3Aissue+label%3ACPS); some repercussions include the following:

- You can overload `cpsVoodoo` procedures with `cpsVoodoo`, and `cpsMagic`
with `cpsMagic`, but other overloads run the risk of clashing with the
shim produced by these procedure macros.

- Exceptions are evaluated differently under `panics:on` and `panics:off`, so
you may need to use `panics:on` in order to produce correct code.

Expand Down
32 changes: 5 additions & 27 deletions cps/spec.nim
Original file line number Diff line number Diff line change
Expand Up @@ -363,18 +363,7 @@ type
Dismissed ## The continuation is currently somewhere else
Finished ## The continuation is finished and can no longer be resumed

proc wrapErrorShim(n: NimNode): NimNode =
## Wrap a proc definition in a guard to avoid symbol redefinition errors.
expectKind(n, nnkProcDef)
# when not declaredInScope(fn):
result =
nnkWhenStmt.newTree:
nnkElifBranch.newTree:
prefix(newCall(bindSym"declaredInScope", n.name), "not")
# proc fn() = error "you can only do this in cps"
result.last.add n

proc makeErrorShim(n: NimNode): NimNode =
proc makeErrorShim*(n: NimNode): NimNode =
## Upgrades a procedure to serve as a CPS primitive, generating
## errors out of `.cps.` context and taking continuations as input.
expectKind(n, nnkProcDef)
Expand All @@ -383,7 +372,6 @@ proc makeErrorShim(n: NimNode): NimNode =
# value. While this version will throw an exception at runtime, it
# may be used inside CPS as magic(); for better programmer ergonomics.
var shim = copyNimTree n
shim.addPragma ident"used"
del(shim.params, 1) # delete the 1st Continuation argument
let msg = newLit($n.name & "() is only valid in {.cps.} context")
shim.body = # raise a defect when invoked directly
Expand All @@ -401,12 +389,8 @@ macro cpsMagic*(n: untyped): untyped =
## The target procedure of a cpsMagic pragma returns the `Continuation`
## to which control-flow should return; this is _usually_ the same value
## passed into the procedure, but this is not required nor is it checked!
##
## You can overload `cpsVoodoo` procedures with `cpsVoodoo`, and `cpsMagic`
## with `cpsMagic`, but you cannot mix the two.
expectKind(n, nnkProcDef)
let n = copyNimTree n
n.addPragma ident"used"
result = newStmtList NormNode n # preserve the original proc
var shim = makeErrorShim n # create the shim
shim.params[0] = newEmptyNode() # wipe out the return value

Expand All @@ -415,25 +399,19 @@ macro cpsMagic*(n: untyped): untyped =
# continuation.
shim.addPragma ident"cpsMustJump"
shim.addPragma ident"cpsMagicCall"
shim = wrapErrorShim shim # `when not declaredInScope(fn): shim`
result = newStmtList(shim, n) # preserve the original proc
result.add shim

macro cpsVoodoo*(n: untyped): untyped =
## Similar to a `cpsMagic` where the first argument is concerned, but
## may specify a return value which is usable inside the CPS procedure.
##
## You can overload `cpsVoodoo` procedures with `cpsVoodoo`, and `cpsMagic`
## with `cpsMagic`, but you cannot mix the two.
expectKind(n, nnkProcDef)
let n = copyNimTree n
n.addPragma ident"used"
result = newStmtList n # preserve the original proc
var shim = makeErrorShim n # create the shim

# we use this pragma to identify the primitive and rewrite it inside
# CPS so that it again binds to the version that takes a continuation.
shim.addPragma ident"cpsVoodooCall"
shim = wrapErrorShim shim # `when not declaredInScope(fn): shim`
result = newStmtList(shim, n) # preserve the original proc
result.add shim

when cpsTraceDeque or cpsStackFrames:
from std/strformat import `&`
Expand Down
28 changes: 13 additions & 15 deletions cps/transform.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1077,21 +1077,19 @@ macro cpsHandleUnhandledException(contType: typed; n: typed): untyped =
# Rewrite continuations within this continuation body as well
fnDef.body = fnDef.body.filter(handle)
# Put the body in a try-except to capture the unhandled exception
fnDef.body =
genAstOpt({}, contType, cont = NimNode cont,
unwind = ident"unwind", # just a desym of the unwind()
body = NimNode fnDef.body):
bind getCurrentException
try:
body
except:
cont.ex = getCurrentException()
# A continuation body created with makeContProc (which is all of
# them) will have a terminator in the body, thus this part can
# only be reached iff the except branch happened to deter the jump
#
# Workaround for https://github.com/nim-lang/Nim/issues/18411
return Continuation unwind(contType(cont), cont.ex)
fnDef.body = genAstOpt({}, contType, cont = NimNode cont,
body = NimNode fnDef.body):
bind getCurrentException
try:
body
except:
cont.ex = getCurrentException()
# A continuation body created with makeContProc (which is all of
# them) will have a terminator in the body, thus this part can
# only be reached iff the except branch happened to deter the jump
#
# Workaround for https://github.com/nim-lang/Nim/issues/18411
return Continuation: unwind(contType(cont), cont.ex)
result = fnDef

debugAnnotation cpsHandleUnhandledException, n:
Expand Down
11 changes: 0 additions & 11 deletions tests/tapi.nim
Original file line number Diff line number Diff line change
Expand Up @@ -210,14 +210,3 @@ suite "cps api":
return 3

check foo() == 3

block:
## magic/voodoo can be overloaded
type
C = ref object of Continuation
O = ref object of C

proc sayYourNameV(c: C): string {.cpsVoodoo.} = return "I am C"
proc sayYourNameV(c: O): string {.cpsVoodoo.} = return "I am O"
proc sayYourNameM(c: C): C {.cpsMagic.} = discard "I am C"
proc sayYourNameM(c: O): O {.cpsMagic.} = discard "I am O"
2 changes: 1 addition & 1 deletion tests/thooks.nim
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ suite "hooks":
block:
## custom continuation exception handling works
var k = newKiller 4
proc unwind(c: Cont; ex: ref Exception): Continuation {.cpsMagic.} =
proc unwind(c: Cont; ex: ref Exception): Continuation {.cpsMagic, used.} =
inc k
result = cps.unwind(c, ex)

Expand Down

0 comments on commit 4ec3364

Please sign in to comment.