Rewrote try transformation in asyncdispatch slightly.
This seems to be awakening a compiler bug though.
This commit is contained in:
parent
5ad9d874c3
commit
f7adc8e601
2 changed files with 54 additions and 36 deletions
|
|
@ -1216,6 +1216,7 @@ proc generateExceptionCheck(futSym,
|
||||||
if tryStmt.kind == nnkNilLit:
|
if tryStmt.kind == nnkNilLit:
|
||||||
result = rootReceiver
|
result = rootReceiver
|
||||||
else:
|
else:
|
||||||
|
# Create an if statement checking the type of the current exception
|
||||||
var exceptionChecks: seq[tuple[cond, body: NimNode]] = @[]
|
var exceptionChecks: seq[tuple[cond, body: NimNode]] = @[]
|
||||||
let errorNode = newDotExpr(futSym, newIdentNode("error"))
|
let errorNode = newDotExpr(futSym, newIdentNode("error"))
|
||||||
for i in 1 .. <tryStmt.len:
|
for i in 1 .. <tryStmt.len:
|
||||||
|
|
@ -1240,6 +1241,8 @@ proc generateExceptionCheck(futSym,
|
||||||
expectKind(exceptBranch[exceptIdentCount], nnkStmtList)
|
expectKind(exceptBranch[exceptIdentCount], nnkStmtList)
|
||||||
exceptionChecks.add((ifCond, exceptBranch[exceptIdentCount]))
|
exceptionChecks.add((ifCond, exceptBranch[exceptIdentCount]))
|
||||||
# -> -> else: raise futSym.error
|
# -> -> else: raise futSym.error
|
||||||
|
# This branch is entered when there are not 'except' branches
|
||||||
|
# specific to the exception.
|
||||||
exceptionChecks.add((newIdentNode("true"),
|
exceptionChecks.add((newIdentNode("true"),
|
||||||
newNimNode(nnkRaiseStmt).add(errorNode)))
|
newNimNode(nnkRaiseStmt).add(errorNode)))
|
||||||
# Read the future if there is no error.
|
# Read the future if there is no error.
|
||||||
|
|
@ -1257,6 +1260,7 @@ proc generateExceptionCheck(futSym,
|
||||||
(newDotExpr(futSym, newIdentNode("failed")), ifBody)
|
(newDotExpr(futSym, newIdentNode("failed")), ifBody)
|
||||||
)
|
)
|
||||||
result.add elseNode
|
result.add elseNode
|
||||||
|
echo(treeRepr(result))
|
||||||
|
|
||||||
template createVar(result: var NimNode, futSymName: string,
|
template createVar(result: var NimNode, futSymName: string,
|
||||||
asyncProc: NimNode,
|
asyncProc: NimNode,
|
||||||
|
|
@ -1336,53 +1340,53 @@ proc processBody(node, retFutureSym: NimNode,
|
||||||
of nnkTryStmt:
|
of nnkTryStmt:
|
||||||
# try: await x; except: ...
|
# try: await x; except: ...
|
||||||
result = newNimNode(nnkStmtList, node)
|
result = newNimNode(nnkStmtList, node)
|
||||||
template wrapInTry(n, tryBody: expr) =
|
template wrapInTry(n, tryBody: expr, copyN: bool) =
|
||||||
var temp = n
|
var temp = if copyN: n.copy else: n
|
||||||
n[0] = tryBody
|
n[0] = tryBody
|
||||||
tryBody = temp
|
tryBody = temp
|
||||||
|
|
||||||
# Transform ``except`` body.
|
# Transform ``except`` body.
|
||||||
# TODO: Could we perform some ``await`` transformation here to get it
|
# TODO: Could we perform some ``await`` transformation here to get it
|
||||||
# working in ``except``?
|
# working in ``except``?
|
||||||
tryBody[1] = processBody(n[1], retFutureSym, subTypeIsVoid, nil)
|
#tryBody[1] = processBody(n[1], retFutureSym, subTypeIsVoid, nil)
|
||||||
|
|
||||||
proc processForTry(n: NimNode, i: var int,
|
|
||||||
res: NimNode): bool {.compileTime.} =
|
proc processForTry(child: NimNode, origNode: NimNode,
|
||||||
|
): tuple[res: NimNode, transformed: bool] {.compileTime, nimcall.}
|
||||||
|
proc processNodes(n: NimNode): NimNode {.compileTime, nimcall.} =
|
||||||
|
result = newStmtList()
|
||||||
|
#echo(treeRepr(n))
|
||||||
|
var nodes = n.skipStmtList()
|
||||||
|
for child in nodes.children:
|
||||||
|
var (res, transformed) = processForTry(child, n)
|
||||||
|
if not transformed:
|
||||||
|
# If this line of code hasn't been transformed, we need to wrap
|
||||||
|
# it in a try statement.
|
||||||
|
#wrapInTry(node, res, false)
|
||||||
|
discard
|
||||||
|
result.add res
|
||||||
|
|
||||||
|
proc processForTry(child: NimNode, origNode: NimNode,
|
||||||
|
): tuple[res: NimNode, transformed: bool] =
|
||||||
## Transforms the body of the tryStmt. Does not transform the
|
## Transforms the body of the tryStmt. Does not transform the
|
||||||
## body in ``except``.
|
## body in ``except``.
|
||||||
## Returns true if the tryStmt node was transformed into an ifStmt.
|
## Returns true if the tryStmt node was transformed into an ifStmt.
|
||||||
result = false
|
var processed: NimNode # = processBody(child, retFutureSym,
|
||||||
var skipped = n.skipStmtList()
|
# subTypeIsVoid, origNode)
|
||||||
while i < skipped.len:
|
|
||||||
var processed = processBody(skipped[i], retFutureSym,
|
|
||||||
subTypeIsVoid, n)
|
|
||||||
|
|
||||||
# Check if we transformed the node into an exception check.
|
# Check if we transformed the node into an exception check.
|
||||||
# This suggests skipped[i] contains ``await``.
|
# This suggests skipped[i] contains ``await``.
|
||||||
if processed.kind != skipped[i].kind or processed.len != skipped[i].len:
|
if processed.kind != child.kind or processed.len != child.len:
|
||||||
processed = processed.skipUntilStmtList()
|
processed = processed.skipUntilStmtList()
|
||||||
expectKind(processed, nnkStmtList)
|
expectKind(processed, nnkStmtList)
|
||||||
expectKind(processed[2][1], nnkElse)
|
expectKind(processed[2][1], nnkElse)
|
||||||
i.inc
|
|
||||||
|
|
||||||
if not processForTry(n, i, processed[2][1][0]):
|
processed[2][1][0] = processNodes(processed[2][1][0])
|
||||||
# We need to wrap the nnkElse nodes back into a tryStmt.
|
|
||||||
# As they are executed if an exception does not happen
|
|
||||||
# inside the awaited future.
|
|
||||||
# The following code will wrap the nodes inside the
|
|
||||||
# original tryStmt.
|
|
||||||
wrapInTry(n, processed[2][1][0])
|
|
||||||
|
|
||||||
res.add processed
|
result = (processed, true)
|
||||||
result = true
|
|
||||||
else:
|
else:
|
||||||
res.add skipped[i]
|
result = (child, false)
|
||||||
i.inc
|
|
||||||
var i = 0
|
result = processNodes(node)
|
||||||
if not processForTry(node, i, result):
|
|
||||||
# If the tryStmt hasn't been transformed we can just put the body
|
|
||||||
# back into it.
|
|
||||||
wrapInTry(node, result)
|
|
||||||
return
|
return
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
|
|
@ -1492,8 +1496,8 @@ macro async*(prc: stmt): stmt {.immediate.} =
|
||||||
result[6] = outerProcBody
|
result[6] = outerProcBody
|
||||||
|
|
||||||
#echo(treeRepr(result))
|
#echo(treeRepr(result))
|
||||||
#if prc[0].getName == "test":
|
if prc[0].getName == "catch":
|
||||||
# echo(toStrLit(result))
|
echo(toStrLit(result))
|
||||||
|
|
||||||
proc recvLine*(socket: TAsyncFD): Future[string] {.async.} =
|
proc recvLine*(socket: TAsyncFD): Future[string] {.async.} =
|
||||||
## Reads a line of data from ``socket``. Returned future will complete once
|
## Reads a line of data from ``socket``. Returned future will complete once
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,9 @@ proc foobar() {.async.} =
|
||||||
if 5 == 5:
|
if 5 == 5:
|
||||||
raise newException(EInvalidIndex, "Test")
|
raise newException(EInvalidIndex, "Test")
|
||||||
|
|
||||||
|
proc raiseExc() =
|
||||||
|
raise newException(EInvalidIndex, "Test")
|
||||||
|
|
||||||
proc catch() {.async.} =
|
proc catch() {.async.} =
|
||||||
# TODO: Create a test for when exceptions are not caught.
|
# TODO: Create a test for when exceptions are not caught.
|
||||||
try:
|
try:
|
||||||
|
|
@ -91,6 +94,14 @@ proc test4(): Future[int] {.async.} =
|
||||||
except:
|
except:
|
||||||
result = 2
|
result = 2
|
||||||
|
|
||||||
|
proc test2650(): Future[int] {.async.} =
|
||||||
|
# Test for bug #2650. https://github.com/Araq/Nim/issues/2650
|
||||||
|
try:
|
||||||
|
raiseExc()
|
||||||
|
discard await foo()
|
||||||
|
except:
|
||||||
|
result = 5
|
||||||
|
|
||||||
var x = test()
|
var x = test()
|
||||||
assert x.read
|
assert x.read
|
||||||
|
|
||||||
|
|
@ -102,3 +113,6 @@ assert y.read == 2
|
||||||
|
|
||||||
y = test4()
|
y = test4()
|
||||||
assert y.read == 2
|
assert y.read == 2
|
||||||
|
|
||||||
|
y = test2650()
|
||||||
|
assert y.read == 5
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue