Skip to content

Commit

Permalink
results.? compatibity
Browse files Browse the repository at this point in the history
This PR uses the facilities provided in
status-im/nim-stew#134 to support `?` in `async`
proc's.
  • Loading branch information
arnetheduck committed Jun 5, 2023
1 parent 2ef34c7 commit baf3600
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 2 deletions.
2 changes: 1 addition & 1 deletion chronos.nimble
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ license = "MIT or Apache License 2.0"
skipDirs = @["tests"]

requires "nim >= 1.2.0",
"stew",
"stew#assign-result",
"bearssl",
"httputils",
"unittest2"
Expand Down
9 changes: 8 additions & 1 deletion chronos/asyncmacro2.nim
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,13 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} =

procBody = prc.body.processBody(castFutureSym, baseType)

# Support `let x = ? await ...`
assignResultSym = ident "assignResult?"
assignResult = quote do:
when declared(Result):
template `assignResultSym`(v: Result) =
`castFutureSym`.complete(v)

# don't do anything with forward bodies (empty)
if procBody.kind != nnkEmpty:
let
Expand Down Expand Up @@ -185,7 +192,7 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} =

completeDecl = completeWithNode(castFutureSym, baseType, procBodyBlck)

closureBody = newStmtList(resultDecl, completeDecl)
closureBody = newStmtList(assignResult, resultDecl, completeDecl)

internalFutureParameter = nnkIdentDefs.newTree(
internalFutureSym, newIdentNode("FutureBase"), newEmptyNode())
Expand Down
29 changes: 29 additions & 0 deletions tests/testmacro.nim
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,20 @@ proc testAwaitne(): Future[bool] {.async.} =

return true

proc resultOk(): Future[Result[int, string]] {.async.} =
return ok(42)

proc resultErr(): Future[Result[int, string]] {.async.} =
return err("string")

proc testResult: Future[Result[int, string]] {.async.} =
let
x = ? await resultOk()

if x == 42:
let _ = ? await resultErr()
return err("not this one")

suite "Macro transformations test suite":
test "`await` command test":
check waitFor(testAwait()) == true
Expand Down Expand Up @@ -226,3 +240,18 @@ suite "Closure iterator's exception transformation issues":

waitFor(x())

suite "Result integration":
test "question mark":
# generics are tricky and buggy, test them more!
proc someFunc2[T](v: T): Future[Result[T, string]] {.async.} =
return ok(v)
proc someFunc[T](v: T): Future[Result[T, string]] {.async.} =
let tmp = ? await someFunc2(v)
return ok(tmp + 2)

proc caller(v: int): Future[Result[int, string]] {.async.} =
return ok(3 + ? await someFunc(v))

check waitFor(testResult()).error() == "string"

check waitFor(caller(42))[] == 42 + 2 + 3

0 comments on commit baf3600

Please sign in to comment.