Fix `async` `proc` types & small cleanups (#347)
* Fix `async` `proc` types & small cleanups * review comments
This commit is contained in:
parent
4ada7fc0e1
commit
f3b77d8661
|
@ -72,6 +72,13 @@ proc verifyReturnType(typeName: string) {.compileTime.} =
|
|||
macro unsupported(s: static[string]): untyped =
|
||||
error s
|
||||
|
||||
proc params2(someProc: NimNode): NimNode =
|
||||
# until https://github.com/nim-lang/Nim/pull/19563 is available
|
||||
if someProc.kind == nnkProcTy:
|
||||
someProc[0]
|
||||
else:
|
||||
params(someProc)
|
||||
|
||||
proc cleanupOpenSymChoice(node: NimNode): NimNode {.compileTime.} =
|
||||
# Replace every Call -> OpenSymChoice by a Bracket expr
|
||||
# ref https://github.com/nim-lang/Nim/issues/11091
|
||||
|
@ -92,21 +99,20 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} =
|
|||
error("Cannot transform " & $prc.kind & " into an async proc." &
|
||||
" proc/method definition or lambda node expected.")
|
||||
|
||||
let returnType =
|
||||
cleanupOpenSymChoice(if prc.kind == nnkProcTy: prc[0][0] else: prc.params[0])
|
||||
var baseType: NimNode
|
||||
let returnType = cleanupOpenSymChoice(prc.params2[0])
|
||||
|
||||
# Verify that the return type is a Future[T]
|
||||
let baseType =
|
||||
if returnType.kind == nnkBracketExpr:
|
||||
let fut = repr(returnType[0])
|
||||
verifyReturnType(fut)
|
||||
baseType = returnType[1]
|
||||
returnType[1]
|
||||
elif returnType.kind == nnkEmpty:
|
||||
baseType = returnType
|
||||
ident("void")
|
||||
else:
|
||||
verifyReturnType(repr(returnType))
|
||||
raiseAssert("Unhandled async return type: " & $prc.kind)
|
||||
|
||||
let subtypeIsVoid = returnType.kind == nnkEmpty or
|
||||
(baseType.kind == nnkIdent and returnType[1].eqIdent("void"))
|
||||
let subtypeIsVoid = baseType.eqIdent("void")
|
||||
|
||||
if prc.kind in {nnkProcDef, nnkLambda, nnkMethodDef, nnkDo}:
|
||||
let
|
||||
|
@ -260,13 +266,12 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} =
|
|||
# Add discardable pragma.
|
||||
if returnType.kind == nnkEmpty:
|
||||
# Add Future[void]
|
||||
prc.params[0] =
|
||||
prc.params2[0] =
|
||||
newNimNode(nnkBracketExpr, prc)
|
||||
.add(newIdentNode("Future"))
|
||||
.add(newIdentNode("void"))
|
||||
|
||||
prc
|
||||
#echo(treeRepr(result))
|
||||
|
||||
template await*[T](f: Future[T]): untyped =
|
||||
when declared(chronosInternalRetFuture):
|
||||
|
@ -318,8 +323,8 @@ macro async*(prc: untyped): untyped =
|
|||
## Macro which processes async procedures into the appropriate
|
||||
## iterators and yield statements.
|
||||
if prc.kind == nnkStmtList:
|
||||
for oneProc in prc:
|
||||
result = newStmtList()
|
||||
for oneProc in prc:
|
||||
result.add asyncSingleProc(oneProc)
|
||||
else:
|
||||
result = asyncSingleProc(prc)
|
||||
|
|
|
@ -13,6 +13,7 @@ when defined(nimHasUsed): {.used.}
|
|||
|
||||
type
|
||||
RetValueType = proc(n: int): Future[int] {.async.}
|
||||
RetImplicitVoidType = proc(n: int) {.async.}
|
||||
RetVoidType = proc(n: int): Future[void] {.async.}
|
||||
|
||||
proc asyncRetValue(n: int): Future[int] {.async.} =
|
||||
|
@ -59,6 +60,9 @@ proc testAwait(): Future[bool] {.async.} =
|
|||
block:
|
||||
let fn: RetVoidType = asyncRetVoid
|
||||
await fn(100)
|
||||
block:
|
||||
let fn: RetImplicitVoidType = asyncRetVoid
|
||||
await fn(100)
|
||||
block:
|
||||
let fn: RetValueType = asyncRetValue
|
||||
if (await fn(100)) != 1000:
|
||||
|
|
Loading…
Reference in New Issue