Fixes issues with 'discard' in async macro.

This commit is contained in:
Dominik Picheta 2014-02-16 13:55:06 +00:00
commit 7d2ed73a62

View file

@ -104,6 +104,7 @@ when defined(windows):
PDispatcher* = ref object PDispatcher* = ref object
ioPort: THandle ioPort: THandle
hasHandles: bool
TCustomOverlapped = object TCustomOverlapped = object
Internal*: DWORD Internal*: DWORD
@ -125,9 +126,13 @@ when defined(windows):
if CreateIOCompletionPort(sock.THandle, p.ioPort, if CreateIOCompletionPort(sock.THandle, p.ioPort,
cast[TCompletionKey](sock), 1) == 0: cast[TCompletionKey](sock), 1) == 0:
OSError(OSLastError()) OSError(OSLastError())
p.hasHandles = true
proc poll*(p: PDispatcher, timeout = 500) = proc poll*(p: PDispatcher, timeout = 500) =
## Waits for completion events and processes them. ## Waits for completion events and processes them.
if not p.hasHandles:
raise newException(EInvalidValue, "No handles registered in dispatcher.")
let llTimeout = let llTimeout =
if timeout == -1: winlean.INFINITE if timeout == -1: winlean.INFINITE
else: timeout.int32 else: timeout.int32
@ -483,6 +488,7 @@ template createVar(futSymName: string, asyncProc: PNimrodNode,
valueReceiver = newDotExpr(futSym, newIdentNode("read")) # -> future<x>.read valueReceiver = newDotExpr(futSym, newIdentNode("read")) # -> future<x>.read
proc processBody(node, retFutureSym: PNimrodNode): PNimrodNode {.compileTime.} = proc processBody(node, retFutureSym: PNimrodNode): PNimrodNode {.compileTime.} =
result = node
case node.kind case node.kind
of nnkReturnStmt: of nnkReturnStmt:
result = newNimNode(nnkStmtList) result = newNimNode(nnkStmtList)
@ -490,8 +496,6 @@ proc processBody(node, retFutureSym: PNimrodNode): PNimrodNode {.compileTime.} =
if node[0].kind == nnkEmpty: newIdentNode("result") else: node[0]) if node[0].kind == nnkEmpty: newIdentNode("result") else: node[0])
result.add newNimNode(nnkYieldStmt).add(newNilLit()) result.add newNimNode(nnkYieldStmt).add(newNilLit())
of nnkCommand: of nnkCommand:
result = node
echo(treeRepr(node))
if node[0].ident == !"await": if node[0].ident == !"await":
case node[1].kind case node[1].kind
of nnkIdent, nnkCall: of nnkIdent, nnkCall:
@ -500,13 +504,13 @@ proc processBody(node, retFutureSym: PNimrodNode): PNimrodNode {.compileTime.} =
result = newNimNode(nnkYieldStmt).add(node[1]) # -> yield x result = newNimNode(nnkYieldStmt).add(node[1]) # -> yield x
else: else:
error("Invalid node kind in 'await', got: " & $node[1].kind) error("Invalid node kind in 'await', got: " & $node[1].kind)
elif node[1].kind == nnkIdent and node[1][0].ident == !"await": elif node[1].kind == nnkCommand and node[1][0].kind == nnkIdent and
node[1][0].ident == !"await":
# foo await x # foo await x
var newCommand = node var newCommand = node
createVar("future" & $node[0].ident, node[1][0], newCommand[1]) createVar("future" & $node[0].ident, node[1][0], newCommand[1])
result.add newCommand result.add newCommand
of nnkVarSection, nnkLetSection: of nnkVarSection, nnkLetSection:
result = node
case node[0][2].kind case node[0][2].kind
of nnkCommand: of nnkCommand:
if node[0][2][0].ident == !"await": if node[0][2][0].ident == !"await":
@ -517,7 +521,6 @@ proc processBody(node, retFutureSym: PNimrodNode): PNimrodNode {.compileTime.} =
result.add newVarSection result.add newVarSection
else: discard else: discard
of nnkAsgn: of nnkAsgn:
result = node
case node[1].kind case node[1].kind
of nnkCommand: of nnkCommand:
if node[1][0].ident == !"await": if node[1][0].ident == !"await":
@ -532,10 +535,12 @@ proc processBody(node, retFutureSym: PNimrodNode): PNimrodNode {.compileTime.} =
var dummy = newNimNode(nnkStmtList) var dummy = newNimNode(nnkStmtList)
createVar("futureDiscard_" & $toStrLit(node[0][1]), node[0][1], dummy) createVar("futureDiscard_" & $toStrLit(node[0][1]), node[0][1], dummy)
else: else:
result = node
for i in 0 .. <node.len: for i in 0 .. <node.len:
result[i] = processBody(node[i], retFutureSym) result[i] = processBody(node[i], retFutureSym)
assert(not result.isNil)
#echo(treeRepr(result))
proc getName(node: PNimrodNode): string {.compileTime.} = proc getName(node: PNimrodNode): string {.compileTime.} =
case node.kind case node.kind
of nnkPostfix: of nnkPostfix:
@ -548,6 +553,8 @@ proc getName(node: PNimrodNode): string {.compileTime.} =
macro async*(prc: stmt): stmt {.immediate.} = macro async*(prc: stmt): stmt {.immediate.} =
expectKind(prc, nnkProcDef) expectKind(prc, nnkProcDef)
hint("Processing " & prc[0].getName & " as an async proc.")
# Verify that the return type is a PFuture[T] # Verify that the return type is a PFuture[T]
if prc[3][0].kind == nnkIdent: if prc[3][0].kind == nnkIdent:
error("Expected return type of 'PFuture' got '" & $prc[3][0] & "'") error("Expected return type of 'PFuture' got '" & $prc[3][0] & "'")
@ -658,7 +665,7 @@ when isMainModule:
p.register(sock) p.register(sock)
when true: when false:
# Await tests # Await tests
proc main(p: PDispatcher): PFuture[int] {.async.} = proc main(p: PDispatcher): PFuture[int] {.async.} =
discard await p.connect(sock, "irc.freenode.net", TPort(6667)) discard await p.connect(sock, "irc.freenode.net", TPort(6667))
@ -684,7 +691,7 @@ when isMainModule:
else: else:
when true: when false:
var f = p.connect(sock, "irc.freenode.org", TPort(6667)) var f = p.connect(sock, "irc.freenode.org", TPort(6667))
f.callback = f.callback =