Implemented genSym for async function calls.

This commit is contained in:
Dominik Picheta 2013-07-28 13:50:32 +01:00
commit 2330c95b22
2 changed files with 36 additions and 17 deletions

View file

@ -841,18 +841,22 @@ proc len*(disp: PDispatcher): int =
proc createRequestNode(varName, proc createRequestNode(varName,
reqArgs: string, sym: var PNimrodNode): PNimrodNode {.compiletime.} = reqArgs: string, sym: var PNimrodNode): PNimrodNode {.compiletime.} =
result = newNimNode(nnkStmtList) result = newNimNode(nnkStmtList)
sym = genSym(nskVar, varName) # TODO: Using gensym here causes segfaults because hasException is not
# initialised.
sym = newIdentNode(varName) #genSym(nskVar, varName)
var reqObj = newVarStmt(sym, var reqObj = newVarStmt(sym,
parseExpr("PRequest($#)" % [reqArgs])) parseExpr("PRequest($#)" % [reqArgs]))
result.add reqObj result.add reqObj
result.add newNimNode(nnkYieldStmt).add(sym) result.add newNimNode(nnkYieldStmt).add(sym)
# Check for exception # Check for exception
# TODO: Create a custom exception type, create a field which will store
# the original stack trace as given by getStackTrace. Maybe there is a way
# to override the stack trace? That'd be nice.
result.add newIfStmt( result.add newIfStmt(
(newDotExpr(sym, newIdentNode("hasException")), (newDotExpr(sym, newIdentNode("hasException")),
newNimNode(nnkRaiseStmt).add( newNimNode(nnkRaiseStmt).add(
newDotExpr(sym, newIdentNode("exc"))))) newDotExpr(sym, newIdentNode("exc")))))
echo treeRepr(result)
proc toYieldVar(n: PNimrodNode): seq[PNimrodNode] {.compiletime.} = proc toYieldVar(n: PNimrodNode): seq[PNimrodNode] {.compiletime.} =
## Transforms a var/let section ## Transforms a var/let section
@ -871,7 +875,7 @@ proc toYieldVar(n: PNimrodNode): seq[PNimrodNode] {.compiletime.} =
let acceptReqVar = "acceptReq" let acceptReqVar = "acceptReq"
var sym: PNimrodNode var sym: PNimrodNode
result.add createRequestNode(acceptReqVar, result.add createRequestNode(acceptReqVar,
"socket: $#, kind: reqAccept, client: nil" % sockName, sym) "socket: $#, kind: reqAccept, client: nil, hasException: false" % sockName, sym)
case n.kind case n.kind
of nnkLetSection: of nnkLetSection:
@ -899,16 +903,24 @@ const typeDef =
P$#ArgObject = ref object of TObject P$#ArgObject = ref object of TObject
""" """
proc transformCallWithArg(call: PNimrodNode): PNimrodNode {.compiletime.} = proc transformCallWithArg(call: PNimrodNode,
sym: var PNimrodNode): PNimrodNode {.compiletime.} =
result = newNimNode(nnkStmtList) result = newNimNode(nnkStmtList)
result.add parseExpr("var argsToPass: P$#ArgObject" % [$call[1][0].ident]) sym = gensym(nskVar, "argsToPass")
result.add parseExpr("new argsToPass")
# var argsToPass: P$#ArgObject
result.add newNimNode(nnkVarSection).add(
newNimNode(nnkIdentDefs).add(sym,
newIdentNode("P$#ArgObject" % [$call[1][0].ident]),
newNimNode(nnkEmpty)))
result.add newCall("new", sym)
for i in 1 .. call[1].len-1: for i in 1 .. call[1].len-1:
case call[1][i].kind case call[1][i].kind
of nnkLiterals, nnkIdent: of nnkLiterals, nnkIdent:
let dotExpr = newDotExpr(newIdentNode("argsToPass"), let dotExpr = newDotExpr(sym,
newIdentNode("dummy" & $i)) newIdentNode("dummy" & $i))
result.add newAssignment(dotExpr, call[1][i]) result.add newAssignment(dotExpr, call[1][i])
else: assert false else: assert false
@ -919,7 +931,7 @@ proc transformCallWithArg(call: PNimrodNode): PNimrodNode {.compiletime.} =
var args: seq[PNimrodNode] = @[] var args: seq[PNimrodNode] = @[]
for i in 1 .. call[1].len-1: for i in 1 .. call[1].len-1:
args.add(call[1][i]) args.add(call[1][i])
result.add newCall(call[1][0], args) result.add newCall(call[1][0], args)
proc toYieldCall(n: PNimrodNode): seq[PNimrodNode] {.compileTime.} = proc toYieldCall(n: PNimrodNode): seq[PNimrodNode] {.compileTime.} =
## Transforms a call/command ## Transforms a call/command
@ -935,10 +947,15 @@ proc toYieldCall(n: PNimrodNode): seq[PNimrodNode] {.compileTime.} =
"socket: $#, kind: reqWrite, toWrite: $#" % "socket: $#, kind: reqWrite, toWrite: $#" %
[socketName, $(toWrite.toStrLit)], sym) [socketName, $(toWrite.toStrLit)], sym)
else: else:
result.add(transformCallWithArg(n)) var sym: PNimrodNode
result.add(transformCallWithArg(n, sym))
# reqRegister # reqRegister
result.add parseExpr("yield PRequest(socket: $#, kind: reqReg, worker: $#, param: argsToPass)" % var yie = parseExpr("yield PRequest(socket: $#, kind: reqReg, worker: $#)" %
[$n[1][1].ident, callIdent]) [$n[1][1].ident, callIdent])
yie[0].add(newNimNode(nnkExprColonExpr).add(newIdentNode("param"),
sym))
result.add yie
proc transform(n: PNimrodNode): PNimrodNode {.compiletime.} = proc transform(n: PNimrodNode): PNimrodNode {.compiletime.} =
result = newNimNode(nnkStmtList) result = newNimNode(nnkStmtList)

View file

@ -1,6 +1,6 @@
import sockets, asyncio, strutils import sockets, asyncio, strutils
proc processRequest(client: PAsyncSocket, test: string) {.async.} = proc processRequest(client: PAsyncSocket, test: string, closeSock: bool) {.async.} =
assert test == "ahha" assert test == "ahha"
assert client != nil assert client != nil
echo("Test = ", test) echo("Test = ", test)
@ -8,9 +8,10 @@ proc processRequest(client: PAsyncSocket, test: string) {.async.} =
echo("Read: ", line) echo("Read: ", line)
await send(client, "Goodbye.\c\L") await send(client, "Goodbye.\c\L")
await send(client, "Goodbye.\c\L") #await send(client, "Goodbye.\c\L")
await send(client, "Goodbye.\c\L") #await send(client, "Goodbye.\c\L")
client.close() if closeSock:
client.close()
proc processServer() {.async.} = proc processServer() {.async.} =
var sock = AsyncSocket() var sock = AsyncSocket()
@ -23,7 +24,8 @@ proc processServer() {.async.} =
while true: while true:
let client: PAsyncSocket = await(accept(sock)) let client: PAsyncSocket = await(accept(sock))
assert client != nil assert client != nil
await processRequest(client, "ahha") await processRequest(client, "ahha", false)
await processRequest(client, "ahha", true)
var disp = newDispatcher(false) var disp = newDispatcher(false)
disp.register(processServer, nil) disp.register(processServer, nil)