Merge branch 'bigbreak' of https://github.com/Araq/Nimrod into bigbreak
This commit is contained in:
commit
758d8e11d9
17 changed files with 153 additions and 97 deletions
|
|
@ -796,6 +796,7 @@ else:
|
|||
else:
|
||||
# FD no longer a part of the selector. Likely been closed
|
||||
# (e.g. socket disconnected).
|
||||
discard
|
||||
|
||||
processTimers(p)
|
||||
|
||||
|
|
@ -972,29 +973,50 @@ template createCb*(retFutureSym, iteratorNameSym,
|
|||
cb()
|
||||
#{.pop.}
|
||||
proc generateExceptionCheck(futSym,
|
||||
exceptBranch, rootReceiver, fromNode: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
if exceptBranch == nil:
|
||||
tryStmt, rootReceiver, fromNode: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
if tryStmt.kind == nnkNilLit:
|
||||
result = rootReceiver
|
||||
else:
|
||||
if exceptBranch[0].kind == nnkStmtList:
|
||||
result = newIfStmt(
|
||||
(newDotExpr(futSym, newIdentNode("failed")),
|
||||
exceptBranch[0]
|
||||
)
|
||||
)
|
||||
else:
|
||||
expectKind(exceptBranch[1], nnkStmtList)
|
||||
result = newIfStmt(
|
||||
(newDotExpr(futSym, newIdentNode("failed")),
|
||||
newIfStmt(
|
||||
(infix(newDotExpr(futSym, newIdentNode("error")), "of", exceptBranch[0]),
|
||||
exceptBranch[1])
|
||||
)
|
||||
)
|
||||
)
|
||||
var exceptionChecks: seq[tuple[cond, body: PNimrodNode]] = @[]
|
||||
let errorNode = newDotExpr(futSym, newIdentNode("error"))
|
||||
for i in 1 .. <tryStmt.len:
|
||||
let exceptBranch = tryStmt[i]
|
||||
if exceptBranch[0].kind == nnkStmtList:
|
||||
exceptionChecks.add((newIdentNode("true"), exceptBranch[0]))
|
||||
else:
|
||||
var exceptIdentCount = 0
|
||||
var ifCond: PNimrodNode
|
||||
for i in 0 .. <exceptBranch.len:
|
||||
let child = exceptBranch[i]
|
||||
if child.kind == nnkIdent:
|
||||
let cond = infix(errorNode, "of", child)
|
||||
if exceptIdentCount == 0:
|
||||
ifCond = cond
|
||||
else:
|
||||
ifCond = infix(ifCond, "or", cond)
|
||||
else:
|
||||
break
|
||||
exceptIdentCount.inc
|
||||
|
||||
expectKind(exceptBranch[exceptIdentCount], nnkStmtList)
|
||||
exceptionChecks.add((ifCond, exceptBranch[exceptIdentCount]))
|
||||
# -> -> else: raise futSym.error
|
||||
exceptionChecks.add((newIdentNode("true"),
|
||||
newNimNode(nnkRaiseStmt).add(errorNode)))
|
||||
# Read the future if there is no error.
|
||||
# -> else: futSym.read
|
||||
let elseNode = newNimNode(nnkElse, fromNode)
|
||||
elseNode.add newNimNode(nnkStmtList, fromNode)
|
||||
elseNode[0].add rootReceiver
|
||||
|
||||
let ifBody = newStmtList()
|
||||
ifBody.add newCall(newIdentNode("setCurrentException"), errorNode)
|
||||
ifBody.add newIfStmt(exceptionChecks)
|
||||
ifBody.add newCall(newIdentNode("setCurrentException"), newNilLit())
|
||||
|
||||
result = newIfStmt(
|
||||
(newDotExpr(futSym, newIdentNode("failed")), ifBody)
|
||||
)
|
||||
result.add elseNode
|
||||
|
||||
template createVar(result: var PNimrodNode, futSymName: string,
|
||||
|
|
@ -1006,11 +1028,11 @@ template createVar(result: var PNimrodNode, futSymName: string,
|
|||
result.add newVarStmt(futSym, asyncProc) # -> var future<x> = y
|
||||
result.add newNimNode(nnkYieldStmt, fromNode).add(futSym) # -> yield future<x>
|
||||
valueReceiver = newDotExpr(futSym, newIdentNode("read")) # -> future<x>.read
|
||||
result.add generateExceptionCheck(futSym, exceptBranch, rootReceiver, fromNode)
|
||||
result.add generateExceptionCheck(futSym, tryStmt, rootReceiver, fromNode)
|
||||
|
||||
proc processBody(node, retFutureSym: PNimrodNode,
|
||||
subTypeIsVoid: bool,
|
||||
exceptBranch: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
tryStmt: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
#echo(node.treeRepr)
|
||||
result = node
|
||||
case node.kind
|
||||
|
|
@ -1024,7 +1046,7 @@ proc processBody(node, retFutureSym: PNimrodNode,
|
|||
result.add newCall(newIdentNode("complete"), retFutureSym)
|
||||
else:
|
||||
result.add newCall(newIdentNode("complete"), retFutureSym,
|
||||
node[0].processBody(retFutureSym, subTypeIsVoid, exceptBranch))
|
||||
node[0].processBody(retFutureSym, subTypeIsVoid, tryStmt))
|
||||
|
||||
result.add newNimNode(nnkReturnStmt, node).add(newNilLit())
|
||||
return # Don't process the children of this return stmt
|
||||
|
|
@ -1079,7 +1101,7 @@ proc processBody(node, retFutureSym: PNimrodNode,
|
|||
res: PNimrodNode): bool {.compileTime.} =
|
||||
result = false
|
||||
while i < n[0].len:
|
||||
var processed = processBody(n[0][i], retFutureSym, subTypeIsVoid, n[1])
|
||||
var processed = processBody(n[0][i], retFutureSym, subTypeIsVoid, n)
|
||||
if processed.kind != n[0][i].kind or processed.len != n[0][i].len:
|
||||
expectKind(processed, nnkStmtList)
|
||||
expectKind(processed[2][1], nnkElse)
|
||||
|
|
@ -1099,7 +1121,7 @@ proc processBody(node, retFutureSym: PNimrodNode,
|
|||
else: discard
|
||||
|
||||
for i in 0 .. <result.len:
|
||||
result[i] = processBody(result[i], retFutureSym, subTypeIsVoid, exceptBranch)
|
||||
result[i] = processBody(result[i], retFutureSym, subTypeIsVoid, tryStmt)
|
||||
|
||||
proc getName(node: PNimrodNode): string {.compileTime.} =
|
||||
case node.kind
|
||||
|
|
@ -1193,7 +1215,7 @@ macro async*(prc: stmt): stmt {.immediate.} =
|
|||
result[6] = outerProcBody
|
||||
|
||||
#echo(treeRepr(result))
|
||||
#if prc[0].getName == "getFile":
|
||||
#if prc[0].getName == "catch":
|
||||
# echo(toStrLit(result))
|
||||
|
||||
proc recvLine*(socket: TAsyncFD): Future[string] {.async.} =
|
||||
|
|
@ -1209,6 +1231,8 @@ proc recvLine*(socket: TAsyncFD): Future[string] {.async.} =
|
|||
## If the socket is disconnected in the middle of a line (before ``\r\L``
|
||||
## is read) then line will be set to ``""``.
|
||||
## The partial line **will be lost**.
|
||||
##
|
||||
## **Warning**: This assumes that lines are delimited by ``\r\l``.
|
||||
|
||||
template addNLIfEmpty(): stmt =
|
||||
if result.len == 0:
|
||||
|
|
@ -1221,9 +1245,8 @@ proc recvLine*(socket: TAsyncFD): Future[string] {.async.} =
|
|||
if c.len == 0:
|
||||
return ""
|
||||
if c == "\r":
|
||||
c = await recv(socket, 1, {SocketFlag.SafeDisconn, SocketFlag.Peek})
|
||||
if c.len > 0 and c == "\L":
|
||||
discard await recv(socket, 1)
|
||||
c = await recv(socket, 1)
|
||||
assert c == "\l"
|
||||
addNLIfEmpty()
|
||||
return
|
||||
elif c == "\L":
|
||||
|
|
|
|||
|
|
@ -34,26 +34,7 @@ type
|
|||
fd: TAsyncFd
|
||||
offset: int64
|
||||
|
||||
# TODO: These will be nil in other threads?
|
||||
var
|
||||
asyncStdin* {.threadvar.}: AsyncFile ## Asynchronous stdin handle
|
||||
asyncStdout* {.threadvar.}: AsyncFile ## Asynchronous stdout handle
|
||||
asyncStderr* {.threadvar.}: AsyncFile ## Asynchronous stderr handle
|
||||
|
||||
when defined(windows):
|
||||
asyncStdin = AsyncFile(
|
||||
fd: getStdHandle(STD_INPUT_HANDLE).TAsyncFd,
|
||||
offset: 0
|
||||
)
|
||||
asyncStdout = AsyncFile(
|
||||
fd: getStdHandle(STD_OUTPUT_HANDLE).TAsyncFd,
|
||||
offset: 0
|
||||
)
|
||||
asyncStderr = AsyncFile(
|
||||
fd: getStdHandle(STD_ERROR_HANDLE).TAsyncFd,
|
||||
offset: 0
|
||||
)
|
||||
|
||||
proc getDesiredAccess(mode: TFileMode): int32 =
|
||||
case mode
|
||||
of fmRead:
|
||||
|
|
@ -73,19 +54,6 @@ when defined(windows):
|
|||
else:
|
||||
CREATE_NEW
|
||||
else:
|
||||
asyncStdin = AsyncFile(
|
||||
fd: STDIN_FILENO.TAsyncFd,
|
||||
offset: 0
|
||||
)
|
||||
asyncStdout = AsyncFile(
|
||||
fd: STDOUT_FILENO.TAsyncFd,
|
||||
offset: 0
|
||||
)
|
||||
asyncStderr = AsyncFile(
|
||||
fd: STDERR_FILENO.TAsyncFd,
|
||||
offset: 0
|
||||
)
|
||||
|
||||
proc getPosixFlags(mode: TFileMode): cint =
|
||||
case mode
|
||||
of fmRead:
|
||||
|
|
@ -100,7 +68,7 @@ else:
|
|||
result = O_RDWR
|
||||
result = result or O_NONBLOCK
|
||||
|
||||
proc getFileSize*(f: AsyncFile): int64 =
|
||||
proc getFileSize(f: AsyncFile): int64 =
|
||||
## Retrieves the specified file's size.
|
||||
when defined(windows):
|
||||
var high: DWord
|
||||
|
|
|
|||
|
|
@ -183,6 +183,7 @@ proc processClient(client: PAsyncSocket, address: string,
|
|||
# header states otherwise.
|
||||
# In HTTP 1.0 we assume that the connection should not be persistent.
|
||||
# Unless the connection header states otherwise.
|
||||
discard
|
||||
else:
|
||||
request.client.close()
|
||||
break
|
||||
|
|
|
|||
|
|
@ -247,6 +247,7 @@ proc asyncSockHandleWrite(h: RootRef) =
|
|||
# Apparently the socket cannot be written to. Even though select
|
||||
# just told us that it can be... This used to be an assert. Just
|
||||
# do nothing instead.
|
||||
discard
|
||||
elif bytesSent != sock.sendBuffer.len:
|
||||
sock.sendBuffer = sock.sendBuffer[bytesSent .. -1]
|
||||
elif bytesSent == sock.sendBuffer.len:
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
import strutils, os, strtabs, cookies
|
||||
|
||||
proc URLencode*(s: string): string =
|
||||
proc urlEncode*(s: string): string =
|
||||
## Encodes a value to be HTTP safe: This means that characters in the set
|
||||
## ``{'A'..'Z', 'a'..'z', '0'..'9', '_'}`` are carried over to the result,
|
||||
## a space is converted to ``'+'`` and every other character is encoded as
|
||||
|
|
@ -52,7 +52,7 @@ proc handleHexChar(c: char, x: var int) {.inline.} =
|
|||
of 'A'..'F': x = (x shl 4) or (ord(c) - ord('A') + 10)
|
||||
else: assert(false)
|
||||
|
||||
proc URLdecode*(s: string): string =
|
||||
proc urlDecode*(s: string): string =
|
||||
## Decodes a value from its HTTP representation: This means that a ``'+'``
|
||||
## is converted to a space, ``'%xx'`` (where ``xx`` denotes a hexadecimal
|
||||
## value) is converted to the character with ordinal number ``xx``, and
|
||||
|
|
@ -82,7 +82,7 @@ proc addXmlChar(dest: var string, c: char) {.inline.} =
|
|||
of '\"': add(dest, """)
|
||||
else: add(dest, c)
|
||||
|
||||
proc XMLencode*(s: string): string =
|
||||
proc xmlEncode*(s: string): string =
|
||||
## Encodes a value to be XML safe:
|
||||
## * ``"`` is replaced by ``"``
|
||||
## * ``<`` is replaced by ``<``
|
||||
|
|
@ -99,7 +99,8 @@ type
|
|||
methodPost, ## query uses the POST method
|
||||
methodGet ## query uses the GET method
|
||||
|
||||
{.deprecated: [TRequestMethod: RequestMethod, ECgi: CgiError].}
|
||||
{.deprecated: [TRequestMethod: RequestMethod, ECgi: CgiError,
|
||||
URLencode: urlEncode, XMLencode: xmlEncode, URLdecode: urlDecode].}
|
||||
|
||||
proc cgiError*(msg: string) {.noreturn.} =
|
||||
## raises an ECgi exception with message `msg`.
|
||||
|
|
@ -331,9 +332,9 @@ proc setTestData*(keysvalues: varargs[string]) =
|
|||
var i = 0
|
||||
var query = ""
|
||||
while i < keysvalues.len:
|
||||
add(query, URLencode(keysvalues[i]))
|
||||
add(query, urlEncode(keysvalues[i]))
|
||||
add(query, '=')
|
||||
add(query, URLencode(keysvalues[i+1]))
|
||||
add(query, urlEncode(keysvalues[i+1]))
|
||||
add(query, '&')
|
||||
inc(i, 2)
|
||||
putEnv("QUERY_STRING", query)
|
||||
|
|
|
|||
|
|
@ -2631,6 +2631,12 @@ when not defined(JS): #and not defined(NimrodVM):
|
|||
excHandler.hasRaiseAction = true
|
||||
excHandler.raiseAction = action
|
||||
|
||||
proc setCurrentException*(exc: ref Exception) {.inline, gcsafe.} =
|
||||
## sets the current exception.
|
||||
##
|
||||
## **Warning**: Only use this if you know what you are doing.
|
||||
currException = exc
|
||||
|
||||
{.push stack_trace: off, profiler:off.}
|
||||
when defined(endb) and not defined(NimrodVM):
|
||||
include "system/debugger"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue