diff options
-rw-r--r-- | compiler/semcall.nim | 3 | ||||
-rw-r--r-- | compiler/semdestruct.nim | 33 | ||||
-rw-r--r-- | compiler/semmagic.nim | 8 | ||||
-rw-r--r-- | compiler/semstmts.nim | 2 | ||||
-rw-r--r-- | lib/pure/asyncio.nim | 96 | ||||
-rw-r--r-- | lib/system.nim | 14 | ||||
-rw-r--r-- | tests/system/tsettostring.nim (renamed from tests/system/settostring.nim) | 0 | ||||
-rw-r--r-- | web/news.txt | 5 |
8 files changed, 82 insertions, 79 deletions
diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 4309661f3..c48e761e3 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -201,7 +201,8 @@ proc resolveOverloads(c: PContext, n, orig: PNode, elif nfDotSetter in n.flags: internalAssert f.kind == nkIdent and n.sonsLen == 3 - let calleeName = newStrNode(nkStrLit, f.ident.s[0.. -2]).withInfo(n.info) + let calleeName = newStrNode(nkStrLit, + f.ident.s[0..f.ident.s.len-2]).withInfo(n.info) let callOp = newIdentNode(getIdent".=", n.info) n.sons[0..1] = [callOp, n[1], calleeName] orig.sons[0..1] = [callOp, orig[1], calleeName] diff --git a/compiler/semdestruct.nim b/compiler/semdestruct.nim index bbc68ee87..aaab49a10 100644 --- a/compiler/semdestruct.nim +++ b/compiler/semdestruct.nim @@ -12,7 +12,7 @@ # included from sem.nim # special marker values that indicates that we are -# 1) AnalyzingDestructor: currently analyzing the type for destructor +# 1) AnalyzingDestructor: currently analyzing the type for destructor # generation (needed for recursive types) # 2) DestructorIsTrivial: completed the analysis before and determined # that the type has a trivial destructor @@ -41,7 +41,7 @@ proc doDestructorStuff(c: PContext, s: PSym, n: PNode) = if t.kind != tyGenericBody: localError(n.info, errDestructorNotGenericEnough) return - + t.destructor = s # automatically insert calls to base classes' destructors if n.sons[bodyPos].kind != nkEmpty: @@ -71,17 +71,18 @@ proc destroyCase(c: PContext, n: PNode, holder: PNode): PNode = result.addSon(newNode(nkDotExpr, n.info, @[holder, n.sons[0]])) for i in countup(1, n.len - 1): # of A, B: - var caseBranch = newNode(n[i].kind, n[i].info, n[i].sons[0 .. -2]) - - let stmt = destroyFieldOrFields(c, n[i].lastSon, holder) + let ni = n[i] + var caseBranch = newNode(ni.kind, ni.info, ni.sons[0..ni.len-2]) + + let stmt = destroyFieldOrFields(c, ni.lastSon, holder) if stmt == nil: - caseBranch.addSon(newNode(nkStmtList, n[i].info, @[])) + caseBranch.addSon(newNode(nkStmtList, ni.info, @[])) else: caseBranch.addSon(stmt) nonTrivialFields += stmt.len - + result.addSon(caseBranch) - + # maybe no fields were destroyed? if nonTrivialFields == 0: result = nil @@ -107,7 +108,7 @@ proc destroyFieldOrFields(c: PContext, field: PNode, holder: PNode): PNode = proc generateDestructor(c: PContext, t: PType): PNode = ## generate a destructor for a user-defined object or tuple type ## returns nil if the destructor turns out to be trivial - + # XXX: This may be true for some C-imported types such as # Tposix_spawnattr if t.n == nil or t.n.sons == nil: return @@ -120,13 +121,13 @@ proc generateDestructor(c: PContext, t: PType): PNode = proc instantiateDestructor(c: PContext, typ: PType): PType = # returns nil if a variable of type `typ` doesn't require a - # destructor. Otherwise, returns the type, which holds the + # destructor. Otherwise, returns the type, which holds the # destructor that must be used for the varialbe. # The destructor is either user-defined or automatically # generated by the compiler in a member-wise fashion. var t = skipTypes(typ, {tyConst, tyMutable}).skipGenericAlias let typeHoldingUserDefinition = if t.kind == tyGenericInst: t.base else: t - + if typeHoldingUserDefinition.destructor != nil: # XXX: This is not entirely correct for recursive types, but we need # it temporarily to hide the "destroy is already defined" problem @@ -135,7 +136,7 @@ proc instantiateDestructor(c: PContext, typ: PType): PType = return typeHoldingUserDefinition else: return nil - + t = t.skipTypes({tyGenericInst}) case t.kind of tySequence, tyArray, tyArrayConstr, tyOpenArray, tyVarargs: @@ -200,16 +201,16 @@ proc insertDestructors(c: PContext, varId = varSection[j][0] varTyp = varId.sym.typ info = varId.info - + if varTyp == nil or sfGlobal in varId.sym.flags: continue let destructableT = instantiateDestructor(c, varTyp) - + if destructableT != nil: var tryStmt = newNodeI(nkTryStmt, info) if j < totalVars - 1: var remainingVars = newNodeI(varSection.kind, info) - remainingVars.sons = varSection.sons[(j+1)..(-1)] + remainingVars.sons = varSection.sons[(j+1)..varSection.len-1] let (outer, inner) = insertDestructors(c, remainingVars) if outer != nil: tryStmt.addSon(outer) @@ -221,7 +222,7 @@ proc insertDestructors(c: PContext, else: result.inner = newNodeI(nkStmtList, info) tryStmt.addSon(result.inner) - + tryStmt.addSon( newNode(nkFinally, info, @[ semStmt(c, newNode(nkCall, info, @[ diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index 56746ce26..de7700be6 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -167,10 +167,10 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode, result.typ = n[1].typ of mDotDot: result = n - # we only need to warnings here about negative indexing: - if isNegative(n.sons[1]) or (n.len > 2 and isNegative(n.sons[2])): - message(n.info, warnDeprecated, - "use '^' instead of '-'; negative indexing") + # disallow negative indexing for now: + if not c.p.bracketExpr.isNil: + if isNegative(n.sons[1]) or (n.len > 2 and isNegative(n.sons[2])): + localError(n.info, "use '^' instead of '-'; negative indexing is obsolete") of mRoof: # error correction: result = n.sons[1] diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index ae0cbd84f..7263b21b9 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1281,7 +1281,7 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode = var tryStmt = newNodeI(nkTryStmt, n.sons[i].info) var body = newNodeI(nkStmtList, n.sons[i].info) if i < n.sonsLen - 1: - body.sons = n.sons[(i+1)..(-1)] + body.sons = n.sons[(i+1)..n.len-1] tryStmt.addSon(body) tryStmt.addSon(deferPart) n.sons[i] = semTry(c, tryStmt) diff --git a/lib/pure/asyncio.nim b/lib/pure/asyncio.nim index 6a7cbe396..f58bb4302 100644 --- a/lib/pure/asyncio.nim +++ b/lib/pure/asyncio.nim @@ -18,8 +18,8 @@ import sockets, os ## This module implements an asynchronous event loop together with asynchronous ## sockets which use this event loop. ## It is akin to Python's asyncore module. Many modules that use sockets -## have an implementation for this module, those modules should all have a -## ``register`` function which you should use to add the desired objects to a +## have an implementation for this module, those modules should all have a +## ``register`` function which you should use to add the desired objects to a ## dispatcher which you created so ## that you can receive the events associated with that module's object. ## @@ -27,19 +27,19 @@ import sockets, os ## function in a while loop. ## ## **Note:** Most modules have tasks which need to be ran regularly, this is -## why you should not call ``poll`` with a infinite timeout, or even a +## why you should not call ``poll`` with a infinite timeout, or even a ## very long one. In most cases the default timeout is fine. ## ## **Note:** This module currently only supports select(), this is limited by ## FD_SETSIZE, which is usually 1024. So you may only be able to use 1024 ## sockets at a time. -## +## ## Most (if not all) modules that use asyncio provide a userArg which is passed ## on with the events. The type that you set userArg to must be inheriting from ## ``RootObj``! ## -## **Note:** If you want to provide async ability to your module please do not -## use the ``Delegate`` object, instead use ``AsyncSocket``. It is possible +## **Note:** If you want to provide async ability to your module please do not +## use the ``Delegate`` object, instead use ``AsyncSocket``. It is possible ## that in the future this type's fields will not be exported therefore breaking ## your code. ## @@ -59,11 +59,11 @@ import sockets, os ## socket which will give you the client which is connecting. You should then ## set any events that you want to use on that client and add it to your dispatcher ## using the ``register`` procedure. -## +## ## An example ``handleAccept`` follows: -## +## ## .. code-block:: nim -## +## ## var disp = newDispatcher() ## ... ## proc handleAccept(s: AsyncSocket) = @@ -74,7 +74,7 @@ import sockets, os ## client.handleRead = ... ## disp.register(client) ## ... -## +## ## For client sockets you should only be interested in the ``handleRead`` and ## ``handleConnect`` events. The former gets called whenever the socket has ## received messages and can be read from and the latter gets called whenever @@ -83,14 +83,14 @@ import sockets, os ## ## Getting a blocking client from an AsyncSocket ## ============================================= -## +## ## If you need a asynchronous server socket but you wish to process the clients ## synchronously then you can use the ``getSocket`` converter to get ## a ``Socket`` from the ``AsyncSocket`` object, this can then be combined ## with ``accept`` like so: ## ## .. code-block:: nim -## +## ## proc handleAccept(s: AsyncSocket) = ## var client: Socket ## getSocket(s).accept(client) @@ -113,11 +113,11 @@ type handleWrite*: proc (h: RootRef) {.nimcall, gcsafe.} handleError*: proc (h: RootRef) {.nimcall, gcsafe.} hasDataBuffered*: proc (h: RootRef): bool {.nimcall, gcsafe.} - + open*: bool task*: proc (h: RootRef) {.nimcall, gcsafe.} mode*: FileMode - + Delegate* = ref DelegateObj Dispatcher* = ref DispatcherObj @@ -144,7 +144,7 @@ type deleg: Delegate SocketStatus* = enum - SockIdle, SockConnecting, SockConnected, SockListening, SockClosed, + SockIdle, SockConnecting, SockConnected, SockListening, SockClosed, SockUDPBound {.deprecated: [TDelegate: DelegateObj, PDelegate: Delegate, @@ -176,8 +176,8 @@ proc newAsyncSocket(): AsyncSocket = result.lineBuffer = "".TaintedString result.sendBuffer = "" -proc asyncSocket*(domain: Domain = AF_INET, typ: SockType = SOCK_STREAM, - protocol: Protocol = IPPROTO_TCP, +proc asyncSocket*(domain: Domain = AF_INET, typ: SockType = SOCK_STREAM, + protocol: Protocol = IPPROTO_TCP, buffered = true): AsyncSocket = ## Initialises an AsyncSocket object. If a socket cannot be initialised ## EOS is raised. @@ -236,7 +236,7 @@ proc asyncSockHandleWrite(h: RootRef) = if AsyncSocket(h).socket.isSSL and not AsyncSocket(h).socket.gotHandshake: return - + if AsyncSocket(h).info == SockConnecting: AsyncSocket(h).handleConnect(AsyncSocket(h)) AsyncSocket(h).info = SockConnected @@ -256,10 +256,10 @@ proc asyncSockHandleWrite(h: RootRef) = # do nothing instead. discard elif bytesSent != sock.sendBuffer.len: - sock.sendBuffer = sock.sendBuffer[bytesSent .. -1] + sock.sendBuffer = sock.sendBuffer[bytesSent .. ^1] elif bytesSent == sock.sendBuffer.len: sock.sendBuffer = "" - + if AsyncSocket(h).handleWrite != nil: AsyncSocket(h).handleWrite(AsyncSocket(h)) except OSError: @@ -284,7 +284,7 @@ when defined(ssl): else: # handshake will set socket's ``sslNoHandshake`` field. discard AsyncSocket(h).socket.handshake() - + proc asyncSockTask(h: RootRef) = when defined(ssl): @@ -377,9 +377,9 @@ proc acceptAddr*(server: AsyncSocket, client: var AsyncSocket, if c == invalidSocket: raiseSocketError(server.socket) c.setBlocking(false) # TODO: Needs to be tested. - + # deleg.open is set in ``toDelegate``. - + client.socket = c client.lineBuffer = "".TaintedString client.sendBuffer = "" @@ -393,7 +393,7 @@ proc accept*(server: AsyncSocket, client: var AsyncSocket) = proc acceptAddr*(server: AsyncSocket): tuple[sock: AsyncSocket, address: string] {.deprecated.} = ## Equivalent to ``sockets.acceptAddr``. - ## + ## ## **Deprecated since version 0.9.0:** Please use the function above. var client = newAsyncSocket() var address: string = "" @@ -441,17 +441,17 @@ proc isConnected*(s: AsyncSocket): bool = ## Determines whether ``s`` is connected. return s.info == SockConnected proc isListening*(s: AsyncSocket): bool = - ## Determines whether ``s`` is listening for incoming connections. + ## Determines whether ``s`` is listening for incoming connections. return s.info == SockListening proc isConnecting*(s: AsyncSocket): bool = - ## Determines whether ``s`` is connecting. + ## Determines whether ``s`` is connecting. return s.info == SockConnecting proc isClosed*(s: AsyncSocket): bool = ## Determines whether ``s`` has been closed. return s.info == SockClosed proc isSendDataBuffered*(s: AsyncSocket): bool = ## Determines whether ``s`` has data waiting to be sent, i.e. whether this - ## socket's sendBuffer contains data. + ## socket's sendBuffer contains data. return s.sendBuffer.len != 0 proc setHandleWrite*(s: AsyncSocket, @@ -550,7 +550,7 @@ proc send*(sock: AsyncSocket, data: string) = sock.sendBuffer.add(data) sock.deleg.mode = fmReadWrite elif bytesSent != data.len: - sock.sendBuffer.add(data[bytesSent .. -1]) + sock.sendBuffer.add(data[bytesSent .. ^1]) sock.deleg.mode = fmReadWrite proc timeValFromMilliseconds(timeout = 500): Timeval = @@ -561,10 +561,10 @@ proc timeValFromMilliseconds(timeout = 500): Timeval = proc createFdSet(fd: var TFdSet, s: seq[Delegate], m: var int) = FD_ZERO(fd) - for i in items(s): + for i in items(s): m = max(m, int(i.fd)) FD_SET(i.fd, fd) - + proc pruneSocketSet(s: var seq[Delegate], fd: var TFdSet) = var i = 0 var L = s.len @@ -576,16 +576,16 @@ proc pruneSocketSet(s: var seq[Delegate], fd: var TFdSet) = inc(i) setLen(s, L) -proc select(readfds, writefds, exceptfds: var seq[Delegate], +proc select(readfds, writefds, exceptfds: var seq[Delegate], timeout = 500): int = var tv {.noInit.}: Timeval = timeValFromMilliseconds(timeout) - + var rd, wr, ex: TFdSet var m = 0 createFdSet(rd, readfds, m) createFdSet(wr, writefds, m) createFdSet(ex, exceptfds, m) - + if timeout != -1: result = int(select(cint(m+1), addr(rd), addr(wr), addr(ex), addr(tv))) else: @@ -599,7 +599,7 @@ proc poll*(d: Dispatcher, timeout: int = 500): bool = ## This function checks for events on all the delegates in the `PDispatcher`. ## It then proceeds to call the correct event handler. ## - ## This function returns ``True`` if there are file descriptors that are still + ## This function returns ``True`` if there are file descriptors that are still ## open, otherwise ``False``. File descriptors that have been ## closed are immediately removed from the dispatcher automatically. ## @@ -611,7 +611,7 @@ proc poll*(d: Dispatcher, timeout: int = 500): bool = var readDg, writeDg, errorDg: seq[Delegate] = @[] var len = d.delegates.len var dc = 0 - + while dc < len: let deleg = d.delegates[dc] if (deleg.mode != fmWrite or deleg.mode != fmAppend) and deleg.open: @@ -625,20 +625,20 @@ proc poll*(d: Dispatcher, timeout: int = 500): bool = # File/socket has been closed. Remove it from dispatcher. d.delegates[dc] = d.delegates[len-1] dec len - + d.delegates.setLen(len) - + var hasDataBufferedCount = 0 for d in d.delegates: if d.hasDataBuffered(d.deleVal): hasDataBufferedCount.inc() d.handleRead(d.deleVal) if hasDataBufferedCount > 0: return true - + if readDg.len() == 0 and writeDg.len() == 0: ## TODO: Perhaps this shouldn't return if errorDg has something? return false - + if select(readDg, writeDg, errorDg, timeout) != 0: for i in 0..len(d.delegates)-1: if i > len(d.delegates)-1: break # One delegate might've been removed. @@ -651,7 +651,7 @@ proc poll*(d: Dispatcher, timeout: int = 500): bool = deleg.handleWrite(deleg.deleVal) if deleg notin errorDg: deleg.handleError(deleg.deleVal) - + # Execute tasks for i in items(d.delegates): i.task(i.deleVal) @@ -664,7 +664,7 @@ when isMainModule: proc testConnect(s: AsyncSocket, no: int) = echo("Connected! " & $no) - + proc testRead(s: AsyncSocket, no: int) = echo("Reading! " & $no) var data = "" @@ -682,31 +682,31 @@ when isMainModule: var address = "" s.acceptAddr(client, address) echo("Accepted ", address) - client.handleRead = + client.handleRead = proc (s: AsyncSocket) = testRead(s, 2) disp.register(client) proc main = var d = newDispatcher() - + var s = asyncSocket() s.connect("amber.tenthbit.net", Port(6667)) - s.handleConnect = + s.handleConnect = proc (s: AsyncSocket) = testConnect(s, 1) - s.handleRead = + s.handleRead = proc (s: AsyncSocket) = testRead(s, 1) d.register(s) - + var server = asyncSocket() server.handleAccept = - proc (s: AsyncSocket) = + proc (s: AsyncSocket) = testAccept(s, d, 78) server.bindAddr(Port(5555)) server.listen() d.register(server) - + while d.poll(-1): discard main() diff --git a/lib/system.nim b/lib/system.nim index 51ac9cd69..ad448c1d1 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -2865,7 +2865,7 @@ template spliceImpl(s, a, L, b: expr): stmt {.immediate.} = when hostOS != "standalone": proc `[]`*(s: string, x: Slice[int]): string {.inline.} = ## slice operation for strings. - result = s.substr(x.a-|s, x.b-|s) + result = s.substr(x.a, x.b) proc `[]=`*(s: var string, x: Slice[int], b: string) = ## slice assignment for strings. If @@ -2876,8 +2876,8 @@ when hostOS != "standalone": ## var s = "abcdef" ## s[1 .. -2] = "xyz" ## assert s == "axyzf" - var a = x.a-|s - var L = x.b-|s - a + 1 + var a = x.a + var L = x.b - a + 1 if L == b.len: for i in 0 .. <L: s[i+a] = b[i] else: @@ -2919,8 +2919,8 @@ proc `[]=`*[Idx, T](a: var array[Idx, T], x: Slice[Idx], b: openArray[T]) = proc `[]`*[T](s: seq[T], x: Slice[int]): seq[T] = ## slice operation for sequences. - var a = x.a-|s - var L = x.b-|s - a + 1 + var a = x.a + var L = x.b - a + 1 newSeq(result, L) for i in 0.. <L: result[i] = s[i + a] @@ -2928,8 +2928,8 @@ proc `[]=`*[T](s: var seq[T], x: Slice[int], b: openArray[T]) = ## slice assignment for sequences. If ## ``b.len`` is not exactly the number of elements that are referred to ## by `x`, a `splice`:idx: is performed. - var a = x.a-|s - var L = x.b-|s - a + 1 + var a = x.a + var L = x.b - a + 1 if L == b.len: for i in 0 .. <L: s[i+a] = b[i] else: diff --git a/tests/system/settostring.nim b/tests/system/tsettostring.nim index c6846ee99..c6846ee99 100644 --- a/tests/system/settostring.nim +++ b/tests/system/tsettostring.nim diff --git a/web/news.txt b/web/news.txt index 3d60540ec..0b28c29bf 100644 --- a/web/news.txt +++ b/web/news.txt @@ -59,11 +59,12 @@ News echo x.T inc x - - **Negative indexing for slicing is deprecated and will be removed in the - next version of the language.** Instead of ``a[0.. -1]`` you can + - **Negative indexing for slicing does not work anymore!** Instead + of ``a[0.. -1]`` you can use ``a[0.. ^1]``. This also works with accessing a single element ``a[^1]``. Note that we cannot detect this reliably as it is determined at **runtime** whether negative indexing is used! + ``a[0.. -1]`` now produces the empty string/sequence. - The compiler now warns about code like ``foo +=1`` which uses inconsistent spacing around binary operators. Later versions of the language will parse these as unary operators instead so that ``echo $foo`` finally can do what |