Skip to content

Commit

Permalink
detect async procs
Browse files Browse the repository at this point in the history
  • Loading branch information
nitely committed Jan 4, 2025
1 parent fda6565 commit 2689ab2
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 22 deletions.
24 changes: 22 additions & 2 deletions lib/pure/asyncmacro.nim
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,29 @@ proc verifyReturnType(typeName: string, node: NimNode = nil) =
error("Expected return type of 'Future' got '$1'" %
typeName, node)

proc isAsyncPrc0(n: NimNode): bool =
if n.kind == nnkBlockStmt and n[0].strVal == "asynctrack":
return true
if n.kind in RoutineNodes:
return false
for i in 0 .. n.len-1:
if isAsyncPrc0(n[i]):
return true
return false

proc isAsyncPrc(n: NimNode): bool =
for i in 0 .. n.len-1:
if isAsyncPrc0(n[i]):
return true
return false

macro withRaises[T](f: Future[T], body: untyped): untyped =
#echo repr f.kind
# XXX support more cases
let prcSym = case f.kind
of nnkSym:
if f.getImpl.kind == nnkIdentDefs and f.getImpl[^1].kind == nnkCall:
#echo repr f.getImpl[^1][0]
f.getImpl[^1][0]
else:
nil
Expand All @@ -173,7 +190,8 @@ macro withRaises[T](f: Future[T], body: untyped): untyped =
else:
nil
#echo repr prcSym
if prcSym != nil:
#echo repr prcSym.getImpl
if prcSym != nil and isAsyncPrc(prcSym.getImpl):
let raisesList = getRaisesList(prcSym)
var raisesListTyp = newNimNode(nnkBracket)
if raisesList.len > 0:
Expand Down Expand Up @@ -361,8 +379,10 @@ proc asyncSingleProc(prc: NimNode): NimNode =

# based on the yglukhov's patch to chronos: https://github.com/status-im/nim-chronos/pull/47
if procBody.kind != nnkEmpty:
let asynctrack = ident"asynctrack"
body2.add quote do:
`outerProcBody`
block `asynctrack`:
`outerProcBody`
result.body = body2

macro async*(prc: untyped): untyped =
Expand Down
46 changes: 26 additions & 20 deletions tests/async/tasync_error_tracking.nim
Original file line number Diff line number Diff line change
Expand Up @@ -76,18 +76,16 @@ block:
doAssert not compiles(bad())

block:
proc bar {.async.} =
err(false)

proc foo {.async.} =
await bar()

template good =
proc bar {.async.} =
err(false)
proc foo {.async.} =
await bar()
proc main {.async, raises: [MyError].} =
await foo()
template bad =
proc bar {.async.} =
err(false)
proc foo {.async.} =
await bar()
proc main {.async, raises: [].} =
await foo()
doAssert compiles(good())
Expand All @@ -103,17 +101,25 @@ block:
doAssert compiles(good())
doAssert not compiles(bad())

# XXX this should not compile;
# add Future.isInternal field?
when false:
proc foo {.async, raises: [].} =
let f = newFuture[void]()
f.complete()
await f
when false:
block:
template good =
proc foo {.async, raises: [Exception].} =
await newFuture[void]()
template bad =
proc foo {.async, raises: [].} =
await newFuture[void]()
doAssert compiles(good())
doAssert not compiles(bad())

block:
proc fut: Future[void] =
newFuture[void]()
proc main {.async, raises: [].} =
let f = fut()
f.complete()
await f

template good =
proc main {.async, raises: [Exception].} =
await fut()
template bad =
proc main {.async, raises: [].} =
await fut()
doAssert compiles(good())
doAssert not compiles(bad())

0 comments on commit 2689ab2

Please sign in to comment.