diff --git a/lib/pure/asyncio.nim b/lib/pure/asyncio.nim index e7e931bf5..473d46a76 100644 --- a/lib/pure/asyncio.nim +++ b/lib/pure/asyncio.nim @@ -907,6 +907,14 @@ proc transformCallWithArg(call: PNimrodNode): PNimrodNode {.compiletime.} = 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 + # the params for us :) + # TODO: Make sure this doesn't actually get called, maybe inline it? + var args: seq[PNimrodNode] = @[] + for i in 1 .. call[1].len-1: + args.add(call[1][i]) + result.add newCall(call[1][0], args) + proc toYieldCall(n: PNimrodNode): seq[PNimrodNode] {.compileTime.} = ## Transforms a call/command if $n[0].ident != "await": error "'await' expected" @@ -994,6 +1002,14 @@ proc isDocumentation(n: PNimrodNode): bool {.compiletime.} = if n[6][i].kind != nnkCommentStmt: return false +proc createVerificationProc(procName: PNimrodNode, + formalParams: PNimrodNode): PNimrodNode {.compiletime.} = + # TODO: Export this stub if our async proc is exported? + var kids: seq[PNimrodNode] = @[] + for i in 0 .. formalParams.len-1: + kids.add(formalParams[i]) + result = newProc(procName, kids) + macro async*(n: stmt): stmt {.immediate.} = expectKind(n, nnkProcDef) #echo(treeRepr(n)) @@ -1041,6 +1057,9 @@ macro async*(n: stmt): stmt {.immediate.} = let procDef = copyNimTree(result) result = newNimNode(nnkStmtList) result.add(transformArgs($n[0].ident, n[3])) + # Generate a proc stub to verify that the user passes the correct params. + result.add createVerificationProc(n[0], n[3]) + result.add procDef #echo treeRepr(result) diff --git a/tests/compile/tasyncitermacro.nim b/tests/compile/tasyncitermacro.nim index 2c6d22b5a..b20bb5ea4 100644 --- a/tests/compile/tasyncitermacro.nim +++ b/tests/compile/tasyncitermacro.nim @@ -1,4 +1,5 @@ import sockets, asyncio, strutils + proc processRequest(client: PAsyncSocket, test: string) {.async.} = assert test == "ahha" assert client != nil diff --git a/tests/reject/tasyncmacroinvalidargs.nim b/tests/reject/tasyncmacroinvalidargs.nim new file mode 100644 index 000000000..9a4d02627 --- /dev/null +++ b/tests/reject/tasyncmacroinvalidargs.nim @@ -0,0 +1,32 @@ +discard """ + msg: "type mismatch: got (int literal(234)) but expected 'string'" +""" +import sockets, asyncio, strutils + +proc processRequest(client: PAsyncSocket, test: string) {.async.} = + assert test == "ahha" + assert client != nil + echo("Test = ", test) + let line = await(readLine(client)) + echo("Read: ", line) + + await send(client, "Goodbye.\c\L") + client.close() + +proc processServer() {.async.} = + var sock = AsyncSocket() + + # blocks: + sock.bindAddr(TPort(6667)) + sock.listen() + + # Accept loop + while true: + let client: PAsyncSocket = await(accept(sock)) + assert client != nil + await processRequest(client, 234) + +var disp = newDispatcher(false) +disp.register(processServer, nil) +while true: + discard disp.poll()