Implemented default arguments for async procs.
This commit is contained in:
parent
2330c95b22
commit
426c2d6c01
2 changed files with 35 additions and 28 deletions
|
|
@ -840,6 +840,7 @@ 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.} =
|
||||||
|
## Creates a constructor for a PRequest object, which will be then yielded.
|
||||||
result = newNimNode(nnkStmtList)
|
result = newNimNode(nnkStmtList)
|
||||||
# TODO: Using gensym here causes segfaults because hasException is not
|
# TODO: Using gensym here causes segfaults because hasException is not
|
||||||
# initialised.
|
# initialised.
|
||||||
|
|
@ -905,33 +906,19 @@ const typeDef =
|
||||||
|
|
||||||
proc transformCallWithArg(call: PNimrodNode,
|
proc transformCallWithArg(call: PNimrodNode,
|
||||||
sym: var PNimrodNode): PNimrodNode {.compiletime.} =
|
sym: var PNimrodNode): PNimrodNode {.compiletime.} =
|
||||||
|
## Transforms an async await call of a user-defined proc into a
|
||||||
|
## ``reqReg`` yield.
|
||||||
result = newNimNode(nnkStmtList)
|
result = newNimNode(nnkStmtList)
|
||||||
|
|
||||||
sym = gensym(nskVar, "argsToPass")
|
sym = gensym(nskVar, "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:
|
|
||||||
case call[1][i].kind
|
|
||||||
of nnkLiterals, nnkIdent:
|
|
||||||
let dotExpr = newDotExpr(sym,
|
|
||||||
newIdentNode("dummy" & $i))
|
|
||||||
result.add newAssignment(dotExpr, call[1][i])
|
|
||||||
else: assert false
|
|
||||||
|
|
||||||
# Add in a call to a pre-generated proc stub so that the compiler verifies
|
# Add in a call to a pre-generated proc stub so that the compiler verifies
|
||||||
# the params for us :)
|
# the params for us :)
|
||||||
# TODO: Make sure this doesn't actually get called, maybe inline it?
|
# TODO: Inline this maybe?
|
||||||
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 newVarStmt(sym, 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
|
||||||
|
|
@ -958,6 +945,11 @@ proc toYieldCall(n: PNimrodNode): seq[PNimrodNode] {.compileTime.} =
|
||||||
result.add yie
|
result.add yie
|
||||||
|
|
||||||
proc transform(n: PNimrodNode): PNimrodNode {.compiletime.} =
|
proc transform(n: PNimrodNode): PNimrodNode {.compiletime.} =
|
||||||
|
## Transforms body.
|
||||||
|
## Specifically it does the following:
|
||||||
|
##
|
||||||
|
## * Looks for 'await' and transforms it into a yield.
|
||||||
|
## * Handles arguments correctly.
|
||||||
result = newNimNode(nnkStmtList)
|
result = newNimNode(nnkStmtList)
|
||||||
expectKind(n, nnkStmtList)
|
expectKind(n, nnkStmtList)
|
||||||
for i in 0 .. n.len-1:
|
for i in 0 .. n.len-1:
|
||||||
|
|
@ -1029,10 +1021,22 @@ proc isDocumentation(n: PNimrodNode): bool {.compiletime.} =
|
||||||
proc createVerificationProc(procName: PNimrodNode,
|
proc createVerificationProc(procName: PNimrodNode,
|
||||||
formalParams: PNimrodNode): PNimrodNode {.compiletime.} =
|
formalParams: PNimrodNode): PNimrodNode {.compiletime.} =
|
||||||
# TODO: Export this stub if our async proc is exported?
|
# TODO: Export this stub if our async proc is exported?
|
||||||
var kids: seq[PNimrodNode] = @[]
|
# Generate list of parameters for the proc. First param is the return type.
|
||||||
for i in 0 .. formalParams.len-1:
|
var params: seq[PNimrodNode] = @[newIdentNode("P$#ArgObject" % $procName.ident)]
|
||||||
kids.add(formalParams[i])
|
for i in 1 .. formalParams.len-1:
|
||||||
result = newProc(procName, kids)
|
params.add(formalParams[i])
|
||||||
|
|
||||||
|
# Generate body. We construct the ArgObject here, this is done so that
|
||||||
|
# default variables of the async proc can be captured.
|
||||||
|
var body = newNimNode(nnkStmtList)
|
||||||
|
body.add newCall("new", newIdentNode("result"))
|
||||||
|
|
||||||
|
for i in 1 .. formalParams.len-1:
|
||||||
|
let dotExpr = newDotExpr(newIdentNode("result"),
|
||||||
|
newIdentNode("dummy" & $i))
|
||||||
|
body.add newAssignment(dotExpr, formalParams[i][0])
|
||||||
|
|
||||||
|
result = newProc(procName, params, body)
|
||||||
|
|
||||||
macro async*(n: stmt): stmt {.immediate.} =
|
macro async*(n: stmt): stmt {.immediate.} =
|
||||||
expectKind(n, nnkProcDef)
|
expectKind(n, nnkProcDef)
|
||||||
|
|
@ -1045,7 +1049,6 @@ macro async*(n: stmt): stmt {.immediate.} =
|
||||||
result[6] = parseStmt("nil")
|
result[6] = parseStmt("nil")
|
||||||
return
|
return
|
||||||
|
|
||||||
#echo("-------------")
|
|
||||||
result = newNimNode(nnkIteratorDef)
|
result = newNimNode(nnkIteratorDef)
|
||||||
for i in 0 .. n.len-1:
|
for i in 0 .. n.len-1:
|
||||||
result.add(copyNimTree(n[i]))
|
result.add(copyNimTree(n[i]))
|
||||||
|
|
@ -1061,18 +1064,20 @@ macro async*(n: stmt): stmt {.immediate.} =
|
||||||
formalParams.add(params)
|
formalParams.add(params)
|
||||||
result[3] = formalParams
|
result[3] = formalParams
|
||||||
|
|
||||||
# Pragma
|
# Closure pragma
|
||||||
result[4].add(newIdentNode(!"closure"))
|
result[4].add(newIdentNode(!"closure"))
|
||||||
|
|
||||||
|
# Body
|
||||||
result[6] = newNimNode(nnkStmtList)
|
result[6] = newNimNode(nnkStmtList)
|
||||||
|
|
||||||
# Declare variables based on the params that the async proc takes.
|
# Declare variables based on the params that the async proc takes.
|
||||||
|
# i.e. extract them from the PRequest object.
|
||||||
if n[3].len > 1:
|
if n[3].len > 1:
|
||||||
let args = declareArgsInBody($n[0].ident, n[3])
|
let args = declareArgsInBody($n[0].ident, n[3])
|
||||||
|
|
||||||
result[6].add(args)
|
result[6].add(args)
|
||||||
|
|
||||||
# Body
|
# Transform body
|
||||||
var body = transform(n[6])
|
var body = transform(n[6])
|
||||||
result[6].add(body)
|
result[6].add(body)
|
||||||
|
|
||||||
|
|
@ -1081,7 +1086,9 @@ macro async*(n: stmt): stmt {.immediate.} =
|
||||||
let procDef = copyNimTree(result)
|
let procDef = copyNimTree(result)
|
||||||
result = newNimNode(nnkStmtList)
|
result = newNimNode(nnkStmtList)
|
||||||
result.add(transformArgs($n[0].ident, n[3]))
|
result.add(transformArgs($n[0].ident, n[3]))
|
||||||
# Generate a proc stub to verify that the user passes the correct params.
|
# Generate a proc to verify that the user passes the correct params.
|
||||||
|
# The proc also constructs the ArgObject, this is so that default params
|
||||||
|
# can be captured into the ArgObject.
|
||||||
result.add createVerificationProc(n[0], n[3])
|
result.add createVerificationProc(n[0], n[3])
|
||||||
|
|
||||||
result.add procDef
|
result.add procDef
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import sockets, asyncio, strutils
|
import sockets, asyncio, strutils
|
||||||
|
|
||||||
proc processRequest(client: PAsyncSocket, test: string, closeSock: bool) {.async.} =
|
proc processRequest(client: PAsyncSocket, test: string, closeSock: bool = true) {.async.} =
|
||||||
assert test == "ahha"
|
assert test == "ahha"
|
||||||
assert client != nil
|
assert client != nil
|
||||||
echo("Test = ", test)
|
echo("Test = ", test)
|
||||||
|
|
@ -25,7 +25,7 @@ proc processServer() {.async.} =
|
||||||
let client: PAsyncSocket = await(accept(sock))
|
let client: PAsyncSocket = await(accept(sock))
|
||||||
assert client != nil
|
assert client != nil
|
||||||
await processRequest(client, "ahha", false)
|
await processRequest(client, "ahha", false)
|
||||||
await processRequest(client, "ahha", true)
|
await processRequest(client, "ahha")
|
||||||
|
|
||||||
var disp = newDispatcher(false)
|
var disp = newDispatcher(false)
|
||||||
disp.register(processServer, nil)
|
disp.register(processServer, nil)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue