Merge branch 'devel' of gh:/Araq/Nimrod into devel

This commit is contained in:
Zahary Karadjov
2014-02-17 00:48:10 +02:00
33 changed files with 677 additions and 275 deletions

View File

@@ -540,7 +540,7 @@ proc typeAtom(p: var TParser): PNode =
if p.tok.s == "unsigned":
isUnsigned = true
elif p.tok.s == "signed" or p.tok.s == "int":
nil
discard
else:
add(x, p.tok.s)
getTok(p, nil)
@@ -746,7 +746,7 @@ proc directDeclarator(p: var TParser, a: PNode, ident: ptr PNode): PNode =
result = declarator(p, a, ident)
eat(p, pxParRi, result)
else:
nil
discard
return parseTypeSuffix(p, a)
proc declarator(p: var TParser, a: PNode, ident: ptr PNode): PNode =
@@ -1165,7 +1165,7 @@ proc enumSpecifier(p: var TParser): PNode =
proc setBaseFlags(n: PNode, base: TNumericalBase) =
case base
of base10: nil
of base10: discard
of base2: incl(n.flags, nfBase2)
of base8: incl(n.flags, nfBase8)
of base16: incl(n.flags, nfBase16)
@@ -1686,7 +1686,7 @@ proc switchStatement(p: var TParser): PNode =
break
of "case", "default":
break
else: nil
else: discard
addSon(result, statement(p))
if sonsLen(result) == 0:
# translate empty statement list to Nimrod's ``nil`` statement

View File

@@ -103,7 +103,7 @@ proc parseDefBody(p: var TParser, m: var TMacro, params: seq[string]) =
m.body.add(tok)
of pxDirConc:
# just ignore this token: this implements token merging correctly
nil
discard
else:
m.body.add(p.tok)
# we do not want macro expansion here:
@@ -166,7 +166,7 @@ proc parseStmtList(p: var TParser): PNode =
of pxDirectiveParLe, pxDirective:
case p.tok.s
of "else", "endif", "elif": break
else: nil
else: discard
addSon(result, statement(p))
proc eatEndif(p: var TParser) =

View File

@@ -65,6 +65,7 @@ proc startBlock(p: BProc, start: TFormatStr = "{$n",
setLen(p.blocks, result + 1)
p.blocks[result].id = p.labels
p.blocks[result].nestedTryStmts = p.nestedTryStmts.len.int16
p.blocks[result].nestedExceptStmts = p.inExceptBlock.int16
proc assignLabel(b: var TBlock): PRope {.inline.} =
b.label = con("LA", b.id.toRope)
@@ -260,14 +261,22 @@ proc genIf(p: BProc, n: PNode, d: var TLoc) =
else: internalError(n.info, "genIf()")
if sonsLen(n) > 1: fixLabel(p, lend)
proc blockLeaveActions(p: BProc, howMany: int) =
var L = p.nestedTryStmts.len
proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) =
# This is called by return and break stmts.
# When jumping out of try/except/finally stmts,
# we need to pop safe points from try statements,
# execute finally-stmts, and pop exceptions
# from except stmts
let L = p.nestedTryStmts.len
# danger of endless recursion! we workaround this here by a temp stack
var stack: seq[PNode]
newSeq(stack, howMany)
for i in countup(1, howMany):
newSeq(stack, howManyTrys)
for i in countup(1, howManyTrys):
stack[i-1] = p.nestedTryStmts[L-i]
setLen(p.nestedTryStmts, L-howMany)
setLen(p.nestedTryStmts, L-howManyTrys)
var alreadyPoppedCnt = p.inExceptBlock
for tryStmt in items(stack):
@@ -276,21 +285,26 @@ proc blockLeaveActions(p: BProc, howMany: int) =
dec alreadyPoppedCnt
else:
linefmt(p, cpsStmts, "#popSafePoint();$n")
# Find finally-stmts for this try-stmt
# and generate a copy of the finally stmts here
var finallyStmt = lastSon(tryStmt)
if finallyStmt.kind == nkFinally:
genStmts(p, finallyStmt.sons[0])
# push old elements again:
for i in countdown(howMany-1, 0):
for i in countdown(howManyTrys-1, 0):
p.nestedTryStmts.add(stack[i])
if gCmd != cmdCompileToCpp:
for i in countdown(p.inExceptBlock-1, 0):
# Pop exceptions that was handled by the
# except-blocks we are in
for i in countdown(howManyExcepts-1, 0):
linefmt(p, cpsStmts, "#popCurrentException();$n")
proc genReturnStmt(p: BProc, t: PNode) =
p.beforeRetNeeded = true
genLineDir(p, t)
if (t.sons[0].kind != nkEmpty): genStmts(p, t.sons[0])
blockLeaveActions(p, min(1, p.nestedTryStmts.len))
blockLeaveActions(p, min(1, p.nestedTryStmts.len), p.inExceptBlock)
lineFF(p, cpsStmts, "goto BeforeRet;$n", "br label %BeforeRet$n", [])
proc genComputedGoto(p: BProc; n: PNode) =
@@ -450,7 +464,9 @@ proc genBreakStmt(p: BProc, t: PNode) =
if idx < 0 or not p.blocks[idx].isLoop:
internalError(t.info, "no loop to break")
let label = assignLabel(p.blocks[idx])
blockLeaveActions(p, p.nestedTryStmts.len - p.blocks[idx].nestedTryStmts)
blockLeaveActions(p,
p.nestedTryStmts.len - p.blocks[idx].nestedTryStmts,
p.inExceptBlock - p.blocks[idx].nestedExceptStmts)
genLineDir(p, t)
lineF(p, cpsStmts, "goto $1;$n", [label])

View File

@@ -58,6 +58,7 @@ type
sections*: TCProcSections # the code beloging
isLoop*: bool # whether block is a loop
nestedTryStmts*: int16 # how many try statements is it nested into
nestedExceptStmts*: int16 # how many except statements is it nested into
frameLen*: int16
TCProc{.final.} = object # represents C proc that is currently generated

View File

@@ -342,7 +342,7 @@ proc getSymbol(L: var TLexer, tok: var TToken) =
h = h +% ord(c)
h = h +% h shl 10
h = h xor (h shr 6)
of '_': nil
of '_': discard
else: break
inc(pos)
h = h +% h shl 3

View File

@@ -335,7 +335,7 @@ proc exprColonEqExprList(p: var TParser, kind, elemKind: TNodeKind,
proc setBaseFlags(n: PNode, base: TNumericalBase) =
case base
of base10: nil
of base10: discard
of base2: incl(n.flags, nfBase2)
of base8: incl(n.flags, nfBase8)
of base16: incl(n.flags, nfBase16)
@@ -466,7 +466,7 @@ proc lowestExprAux(p: var TParser, v: var PNode, limit: int): TTokKind =
eat(p, pxCurlyDirRi)
opNode.ident = getIdent("&")
else:
nil
discard
of pxMinus:
if p.tok.xkind == pxPer:
getTok(p)
@@ -477,7 +477,7 @@ proc lowestExprAux(p: var TParser, v: var PNode, limit: int): TTokKind =
of pxNeq:
opNode.ident = getIdent("!=")
else:
nil
discard
skipCom(p, opNode) # read sub-expression with higher priority
nextop = lowestExprAux(p, v2, opPred)
addSon(node, opNode)
@@ -505,7 +505,7 @@ proc fixExpr(n: PNode): PNode =
(n.sons[2].kind in {nkCharLit, nkStrLit}):
n.sons[0].ident = getIdent("&") # fix operator
else:
nil
discard
if not (n.kind in {nkEmpty..nkNilLit}):
for i in countup(0, sonsLen(n) - 1): result.sons[i] = fixExpr(n.sons[i])
@@ -603,7 +603,7 @@ proc parseStmtList(p: var TParser): PNode =
of pxCurlyDirLe, pxStarDirLe:
if not isHandledDirective(p): break
else:
nil
discard
addSon(result, parseStmt(p))
if sonsLen(result) == 1: result = result.sons[0]
@@ -732,7 +732,7 @@ proc parseRepeat(p: var TParser): PNode =
addSon(b, c)
addSon(a, b)
if b.sons[0].kind == nkIdent and b.sons[0].ident.id == getIdent("false").id:
nil
discard
else:
addSon(s, a)
addSon(result, s)
@@ -840,7 +840,7 @@ proc parseParam(p: var TParser): PNode =
getTok(p)
v = newNodeP(nkVarTy, p)
else:
nil
discard
while true:
case p.tok.xkind
of pxSymbol: a = createIdentNodeP(p.tok.ident, p)
@@ -1133,7 +1133,7 @@ proc parseRecordPart(p: var TParser): PNode =
proc exSymbol(n: var PNode) =
case n.kind
of nkPostfix:
nil
discard
of nkPragmaExpr:
exSymbol(n.sons[0])
of nkIdent, nkAccQuoted:
@@ -1154,7 +1154,7 @@ proc fixRecordDef(n: var PNode) =
for i in countup(0, sonsLen(n) - 1): fixRecordDef(n.sons[i])
of nkIdentDefs:
for i in countup(0, sonsLen(n) - 3): exSymbol(n.sons[i])
of nkNilLit, nkEmpty: nil
of nkNilLit, nkEmpty: discard
else: internalError(n.info, "fixRecordDef(): " & $n.kind)
proc addPragmaToIdent(ident: var PNode, pragma: PNode) =
@@ -1191,7 +1191,7 @@ proc parseRecordBody(p: var TParser, result, definition: PNode) =
if definition != nil: addPragmaToIdent(definition.sons[0], parseCommand(p))
else: internalError(result.info, "anonymous record is not supported")
else:
nil
discard
opt(p, pxSemicolon)
skipCom(p, result)
@@ -1399,7 +1399,7 @@ proc fixVarSection(p: var TParser, counter: PNode) =
proc exSymbols(n: PNode) =
case n.kind
of nkEmpty..nkNilLit: nil
of nkEmpty..nkNilLit: discard
of nkProcDef..nkIteratorDef: exSymbol(n.sons[namePos])
of nkWhenStmt, nkStmtList:
for i in countup(0, sonsLen(n) - 1): exSymbols(n.sons[i])
@@ -1410,7 +1410,7 @@ proc exSymbols(n: PNode) =
exSymbol(n.sons[i].sons[0])
if n.sons[i].sons[2].kind == nkObjectTy:
fixRecordDef(n.sons[i].sons[2])
else: nil
else: discard
proc parseBegin(p: var TParser, result: PNode) =
getTok(p)

View File

@@ -36,7 +36,7 @@ block mainLoop:
case x.kind
of xmlEof: break mainLoop
of xmlElementClose: break
else: nil
else: discard
x.next() # skip ``xmlElementClose``
# now we have the description for the ``a`` element
var desc = ""

View File

@@ -7,7 +7,7 @@
# distribution, for details about the copyright.
#
import os, oids, tables, strutils
import os, oids, tables, strutils, macros
import winlean
@@ -23,14 +23,13 @@ import sockets2, net
# -- Futures
type
PFutureVoid* = ref object of PObject
cbVoid: proc () {.closure.}
PFutureBase* = ref object of PObject
cb: proc () {.closure.}
finished: bool
PFuture*[T] = ref object of PFutureVoid
PFuture*[T] = ref object of PFutureBase
value: T
error: ref EBase
cb: proc (future: PFuture[T]) {.closure.}
proc newFuture*[T](): PFuture[T] =
## Creates a new future.
@@ -39,42 +38,38 @@ proc newFuture*[T](): PFuture[T] =
proc complete*[T](future: PFuture[T], val: T) =
## Completes ``future`` with value ``val``.
assert(not future.finished)
assert(not future.finished, "Future already finished, cannot finish twice.")
assert(future.error == nil)
future.value = val
future.finished = true
if future.cb != nil:
future.cb(future)
if future.cbVoid != nil:
future.cbVoid()
future.cb()
proc fail*[T](future: PFuture[T], error: ref EBase) =
## Completes ``future`` with ``error``.
assert(not future.finished)
assert(not future.finished, "Future already finished, cannot finish twice.")
future.finished = true
future.error = error
if future.cb != nil:
future.cb(future)
future.cb()
proc `callback=`*(future: PFutureBase, cb: proc () {.closure.}) =
## Sets the callback proc to be called when the future completes.
##
## If future has already completed then ``cb`` will be called immediately.
##
## **Note**: You most likely want the other ``callback`` setter which
## passes ``future`` as a param to the callback.
future.cb = cb
if future.finished:
future.cb()
proc `callback=`*[T](future: PFuture[T],
cb: proc (future: PFuture[T]) {.closure.}) =
## Sets the callback proc to be called when the future completes.
##
## If future has already completed then ``cb`` will be called immediately.
future.cb = cb
if future.finished:
future.cb(future)
proc `callbackVoid=`*(future: PFutureVoid, cb: proc () {.closure.}) =
## Sets the **void** callback proc to be called when the future completes.
##
## If future has already completed then ``cb`` will be called immediately.
##
## **Note**: This is used for the ``await`` functionality, you most likely
## want to use ``callback``.
future.cbVoid = cb
if future.finished:
future.cbVoid()
future.callback = proc () = cb(future)
proc read*[T](future: PFuture[T]): T =
## Retrieves the value of ``future``. Future must be finished otherwise
@@ -104,10 +99,12 @@ when defined(windows):
TCompletionData* = object
sock: TSocketHandle
cb: proc (sock: TSocketHandle, errcode: TOSErrorCode) {.closure.}
cb: proc (sock: TSocketHandle, bytesTransferred: DWORD,
errcode: TOSErrorCode) {.closure.}
PDispatcher* = ref object
ioPort: THandle
hasHandles: bool
TCustomOverlapped = object
Internal*: DWORD
@@ -129,9 +126,13 @@ when defined(windows):
if CreateIOCompletionPort(sock.THandle, p.ioPort,
cast[TCompletionKey](sock), 1) == 0:
OSError(OSLastError())
p.hasHandles = true
proc poll*(p: PDispatcher, timeout = 500) =
## Waits for completion events and processes them.
if not p.hasHandles:
raise newException(EInvalidValue, "No handles registered in dispatcher.")
let llTimeout =
if timeout == -1: winlean.INFINITE
else: timeout.int32
@@ -145,16 +146,19 @@ when defined(windows):
# TODO: http://www.serverframework.com/handling-multiple-pending-socket-read-and-write-operations.html
var customOverlapped = cast[PCustomOverlapped](lpOverlapped)
if res:
# This is useful for ensuring the reliability of the overlapped struct.
assert customOverlapped.data.sock == lpCompletionKey.TSocketHandle
customOverlapped.data.cb(customOverlapped.data.sock, TOSErrorCode(-1))
customOverlapped.data.cb(customOverlapped.data.sock,
lpNumberOfBytesTransferred, TOSErrorCode(-1))
dealloc(customOverlapped)
else:
let errCode = OSLastError()
if lpOverlapped != nil:
assert customOverlapped.data.sock == lpCompletionKey.TSocketHandle
customOverlapped.data.cb(customOverlapped.data.sock,
lpNumberOfBytesTransferred, errCode)
dealloc(customOverlapped)
customOverlapped.data.cb(customOverlapped.data.sock, errCode)
else:
if errCode.int32 == WAIT_TIMEOUT:
# Timed out
@@ -252,11 +256,12 @@ when defined(windows):
# http://blogs.msdn.com/b/oldnewthing/archive/2011/02/02/10123392.aspx
var ol = cast[PCustomOverlapped](alloc0(sizeof(TCustomOverlapped)))
ol.data = TCompletionData(sock: socket, cb:
proc (sock: TSocketHandle, errcode: TOSErrorCode) =
if errcode == TOSErrorCode(-1):
retFuture.complete(0)
else:
retFuture.fail(newException(EOS, osErrorMsg(errcode)))
proc (sock: TSocketHandle, bytesCount: DWord, errcode: TOSErrorCode) =
if not retFuture.finished:
if errcode == TOSErrorCode(-1):
retFuture.complete(0)
else:
retFuture.fail(newException(EOS, osErrorMsg(errcode)))
)
var ret = connectEx(socket, it.ai_addr, sizeof(TSockAddrIn).cint,
@@ -265,7 +270,9 @@ when defined(windows):
# Request to connect completed immediately.
success = true
retFuture.complete(0)
dealloc(ol)
# We don't deallocate ``ol`` here because even though this completed
# immediately poll will still be notified about its completion and it will
# free ``ol``.
break
else:
lastError = OSLastError()
@@ -283,7 +290,8 @@ when defined(windows):
retFuture.fail(newException(EOS, osErrorMsg(lastError)))
return retFuture
proc recv*(p: PDispatcher, socket: TSocketHandle, size: int): PFuture[string] =
proc recv*(p: PDispatcher, socket: TSocketHandle, size: int,
flags: int = 0): PFuture[string] =
## Reads ``size`` bytes from ``socket``. Returned future will complete once
## all of the requested data is read.
@@ -293,31 +301,50 @@ when defined(windows):
dataBuf.buf = newString(size)
dataBuf.len = size
var bytesReceived, flags: DWord
var bytesReceived: DWord
var flagsio = flags.dword
var ol = cast[PCustomOverlapped](alloc0(sizeof(TCustomOverlapped)))
ol.data = TCompletionData(sock: socket, cb:
proc (sock: TSocketHandle, errcode: TOSErrorCode) =
if errcode == TOSErrorCode(-1):
var data = newString(size)
copyMem(addr data[0], addr dataBuf.buf[0], size)
retFuture.complete($data)
else:
retFuture.fail(newException(EOS, osErrorMsg(errcode)))
proc (sock: TSocketHandle, bytesCount: DWord, errcode: TOSErrorCode) =
if not retFuture.finished:
if errcode == TOSErrorCode(-1):
if bytesCount == 0 and dataBuf.buf[0] == '\0':
retFuture.complete("")
else:
var data = newString(size)
copyMem(addr data[0], addr dataBuf.buf[0], size)
retFuture.complete($data)
else:
retFuture.fail(newException(EOS, osErrorMsg(errcode)))
)
let ret = WSARecv(socket, addr dataBuf, 1, addr bytesReceived,
addr flags, cast[POverlapped](ol), nil)
addr flagsio, cast[POverlapped](ol), nil)
if ret == -1:
let err = OSLastError()
if err.int32 != ERROR_IO_PENDING:
retFuture.fail(newException(EOS, osErrorMsg(err)))
dealloc(ol)
elif ret == 0 and bytesReceived == 0 and dataBuf.buf[0] == '\0':
# We have to ensure that the buffer is empty because WSARecv will tell
# us immediatelly when it was disconnected, even when there is still
# data in the buffer.
# We want to give the user as much data as we can. So we only return
# the empty string (which signals a disconnection) when there is
# nothing left to read.
retFuture.complete("")
# TODO: "For message-oriented sockets, where a zero byte message is often
# allowable, a failure with an error code of WSAEDISCON is used to
# indicate graceful closure."
# ~ http://msdn.microsoft.com/en-us/library/ms741688%28v=vs.85%29.aspx
else:
# Request to read completed immediately.
var data = newString(size)
copyMem(addr data[0], addr dataBuf.buf[0], size)
retFuture.complete($data)
dealloc(ol)
# We don't deallocate ``ol`` here because even though this completed
# immediately poll will still be notified about its completion and it will
# free ``ol``.
return retFuture
proc send*(p: PDispatcher, socket: TSocketHandle, data: string): PFuture[int] =
@@ -332,11 +359,12 @@ when defined(windows):
var bytesReceived, flags: DWord
var ol = cast[PCustomOverlapped](alloc0(sizeof(TCustomOverlapped)))
ol.data = TCompletionData(sock: socket, cb:
proc (sock: TSocketHandle, errcode: TOSErrorCode) =
if errcode == TOSErrorCode(-1):
retFuture.complete(0)
else:
retFuture.fail(newException(EOS, osErrorMsg(errcode)))
proc (sock: TSocketHandle, bytesCount: DWord, errcode: TOSErrorCode) =
if not retFuture.finished:
if errcode == TOSErrorCode(-1):
retFuture.complete(0)
else:
retFuture.fail(newException(EOS, osErrorMsg(errcode)))
)
let ret = WSASend(socket, addr dataBuf, 1, addr bytesReceived,
@@ -348,7 +376,9 @@ when defined(windows):
dealloc(ol)
else:
retFuture.complete(0)
dealloc(ol)
# We don't deallocate ``ol`` here because even though this completed
# immediately poll will still be notified about its completion and it will
# free ``ol``.
return retFuture
proc acceptAddr*(p: PDispatcher, socket: TSocketHandle):
@@ -390,11 +420,12 @@ when defined(windows):
var ol = cast[PCustomOverlapped](alloc0(sizeof(TCustomOverlapped)))
ol.data = TCompletionData(sock: socket, cb:
proc (sock: TSocketHandle, errcode: TOSErrorCode) =
if errcode == TOSErrorCode(-1):
completeAccept()
else:
retFuture.fail(newException(EOS, osErrorMsg(errcode)))
proc (sock: TSocketHandle, bytesCount: DWord, errcode: TOSErrorCode) =
if not retFuture.finished:
if errcode == TOSErrorCode(-1):
completeAccept()
else:
retFuture.fail(newException(EOS, osErrorMsg(errcode)))
)
# http://msdn.microsoft.com/en-us/library/windows/desktop/ms737524%28v=vs.85%29.aspx
@@ -411,7 +442,9 @@ when defined(windows):
dealloc(ol)
else:
completeAccept()
dealloc(ol)
# We don't deallocate ``ol`` here because even though this completed
# immediately poll will still be notified about its completion and it will
# free ``ol``.
return retFuture
@@ -434,6 +467,199 @@ when defined(windows):
else:
# TODO: Selectors.
# -- Await Macro
template createCb*(cbName, varNameIterSym, retFutureSym: expr): stmt {.immediate, dirty.} =
proc cbName {.closure.} =
if not varNameIterSym.finished:
var next = varNameIterSym()
if next == nil:
assert retFutureSym.finished, "Async procedure's return Future was not finished."
else:
next.callback = cbName
template createVar(futSymName: string, asyncProc: PNimrodNode,
valueReceiver: expr) {.immediate, dirty.} =
# TODO: Used template here due to bug #926
result = newNimNode(nnkStmtList)
var futSym = newIdentNode(futSymName) #genSym(nskVar, "future")
result.add newVarStmt(futSym, asyncProc) # -> var future<x> = y
result.add newNimNode(nnkYieldStmt).add(futSym) # -> yield future<x>
valueReceiver = newDotExpr(futSym, newIdentNode("read")) # -> future<x>.read
proc processBody(node, retFutureSym: PNimrodNode): PNimrodNode {.compileTime.} =
result = node
case node.kind
of nnkReturnStmt:
result = newNimNode(nnkStmtList)
result.add newCall(newIdentNode("complete"), retFutureSym,
if node[0].kind == nnkEmpty: newIdentNode("result") else: node[0])
result.add newNimNode(nnkYieldStmt).add(newNilLit())
of nnkCommand:
if node[0].ident == !"await":
case node[1].kind
of nnkIdent:
# await x
result = newNimNode(nnkYieldStmt).add(node[1]) # -> yield x
of nnkCall:
# await foo(p, x)
var futureValue: PNimrodNode
createVar("future" & $node[1][0].toStrLit, node[1], futureValue)
result.add futureValue
else:
error("Invalid node kind in 'await', got: " & $node[1].kind)
elif node[1].kind == nnkCommand and node[1][0].kind == nnkIdent and
node[1][0].ident == !"await":
# foo await x
var newCommand = node
createVar("future" & $node[0].ident, node[1][0], newCommand[1])
result.add newCommand
of nnkVarSection, nnkLetSection:
case node[0][2].kind
of nnkCommand:
if node[0][2][0].ident == !"await":
# var x = await y
var newVarSection = node # TODO: Should this use copyNimNode?
createVar("future" & $node[0][0].ident, node[0][2][1],
newVarSection[0][2])
result.add newVarSection
else: discard
of nnkAsgn:
case node[1].kind
of nnkCommand:
if node[1][0].ident == !"await":
# x = await y
var newAsgn = node
createVar("future" & $node[0].ident, node[1][1], newAsgn[1])
result.add newAsgn
else: discard
of nnkDiscardStmt:
# discard await x
if node[0][0].ident == !"await":
var dummy = newNimNode(nnkStmtList)
createVar("futureDiscard_" & $toStrLit(node[0][1]), node[0][1], dummy)
else: discard
for i in 0 .. <result.len:
result[i] = processBody(result[i], retFutureSym)
#echo(treeRepr(result))
proc getName(node: PNimrodNode): string {.compileTime.} =
case node.kind
of nnkPostfix:
return $node[1].ident
of nnkIdent:
return $node.ident
else:
assert false
macro async*(prc: stmt): stmt {.immediate.} =
expectKind(prc, nnkProcDef)
hint("Processing " & prc[0].getName & " as an async proc.")
# Verify that the return type is a PFuture[T]
if prc[3][0].kind == nnkIdent:
error("Expected return type of 'PFuture' got '" & $prc[3][0] & "'")
elif prc[3][0].kind == nnkBracketExpr:
if $prc[3][0][0] != "PFuture":
error("Expected return type of 'PFuture' got '" & $prc[3][0][0] & "'")
# TODO: Why can't I use genSym? I get illegal capture errors for Syms.
# TODO: It seems genSym is broken. Change all usages back to genSym when fixed
var outerProcBody = newNimNode(nnkStmtList)
# -> var retFuture = newFuture[T]()
var retFutureSym = newIdentNode("retFuture") #genSym(nskVar, "retFuture")
outerProcBody.add(
newVarStmt(retFutureSym,
newCall(
newNimNode(nnkBracketExpr).add(
newIdentNode("newFuture"),
prc[3][0][1])))) # Get type from return type of this proc.
# -> iterator nameIter(): PFutureBase {.closure.} =
# -> var result: T
# -> <proc_body>
# -> complete(retFuture, result)
var iteratorNameSym = newIdentNode($prc[0].getName & "Iter") #genSym(nskIterator, $prc[0].ident & "Iter")
var procBody = prc[6].processBody(retFutureSym)
procBody.insert(0, newNimNode(nnkVarSection).add(
newIdentDefs(newIdentNode("result"), prc[3][0][1]))) # -> var result: T
procBody.add(
newCall(newIdentNode("complete"),
retFutureSym, newIdentNode("result"))) # -> complete(retFuture, result)
var closureIterator = newProc(iteratorNameSym, [newIdentNode("PFutureBase")],
procBody, nnkIteratorDef)
closureIterator[4] = newNimNode(nnkPragma).add(newIdentNode("closure"))
outerProcBody.add(closureIterator)
# -> var nameIterVar = nameIter
# -> var first = nameIterVar()
var varNameIterSym = newIdentNode($prc[0].getName & "IterVar") #genSym(nskVar, $prc[0].ident & "IterVar")
var varNameIter = newVarStmt(varNameIterSym, iteratorNameSym)
outerProcBody.add varNameIter
var varFirstSym = genSym(nskVar, "first")
var varFirst = newVarStmt(varFirstSym, newCall(varNameIterSym))
outerProcBody.add varFirst
# -> createCb(cb, nameIter, retFuture)
var cbName = newIdentNode("cb")
var procCb = newCall("createCb", cbName, varNameIterSym, retFutureSym)
outerProcBody.add procCb
# -> first.callback = cb
outerProcBody.add newAssignment(
newDotExpr(varFirstSym, newIdentNode("callback")),
cbName)
# -> return retFuture
outerProcBody.add newNimNode(nnkReturnStmt).add(retFutureSym)
result = prc
# Remove the 'async' pragma.
for i in 0 .. <result[4].len:
if result[4][i].ident == !"async":
result[4].del(i)
result[6] = outerProcBody
echo(toStrLit(result))
proc recvLine*(p: PDispatcher, socket: TSocketHandle): PFuture[string] {.async.} =
## Reads a line of data from ``socket``. Returned future will complete once
## a full line is read or an error occurs.
##
## If a full line is read ``\r\L`` is not
## added to ``line``, however if solely ``\r\L`` is read then ``line``
## will be set to it.
##
## If the socket is disconnected, ``line`` will be set to ``""``.
template addNLIfEmpty(): stmt =
if result.len == 0:
result.add("\c\L")
result = ""
var c = ""
while true:
c = await p.recv(socket, 1)
if c.len == 0:
return
if c == "\r":
c = await p.recv(socket, 1, MSG_PEEK)
if c.len > 0 and c == "\L":
discard await p.recv(socket, 1)
addNLIfEmpty()
return
elif c == "\L":
addNLIfEmpty()
return
add(result.string, c)
when isMainModule:
@@ -442,39 +668,65 @@ when isMainModule:
#sock.setBlocking false
p.register(sock)
when true:
var f = p.connect(sock, "irc.freenode.org", TPort(6667))
f.callback =
proc (future: PFuture[int]) =
echo("Connected in future!")
echo(future.read)
for i in 0 .. 50:
var recvF = p.recv(sock, 10)
recvF.callback =
proc (future: PFuture[string]) =
echo("Read: ", future.read)
when false:
# Await tests
proc main(p: PDispatcher): PFuture[int] {.async.} =
discard await p.connect(sock, "irc.freenode.net", TPort(6667))
while true:
var line = await p.recvLine(sock)
echo("Line is: ", line.repr)
if line == "":
echo "Disconnected"
break
proc peekTest(p: PDispatcher): PFuture[int] {.async.} =
discard await p.connect(sock, "localhost", TPort(6667))
while true:
var line = await p.recv(sock, 1, MSG_PEEK)
var line2 = await p.recv(sock, 1)
echo(line.repr)
echo(line2.repr)
echo("---")
if line2 == "": break
sleep(500)
var f = main(p)
else:
when false:
sock.bindAddr(TPort(6667))
sock.listen()
proc onAccept(future: PFuture[TSocketHandle]) =
echo "Accepted"
var t = p.send(future.read, "test\c\L")
t.callback =
var f = p.connect(sock, "irc.freenode.org", TPort(6667))
f.callback =
proc (future: PFuture[int]) =
echo("Connected in future!")
echo(future.read)
for i in 0 .. 50:
var recvF = p.recv(sock, 10)
recvF.callback =
proc (future: PFuture[string]) =
echo("Read: ", future.read)
else:
sock.bindAddr(TPort(6667))
sock.listen()
proc onAccept(future: PFuture[TSocketHandle]) =
echo "Accepted"
var t = p.send(future.read, "test\c\L")
t.callback =
proc (future: PFuture[int]) =
echo(future.read)
var f = p.accept(sock)
f.callback = onAccept
var f = p.accept(sock)
f.callback = onAccept
var f = p.accept(sock)
f.callback = onAccept
while true:
p.poll()
echo "polled"

View File

@@ -557,6 +557,119 @@ proc `$`*(m: TMonth): string =
"November", "December"]
return lookup[m]
proc format_token(info: TTimeInfo, token: string, buf: var string) =
## Helper of the format proc to parse individual tokens.
##
## Pass the found token in the user input string, and the buffer where the
## final string is being built. This has to be a var value because certain
## formatting tokens require modifying the previous characters.
case token
of "d":
buf.add($info.monthday)
of "dd":
if info.monthday < 10:
buf.add("0")
buf.add($info.monthday)
of "ddd":
buf.add(($info.weekday)[0 .. 2])
of "dddd":
buf.add($info.weekday)
of "h":
buf.add($(if info.hour > 12: info.hour - 12 else: info.hour))
of "hh":
let amerHour = if info.hour > 12: info.hour - 12 else: info.hour
if amerHour < 10:
buf.add('0')
buf.add($amerHour)
of "H":
buf.add($info.hour)
of "HH":
if info.hour < 10:
buf.add('0')
buf.add($info.hour)
of "m":
buf.add($info.minute)
of "mm":
if info.minute < 10:
buf.add('0')
buf.add($info.minute)
of "M":
buf.add($(int(info.month)+1))
of "MM":
if info.month < mOct:
buf.add('0')
buf.add($(int(info.month)+1))
of "MMM":
buf.add(($info.month)[0..2])
of "MMMM":
buf.add($info.month)
of "s":
buf.add($info.second)
of "ss":
if info.second < 10:
buf.add('0')
buf.add($info.second)
of "t":
if info.hour >= 12:
buf.add('P')
else: buf.add('A')
of "tt":
if info.hour >= 12:
buf.add("PM")
else: buf.add("AM")
of "y":
var fr = ($info.year).len()-1
if fr < 0: fr = 0
buf.add(($info.year)[fr .. ($info.year).len()-1])
of "yy":
var fr = ($info.year).len()-2
if fr < 0: fr = 0
var fyear = ($info.year)[fr .. ($info.year).len()-1]
if fyear.len != 2: fyear = repeatChar(2-fyear.len(), '0') & fyear
buf.add(fyear)
of "yyy":
var fr = ($info.year).len()-3
if fr < 0: fr = 0
var fyear = ($info.year)[fr .. ($info.year).len()-1]
if fyear.len != 3: fyear = repeatChar(3-fyear.len(), '0') & fyear
buf.add(fyear)
of "yyyy":
var fr = ($info.year).len()-4
if fr < 0: fr = 0
var fyear = ($info.year)[fr .. ($info.year).len()-1]
if fyear.len != 4: fyear = repeatChar(4-fyear.len(), '0') & fyear
buf.add(fyear)
of "yyyyy":
var fr = ($info.year).len()-5
if fr < 0: fr = 0
var fyear = ($info.year)[fr .. ($info.year).len()-1]
if fyear.len != 5: fyear = repeatChar(5-fyear.len(), '0') & fyear
buf.add(fyear)
of "z":
let hrs = (info.timezone div 60) div 60
buf.add($hrs)
of "zz":
let hrs = (info.timezone div 60) div 60
buf.add($hrs)
if hrs.abs < 10:
var atIndex = buf.len-(($hrs).len-(if hrs < 0: 1 else: 0))
buf.insert("0", atIndex)
of "zzz":
let hrs = (info.timezone div 60) div 60
buf.add($hrs & ":00")
if hrs.abs < 10:
var atIndex = buf.len-(($hrs & ":00").len-(if hrs < 0: 1 else: 0))
buf.insert("0", atIndex)
of "ZZZ":
buf.add(info.tzname)
of "":
discard
else:
raise newException(EInvalidValue, "Invalid format string: " & token)
proc format*(info: TTimeInfo, f: string): string =
## This function formats `info` as specified by `f`. The following format
## specifiers are available:
@@ -591,8 +704,11 @@ proc format*(info: TTimeInfo, f: string): string =
## ZZZ Displays the name of the timezone. ``GMT -> GMT``, ``EST -> EST``
## ========== ================================================================================= ================================================
##
## Other strings can be inserted by putting them in ``''``. For example ``hh'->'mm`` will give ``01->56``.
## The following characters can be inserted without quoting them: ``:`` ``-`` ``(`` ``)`` ``/`` ``[`` ``]`` ``,``
## Other strings can be inserted by putting them in ``''``. For example
## ``hh'->'mm`` will give ``01->56``. The following characters can be
## inserted without quoting them: ``:`` ``-`` ``(`` ``)`` ``/`` ``[`` ``]``
## ``,``. However you don't need to necessarily separate format specifiers, a
## unambiguous format string like ``yyyyMMddhhmmss`` is valid too.
result = ""
var i = 0
@@ -600,112 +716,8 @@ proc format*(info: TTimeInfo, f: string): string =
while true:
case f[i]
of ' ', '-', '/', ':', '\'', '\0', '(', ')', '[', ']', ',':
case currentF
of "d":
result.add($info.monthday)
of "dd":
if info.monthday < 10:
result.add("0")
result.add($info.monthday)
of "ddd":
result.add(($info.weekday)[0 .. 2])
of "dddd":
result.add($info.weekday)
of "h":
result.add($(if info.hour > 12: info.hour - 12 else: info.hour))
of "hh":
let amerHour = if info.hour > 12: info.hour - 12 else: info.hour
if amerHour < 10:
result.add('0')
result.add($amerHour)
of "H":
result.add($info.hour)
of "HH":
if info.hour < 10:
result.add('0')
result.add($info.hour)
of "m":
result.add($info.minute)
of "mm":
if info.minute < 10:
result.add('0')
result.add($info.minute)
of "M":
result.add($(int(info.month)+1))
of "MM":
if info.month < mOct:
result.add('0')
result.add($(int(info.month)+1))
of "MMM":
result.add(($info.month)[0..2])
of "MMMM":
result.add($info.month)
of "s":
result.add($info.second)
of "ss":
if info.second < 10:
result.add('0')
result.add($info.second)
of "t":
if info.hour >= 12:
result.add('P')
else: result.add('A')
of "tt":
if info.hour >= 12:
result.add("PM")
else: result.add("AM")
of "y":
var fr = ($info.year).len()-1
if fr < 0: fr = 0
result.add(($info.year)[fr .. ($info.year).len()-1])
of "yy":
var fr = ($info.year).len()-2
if fr < 0: fr = 0
var fyear = ($info.year)[fr .. ($info.year).len()-1]
if fyear.len != 2: fyear = repeatChar(2-fyear.len(), '0') & fyear
result.add(fyear)
of "yyy":
var fr = ($info.year).len()-3
if fr < 0: fr = 0
var fyear = ($info.year)[fr .. ($info.year).len()-1]
if fyear.len != 3: fyear = repeatChar(3-fyear.len(), '0') & fyear
result.add(fyear)
of "yyyy":
var fr = ($info.year).len()-4
if fr < 0: fr = 0
var fyear = ($info.year)[fr .. ($info.year).len()-1]
if fyear.len != 4: fyear = repeatChar(4-fyear.len(), '0') & fyear
result.add(fyear)
of "yyyyy":
var fr = ($info.year).len()-5
if fr < 0: fr = 0
var fyear = ($info.year)[fr .. ($info.year).len()-1]
if fyear.len != 5: fyear = repeatChar(5-fyear.len(), '0') & fyear
result.add(fyear)
of "z":
let hrs = (info.timezone div 60) div 60
result.add($hrs)
of "zz":
let hrs = (info.timezone div 60) div 60
result.add($hrs)
if hrs.abs < 10:
var atIndex = result.len-(($hrs).len-(if hrs < 0: 1 else: 0))
result.insert("0", atIndex)
of "zzz":
let hrs = (info.timezone div 60) div 60
result.add($hrs & ":00")
if hrs.abs < 10:
var atIndex = result.len-(($hrs & ":00").len-(if hrs < 0: 1 else: 0))
result.insert("0", atIndex)
of "ZZZ":
result.add(info.tzname)
of "":
discard
else:
raise newException(EInvalidValue, "Invalid format string: " & currentF)
format_token(info, currentF, result)
currentF = ""
if f[i] == '\0': break
@@ -716,7 +728,15 @@ proc format*(info: TTimeInfo, f: string): string =
inc(i)
else: result.add(f[i])
else: currentF.add(f[i])
else:
# Check if the letter being added matches previous accumulated buffer.
if currentF.len < 1 or currentF[high(currentF)] == f[i]:
currentF.add(f[i])
else:
format_token(info, currentF, result)
dec(i) # Move position back to re-process the character separately.
currentF = ""
inc(i)
{.pop.}
@@ -727,11 +747,15 @@ when isMainModule:
var t = getGMTime(fromSeconds(2147483647))
echo t.format("ddd dd MMM hh:mm:ss ZZZ yyyy")
echo t.format("ddd ddMMMhhmmssZZZyyyy")
assert t.format("ddd dd MMM hh:mm:ss ZZZ yyyy") == "Tue 19 Jan 03:14:07 UTC 2038"
assert t.format("ddd ddMMMhh:mm:ssZZZyyyy") == "Tue 19Jan03:14:07UTC2038"
assert t.format("d dd ddd dddd h hh H HH m mm M MM MMM MMMM s" &
" ss t tt y yy yyy yyyy yyyyy z zz zzz ZZZ") ==
"19 19 Tue Tuesday 3 03 3 03 14 14 1 01 Jan January 7 07 A AM 8 38 038 2038 02038 0 00 00:00 UTC"
assert t.format("yyyyMMddhhmmss") == "20380119031407"
var t2 = getGMTime(fromSeconds(160070789)) # Mon 27 Jan 16:06:29 GMT 1975
assert t2.format("d dd ddd dddd h hh H HH m mm M MM MMM MMMM s" &

View File

@@ -199,14 +199,14 @@ else:
importc: "GetCurrentDirectoryA", dynlib: "kernel32", stdcall.}
proc setCurrentDirectoryA*(lpPathName: cstring): int32 {.
importc: "SetCurrentDirectoryA", dynlib: "kernel32", stdcall.}
proc createDirectoryA*(pathName: cstring, security: pointer=nil): int32 {.
proc createDirectoryA*(pathName: cstring, security: Pointer=nil): int32 {.
importc: "CreateDirectoryA", dynlib: "kernel32", stdcall.}
proc removeDirectoryA*(lpPathName: cstring): int32 {.
importc: "RemoveDirectoryA", dynlib: "kernel32", stdcall.}
proc setEnvironmentVariableA*(lpName, lpValue: cstring): int32 {.
stdcall, dynlib: "kernel32", importc: "SetEnvironmentVariableA".}
proc getModuleFileNameA*(handle: THandle, buf: cstring, size: int32): int32 {.
proc getModuleFileNameA*(handle: THandle, buf: CString, size: int32): int32 {.
importc: "GetModuleFileNameA", dynlib: "kernel32", stdcall.}
when useWinUnicode:
@@ -304,7 +304,7 @@ else:
dwFileAttributes: int32): WINBOOL {.
stdcall, dynlib: "kernel32", importc: "SetFileAttributesA".}
proc copyFileA*(lpExistingFileName, lpNewFileName: cstring,
proc copyFileA*(lpExistingFileName, lpNewFileName: CString,
bFailIfExists: cint): cint {.
importc: "CopyFileA", stdcall, dynlib: "kernel32".}

View File

@@ -7,4 +7,4 @@ type
proc ha() =
var
x: TExport # no error
nil
discard

View File

@@ -4,4 +4,4 @@ type
TExport* = enum x, y, z
proc foo*(x: int) =
nil
discard

View File

@@ -1,4 +1,4 @@
type
TExport* = enum x, y, z # exactly the same type!
proc foo*(x: int) = nil
proc foo*(x: int) = discard

View File

@@ -0,0 +1,64 @@
discard """
file: "tasyncawait.nim"
cmd: "nimrod cc --hints:on $# $#"
output: "5000"
"""
import asyncio2, sockets2, net, strutils
var disp = newDispatcher()
var msgCount = 0
const
swarmSize = 50
messagesToSend = 100
var clientCount = 0
proc sendMessages(disp: PDispatcher, client: TSocketHandle): PFuture[int] {.async.} =
for i in 0 .. <messagesToSend:
discard await disp.send(client, "Message " & $i & "\c\L")
proc launchSwarm(disp: PDispatcher, port: TPort): PFuture[int] {.async.} =
for i in 0 .. <swarmSize:
var sock = socket()
disp.register(sock)
discard await disp.connect(sock, "localhost", port)
when true:
discard await sendMessages(disp, sock)
sock.close()
else:
# Issue #932: https://github.com/Araq/Nimrod/issues/932
var msgFut = sendMessages(disp, sock)
msgFut.callback =
proc () =
sock.close()
proc readMessages(disp: PDispatcher, client: TSocketHandle): PFuture[int] {.async.} =
while true:
var line = await disp.recvLine(client)
if line == "":
client.close()
clientCount.inc
break
else:
if line.startswith("Message "):
msgCount.inc
else:
doAssert false
proc createServer(disp: PDispatcher, port: TPort): PFuture[int] {.async.} =
var server = socket()
disp.register(server)
server.bindAddr(port)
server.listen()
while true:
discard readMessages(disp, await disp.accept(server))
discard disp.createServer(TPort(10335))
discard disp.launchSwarm(TPort(10335))
while true:
disp.poll()
if clientCount == swarmSize: break
assert msgCount == swarmSize * messagesToSend
echo msgCount

View File

@@ -19,8 +19,8 @@ of eB, eC: write(stdout, "b or c")
case x
of "Andreas", "Rumpf": write(stdout, "Hallo Meister!")
of "aa", "bb": write(stdout, "Du bist nicht mein Meister")
of "cc", "hash", "when": nil
of "will", "it", "finally", "be", "generated": nil
of "cc", "hash", "when": discard
of "will", "it", "finally", "be", "generated": discard
var z = case i
of 1..5, 8, 9: "aa"

View File

@@ -12,7 +12,7 @@ var
thr: array [0..5, TThread[tuple[a, b: int]]]
L, M, N: TLock
proc doNothing() = nil
proc doNothing() = discard
proc threadFunc(interval: tuple[a, b: int]) {.thread.} =
doNothing()

View File

@@ -6,7 +6,7 @@ type
PDict[TK, TV] = ref TDict[TK, TV]
proc fakeNew[T](x: var ref T, destroy: proc (a: ref T) {.nimcall.}) =
nil
discard
proc destroyDict[TK, TV](a: PDict[TK, TV]) =
return

View File

@@ -0,0 +1,45 @@
discard """
file: "tnestedbreak.nim"
output: "1\n2\n3\n4"
"""
# First variety
try:
raise newException(EOS, "Problem")
except EOS:
for y in [1, 2, 3]:
discard
try:
discard
except EOS:
discard
echo "1"
# Second Variety
try:
raise newException(EOS, "Problem")
except EOS:
for y in [1, 2, 3]:
discard
for y in [1, 2, 3]:
discard
echo "2"
# Third Variety
try:
raise newException(EOS, "Problem")
except EOS:
block:
break
echo "3"
# Fourth Variety
block:
try:
raise newException(EOS, "Problem")
except EOS:
break
echo "4"

View File

@@ -32,7 +32,7 @@ const
proc len[T,D] (n:PNode[T,D]): Int {.inline.} =
return n.Count
proc clean[T: TOrdinal|TNumber](o: var T) {.inline.} = nil
proc clean[T: TOrdinal|TNumber](o: var T) {.inline.} = discard
proc clean[T: string|seq](o: var T) {.inline.} =
o = nil
@@ -98,7 +98,7 @@ proc DeleteItem[T,D] (n: PNode[T,D], x: Int): PNode[T,D] {.inline.} =
of cLen3 : setLen(n.slots, cLen3)
of cLenCenter : setLen(n.slots, cLenCenter)
of cLen4 : setLen(n.slots, cLen4)
else: nil
else: discard
Result = n
else :
@@ -232,7 +232,7 @@ proc InsertItem[T,D](APath: RPath[T,D], ANode:PNode[T,D], AKey: T, AValue: D) =
of cLen3: setLen(APath.Nd.slots, cLenCenter)
of cLenCenter: setLen(APath.Nd.slots, cLen4)
of cLen4: setLen(APath.Nd.slots, cLenMax)
else: nil
else: discard
for i in countdown(APath.Nd.Count.int - 1, x + 1): shallowCopy(APath.Nd.slots[i], APath.Nd.slots[i - 1])
APath.Nd.slots[x] = setItem(AKey, AValue, ANode)

View File

@@ -1,28 +1,28 @@
template foo(a: int, b: string) = nil
template foo(a: int, b: string) = discard
foo(1, "test")
proc bar(a: int, b: string) = nil
proc bar(a: int, b: string) = discard
bar(1, "test")
template foo(a: int, b: string) = bar(a, b)
foo(1, "test")
block:
proc bar(a: int, b: string) = nil
template foo(a: int, b: string) = nil
proc bar(a: int, b: string) = discard
template foo(a: int, b: string) = discard
foo(1, "test")
bar(1, "test")
proc baz =
proc foo(a: int, b: string) = nil
proc foo(a: int, b: string) = discard
proc foo(b: string) =
template bar(a: int, b: string) = nil
template bar(a: int, b: string) = discard
bar(1, "test")
foo("test")
block:
proc foo(b: string) = nil
proc foo(b: string) = discard
foo("test")
foo(1, "test")

View File

@@ -14,8 +14,8 @@ type
TSomethingElse = object
PSomethingElse = ref TSomethingElse
method foo(a: PNode, b: PSomethingElse) = nil
method foo(a: PNodeFoo, b: PSomethingElse) = nil
method foo(a: PNode, b: PSomethingElse) = discard
method foo(a: PNodeFoo, b: PSomethingElse) = discard
var o: TObject
o.somethin()

View File

@@ -1,13 +1,13 @@
discard """
file: "toverwr.nim"
output: "hello"
"""
discard """
file: "toverwr.nim"
output: "hello"
"""
# Test the overloading resolution in connection with a qualifier
proc write(t: TFile, s: string) =
nil # a nop
discard # a nop
system.write(stdout, "hello")
#OUT hello

View File

@@ -2,7 +2,7 @@ discard """
output: "12false3ha"
"""
proc f(x: varargs[string, `$`]) = nil
proc f(x: varargs[string, `$`]) = discard
template optF{f(X)}(x: varargs[expr]) =
writeln(stdout, x)

View File

@@ -8,7 +8,7 @@ type
TRange = range[0..40]
proc p(r: TRange) =
nil
discard
var
r: TRange

View File

@@ -8,7 +8,7 @@ type
TRange = range[0..40]
proc p(r: TRange) =
nil
discard
var
r: TRange

View File

@@ -1,7 +1,7 @@
discard """
file: "tsets.nim"
output: "Ha ein F ist in s!"
"""
discard """
file: "tsets.nim"
output: "Ha ein F ist in s!"
"""
# Test the handling of sets
import
@@ -38,7 +38,7 @@ type
TTokTypes* = set[TTokTypeRange]
const
toktypes: TTokTypes = {TTokTypeRange(tkSymbol)..pred(tkIntLit),
toktypes: TTokTypes = {TTokTypeRange(tkSymbol)..pred(tkIntLit),
tkStrLit..tkTripleStrLit}
var
@@ -51,14 +51,14 @@ else: write(stdout, "BUG: F ist nicht in s!\n")
a = {} #{'a'..'z'}
for x in low(TAZ) .. high(TAZ):
incl(a, x)
if x in a: nil
if x in a: discard
else: write(stdout, "BUG: something not in a!\n")
for x in low(TTokTypeRange) .. high(TTokTypeRange):
if x in tokTypes:
nil
discard
#writeln(stdout, "the token '$1' is in the set" % repr(x))
#OUT Ha ein F ist in s!

View File

@@ -183,7 +183,7 @@ type
channel: string
timestamp: TTime
case kind*: TSeenType
of PSeenJoin: nil
of PSeenJoin: discard
of PSeenPart, PSeenQuit, PSeenMsg:
msg: string
of PSeenNick:
@@ -200,7 +200,7 @@ proc setSeen(d: TDb, s: TSeen) =
var hashToSet = @[("type", $s.kind.int), ("channel", s.channel),
("timestamp", $s.timestamp.int)]
case s.kind
of PSeenJoin: nil
of PSeenJoin: discard
of PSeenPart, PSeenMsg, PSeenQuit:
hashToSet.add(("msg", s.msg))
of PSeenNick:
@@ -338,7 +338,7 @@ proc hubConnect(state: PState) =
proc handleIrc(irc: PAsyncIRC, event: TIRCEvent, state: PState) =
case event.typ
of EvConnected: nil
of EvConnected: discard
of EvDisconnected:
while not state.ircClient.isConnected:
try:
@@ -424,7 +424,7 @@ proc handleIrc(irc: PAsyncIRC, event: TIRCEvent, state: PState) =
seenNick.newNick = event.params[0]
state.database.setSeen(seenNick)
else:
nil # TODO: ?
discard # TODO: ?
proc open(port: TPort = TPort(5123)): PState =
var res: PState

View File

@@ -1,7 +1,7 @@
# tests for the interpreter
proc loops(a: var int) =
nil
discard
#var
# b: int
#b = glob

View File

@@ -7,6 +7,6 @@ proc walkDirTree(root: string) =
case k
of pcFile, pcLinkToFile: echo(f)
of pcDir: walkDirTree(f)
of pcLinkToDir: nil
of pcLinkToDir: discard
walkDirTree(".")

View File

@@ -72,7 +72,7 @@ type
rule: TNode ## the rule that the symbol refers to
TNode {.final, shallow.} = object
case kind: TPegKind
of pkEmpty..pkWhitespace: nil
of pkEmpty..pkWhitespace: discard
of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle: term: string
of pkChar, pkGreedyRepChar: ch: char
of pkCharChoice, pkGreedyRepSet: charChoice: ref set[char]
@@ -123,7 +123,7 @@ proc add(d: var TPeg, s: TPeg) {.inline.} = add(d.sons, s)
proc copyPeg(a: TPeg): TPeg =
result.kind = a.kind
case a.kind
of pkEmpty..pkWhitespace: nil
of pkEmpty..pkWhitespace: discard
of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle:
result.term = a.term
of pkChar, pkGreedyRepChar:
@@ -229,7 +229,7 @@ when false:
case a.kind
of pkEmpty, pkAny, pkAnyRune, pkGreedyAny, pkNewLine, pkTerminal,
pkTerminalIgnoreCase, pkTerminalIgnoreStyle, pkChar, pkGreedyRepChar,
pkCharChoice, pkGreedyRepSet: nil
pkCharChoice, pkGreedyRepSet: discard
of pkNonTerminal: return true
else:
for i in 0..a.sons.len-1:
@@ -318,7 +318,7 @@ proc backrefIgnoreStyle*(index: range[1..MaxSubPatterns]): TPeg {.
proc spaceCost(n: TPeg): int =
case n.kind
of pkEmpty: nil
of pkEmpty: discard
of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle, pkChar,
pkGreedyRepChar, pkCharChoice, pkGreedyRepSet,
pkAny..pkWhitespace, pkGreedyAny:
@@ -1111,7 +1111,7 @@ proc handleHexChar(c: var TPegLexer, xi: var int) =
of 'A'..'F':
xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('A') + 10)
inc(c.bufpos)
else: nil
else: discard
proc getEscapedChar(c: var TPegLexer, tok: var TToken) =
inc(c.bufpos)
@@ -1341,7 +1341,7 @@ proc getTok(c: var TPegLexer, tok: var TToken) =
of "i": tok.modifier = modIgnoreCase
of "y": tok.modifier = modIgnoreStyle
of "v": tok.modifier = modVerbatim
else: nil
else: discard
setLen(tok.literal, 0)
if c.buf[c.bufpos] == '$':
getDollar(c, tok)
@@ -1488,7 +1488,7 @@ proc primary(p: var TPegParser): TPeg =
of tkCurlyAt:
getTok(p)
return !*\primary(p).token(p)
else: nil
else: discard
case p.tok.kind
of tkIdentifier:
if p.identIsVerbatim:

View File

@@ -1,7 +1,7 @@
# Test if the new table constructor syntax works:
template ignoreExpr(e: expr): stmt {.immediate.} =
nil
discard
# test first class '..' syntactical citizen:
ignoreExpr x <> 2..4

View File

@@ -9,7 +9,7 @@ proc init: TYourObj =
result.y = -1
proc f(x: var TYourObj) =
nil
discard
var m: TMyObj = init()
f(m)

View File

@@ -249,7 +249,7 @@ proc walker(dir: string) =
of pcDir:
if optRecursive in options:
walker(path)
else: nil
else: discard
if existsFile(dir): processFile(dir)
proc writeHelp() =