From a30e4fe361c846bc3c1a4185518e4067f7abb242 Mon Sep 17 00:00:00 2001 From: Yuriy Glukhov Date: Thu, 15 Aug 2019 17:26:00 +0200 Subject: [PATCH 1/3] No Iter in stacktraces --- chronos/asyncmacro2.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chronos/asyncmacro2.nim b/chronos/asyncmacro2.nim index c0db4e7..570d8aa 100644 --- a/chronos/asyncmacro2.nim +++ b/chronos/asyncmacro2.nim @@ -202,7 +202,7 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} = # -> {.pop.} # -> # -> complete(retFuture, result) - var iteratorNameSym = genSym(nskIterator, $prcName & "Iter") + var iteratorNameSym = genSym(nskIterator, $prcName) var procBody = prc.body.processBody(retFutureSym, subtypeIsVoid, futureVarIdents) # don't do anything with forward bodies (empty) From bff83a9c3c5c33c0e4039d1fa8b3883daac3883e Mon Sep 17 00:00:00 2001 From: Yuriy Glukhov Date: Thu, 15 Aug 2019 17:41:15 +0200 Subject: [PATCH 2/3] Disallow waitFor in async --- chronos/asyncmacro2.nim | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/chronos/asyncmacro2.nim b/chronos/asyncmacro2.nim index 570d8aa..b970e4d 100644 --- a/chronos/asyncmacro2.nim +++ b/chronos/asyncmacro2.nim @@ -188,13 +188,11 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} = var subRetType = if returnType.kind == nnkEmpty: newIdentNode("void") else: baseType - outerProcBody.add( - newVarStmt(retFutureSym, - newCall( - newNimNode(nnkBracketExpr, prc.body).add( - newIdentNode("newFuture"), - subRetType), - newLit(prcName)))) # Get type from return type of this proc + outerProcBody.add quote do: + var `retFutureSym` = newFuture[`subRetType`](`prcName`) + template waitFor[T](f: Future[T]): T = + static: + assert(false, "waitFor can not be used within {.async.}") # -> iterator nameIter(): FutureBase {.closure.} = # -> {.push warning[resultshadowed]: off.} From 2346ed3c6c3775e340c13f17664b7892033dbbbe Mon Sep 17 00:00:00 2001 From: Yuriy Glukhov Date: Thu, 15 Aug 2019 18:35:42 +0200 Subject: [PATCH 3/3] Fixup error reporting --- chronos/asyncmacro2.nim | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/chronos/asyncmacro2.nim b/chronos/asyncmacro2.nim index b970e4d..8207da8 100644 --- a/chronos/asyncmacro2.nim +++ b/chronos/asyncmacro2.nim @@ -29,7 +29,7 @@ template createCb(retFutureSym, iteratorNameSym, bind finished var nameIterVar = iteratorNameSym - #{.push stackTrace: off.} + {.push stackTrace: off.} proc identName(udata: pointer = nil) {.closure.} = try: if not(nameIterVar.finished()): @@ -63,7 +63,7 @@ template createCb(retFutureSym, iteratorNameSym, retFutureSym.fail(getCurrentException()) identName() - #{.pop.} + {.pop.} proc createFutureVarCompletions(futureVarIdents: seq[NimNode], fromNode: NimNode): NimNode {.compileTime.} = @@ -151,6 +151,9 @@ proc verifyReturnType(typeName: string) {.compileTime.} = error("Expected return type of 'Future' got '$1'" % typeName) +macro unsupported(s: static[string]): untyped = + error s + proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} = ## This macro transforms a single procedure into a closure iterator. ## The ``async`` macro supports a stmtList holding multiple async procedures. @@ -190,9 +193,6 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} = else: baseType outerProcBody.add quote do: var `retFutureSym` = newFuture[`subRetType`](`prcName`) - template waitFor[T](f: Future[T]): T = - static: - assert(false, "waitFor can not be used within {.async.}") # -> iterator nameIter(): FutureBase {.closure.} = # -> {.push warning[resultshadowed]: off.} @@ -249,6 +249,8 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} = # -> return retFuture outerProcBody.add newNimNode(nnkReturnStmt, prc.body[^1]).add(retFutureSym) + prc.addPragma(newColonExpr(ident "stackTrace", ident "off")) + result = prc if subtypeIsVoid: @@ -264,8 +266,8 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} = template await*[T](f: Future[T]): auto = when declared(chronosInternalRetFuture): - when not declared(chronosInternalTmpFuture): - var chronosInternalTmpFuture: FutureBase + when not declaredInScope(chronosInternalTmpFuture): + var chronosInternalTmpFuture {.inject.}: FutureBase chronosInternalTmpFuture = f chronosInternalRetFuture.child = chronosInternalTmpFuture yield chronosInternalTmpFuture @@ -273,21 +275,19 @@ template await*[T](f: Future[T]): auto = chronosInternalRetFuture.child = nil cast[type(f)](chronosInternalTmpFuture).internalRead() else: - static: - assert(false, "Await only available within {.async.}") + unsupported "await is only available within {.async.}" template awaitne*[T](f: Future[T]): Future[T] = when declared(chronosInternalRetFuture): - when not declared(chronosInternalTmpFuture): - var chronosInternalTmpFuture: FutureBase + when not declaredInScope(chronosInternalTmpFuture): + var chronosInternalTmpFuture {.inject.}: FutureBase chronosInternalTmpFuture = f chronosInternalRetFuture.child = chronosInternalTmpFuture yield chronosInternalTmpFuture chronosInternalRetFuture.child = nil cast[type(f)](chronosInternalTmpFuture) else: - static: - assert(false, "Await only available within {.async.}") + unsupported "awaitne is only available within {.async.}" macro async*(prc: untyped): untyped = ## Macro which processes async procedures into the appropriate