diff options
Diffstat (limited to 'lib/pure')
87 files changed, 2066 insertions, 1897 deletions
diff --git a/lib/pure/actors.nim b/lib/pure/actors.nim index 2d902debe..8a8d8b51b 100644 --- a/lib/pure/actors.nim +++ b/lib/pure/actors.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -21,6 +21,11 @@ ## for i in 0 .. < 300: ## a.spawn(i, proc (x: int) {.thread.} = echo x) ## a.join() +## +## **Note**: This whole module is deprecated. Use `threadpool` and ``spawn`` +## instead. + +{.deprecated.} from os import sleep diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim index df94c9eb5..b27ccb93c 100644 --- a/lib/pure/algorithm.nim +++ b/lib/pure/algorithm.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -10,9 +10,12 @@ ## This module implements some common generic algorithms. type - TSortOrder* = enum ## sort order + SortOrder* = enum ## sort order Descending, Ascending +{.deprecated: [TSortOrder: SortOrder].} + + proc `*`*(x: int, order: TSortOrder): int {.inline.} = ## flips `x` if ``order == Descending``; ## if ``order == Ascending`` then `x` is returned. diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index 5dfcf4656..194c6ee1b 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2014 Dominik Picheta # # See the file "copying.txt", included in this @@ -13,7 +13,7 @@ import os, oids, tables, strutils, macros, times import rawsockets, net -export TPort, TSocketFlags +export Port, SocketFlags #{.injectStmt: newGcInvariant().} @@ -36,21 +36,24 @@ export TPort, TSocketFlags # -- Futures type - PFutureBase* = ref object of PObject + FutureBase* = ref object of RootObj cb: proc () {.closure,gcsafe.} finished: bool - error*: ref EBase + error*: ref Exception errorStackTrace*: string when not defined(release): stackTrace: string ## For debugging purposes only. id: int fromProc: string - PFuture*[T] = ref object of PFutureBase + Future*[T] = ref object of FutureBase value: T +{.deprecated: [PFutureBase: FutureBase, PFuture: Future].} + + var currentID* = 0 -proc newFuture*[T](fromProc: string = "unspecified"): PFuture[T] = +proc newFuture*[T](fromProc: string = "unspecified"): Future[T] = ## Creates a new future. ## ## Specifying ``fromProc``, which is a string specifying the name of the proc @@ -63,7 +66,7 @@ proc newFuture*[T](fromProc: string = "unspecified"): PFuture[T] = result.fromProc = fromProc currentID.inc() -proc checkFinished[T](future: PFuture[T]) = +proc checkFinished[T](future: Future[T]) = when not defined(release): if future.finished: echo("<-----> ", future.id, " ", future.fromProc) @@ -76,7 +79,7 @@ proc checkFinished[T](future: PFuture[T]) = echo getStackTrace() assert false -proc complete*[T](future: PFuture[T], val: T) = +proc complete*[T](future: Future[T], val: T) = ## Completes ``future`` with value ``val``. #assert(not future.finished, "Future already finished, cannot finish twice.") checkFinished(future) @@ -86,7 +89,7 @@ proc complete*[T](future: PFuture[T], val: T) = if future.cb != nil: future.cb() -proc complete*(future: PFuture[void]) = +proc complete*(future: Future[void]) = ## Completes a void ``future``. #assert(not future.finished, "Future already finished, cannot finish twice.") checkFinished(future) @@ -95,7 +98,7 @@ proc complete*(future: PFuture[void]) = if future.cb != nil: future.cb() -proc fail*[T](future: PFuture[T], error: ref EBase) = +proc fail*[T](future: Future[T], error: ref Exception) = ## Completes ``future`` with ``error``. #assert(not future.finished, "Future already finished, cannot finish twice.") checkFinished(future) @@ -111,8 +114,9 @@ proc fail*[T](future: PFuture[T], error: ref EBase) = # TODO: This may turn out to be a bad idea. # Turns out this is a bad idea. #raise error + discard -proc `callback=`*(future: PFutureBase, cb: proc () {.closure,gcsafe.}) = +proc `callback=`*(future: FutureBase, cb: proc () {.closure,gcsafe.}) = ## Sets the callback proc to be called when the future completes. ## ## If future has already completed then ``cb`` will be called immediately. @@ -123,23 +127,23 @@ proc `callback=`*(future: PFutureBase, cb: proc () {.closure,gcsafe.}) = if future.finished: future.cb() -proc `callback=`*[T](future: PFuture[T], - cb: proc (future: PFuture[T]) {.closure,gcsafe.}) = +proc `callback=`*[T](future: Future[T], + cb: proc (future: Future[T]) {.closure,gcsafe.}) = ## Sets the callback proc to be called when the future completes. ## ## If future has already completed then ``cb`` will be called immediately. future.callback = proc () = cb(future) -proc echoOriginalStackTrace[T](future: PFuture[T]) = +proc echoOriginalStackTrace[T](future: Future[T]) = # TODO: Come up with something better. when not defined(release): echo("Original stack trace in ", future.fromProc, ":") - if not future.errorStackTrace.isNil() and future.errorStackTrace != "": + if not future.errorStackTrace.isNil and future.errorStackTrace != "": echo(future.errorStackTrace) else: echo("Empty or nil stack trace.") -proc read*[T](future: PFuture[T]): T = +proc read*[T](future: Future[T]): T = ## Retrieves the value of ``future``. Future must be finished otherwise ## this function will fail with a ``EInvalidValue`` exception. ## @@ -154,22 +158,22 @@ proc read*[T](future: PFuture[T]): T = # TODO: Make a custom exception type for this? raise newException(EInvalidValue, "Future still in progress.") -proc readError*[T](future: PFuture[T]): ref EBase = +proc readError*[T](future: Future[T]): ref EBase = if future.error != nil: return future.error else: raise newException(EInvalidValue, "No error in future.") -proc finished*[T](future: PFuture[T]): bool = +proc finished*[T](future: Future[T]): bool = ## Determines whether ``future`` has completed. ## ## ``True`` may indicate an error or a value. Use ``failed`` to distinguish. future.finished -proc failed*(future: PFutureBase): bool = +proc failed*(future: FutureBase): bool = ## Determines whether ``future`` completed with an error. future.error != nil -proc asyncCheck*[T](future: PFuture[T]) = +proc asyncCheck*[T](future: Future[T]) = ## Sets a callback on ``future`` which raises an exception if the future ## finished with an error. ## @@ -180,7 +184,7 @@ proc asyncCheck*[T](future: PFuture[T]) = echoOriginalStackTrace(future) raise future.error -proc `and`*[T, Y](fut1: PFuture[T], fut2: PFuture[Y]): PFuture[void] = +proc `and`*[T, Y](fut1: Future[T], fut2: Future[Y]): Future[void] = ## Returns a future which will complete once both ``fut1`` and ``fut2`` ## complete. var retFuture = newFuture[void]() @@ -192,7 +196,7 @@ proc `and`*[T, Y](fut1: PFuture[T], fut2: PFuture[Y]): PFuture[void] = if fut1.finished: retFuture.complete() return retFuture -proc `or`*[T, Y](fut1: PFuture[T], fut2: PFuture[Y]): PFuture[void] = +proc `or`*[T, Y](fut1: Future[T], fut2: Future[Y]): Future[void] = ## Returns a future which will complete once either ``fut1`` or ``fut2`` ## complete. var retFuture = newFuture[void]() @@ -203,7 +207,7 @@ proc `or`*[T, Y](fut1: PFuture[T], fut2: PFuture[Y]): PFuture[void] = type PDispatcherBase = ref object of PObject - timers: seq[tuple[finishAt: float, fut: PFuture[void]]] + timers: seq[tuple[finishAt: float, fut: Future[void]]] proc processTimers(p: PDispatcherBase) = var oldTimers = p.timers @@ -375,10 +379,10 @@ when defined(windows) or defined(nimdoc): RemoteSockaddr, RemoteSockaddrLength) proc connect*(socket: TAsyncFD, address: string, port: TPort, - af = AF_INET): PFuture[void] = + af = AF_INET): Future[void] = ## Connects ``socket`` to server at ``address:port``. ## - ## Returns a ``PFuture`` which will complete when the connection succeeds + ## Returns a ``Future`` which will complete when the connection succeeds ## or an error occurs. verifyPresence(socket) var retFuture = newFuture[void]("connect") @@ -437,7 +441,7 @@ when defined(windows) or defined(nimdoc): return retFuture proc recv*(socket: TAsyncFD, size: int, - flags = {TSocketFlags.SafeDisconn}): PFuture[string] = + flags = {TSocketFlags.SafeDisconn}): Future[string] = ## Reads **up to** ``size`` bytes from ``socket``. Returned future will ## complete once all the data requested is read, a part of the data has been ## read, or the socket has disconnected in which case the future will @@ -525,7 +529,7 @@ when defined(windows) or defined(nimdoc): return retFuture proc send*(socket: TAsyncFD, data: string, - flags = {TSocketFlags.SafeDisconn}): PFuture[void] = + flags = {TSocketFlags.SafeDisconn}): Future[void] = ## Sends ``data`` to ``socket``. The returned future will complete once all ## data has been sent. verifyPresence(socket) @@ -568,7 +572,7 @@ when defined(windows) or defined(nimdoc): return retFuture proc acceptAddr*(socket: TAsyncFD, flags = {TSocketFlags.SafeDisconn}): - PFuture[tuple[address: string, client: TAsyncFD]] = + Future[tuple[address: string, client: TAsyncFD]] = ## Accepts a new connection. Returns a future containing the client socket ## corresponding to that connection and the remote address of the client. ## The future will complete when the connection is successfully accepted. @@ -789,7 +793,7 @@ else: processTimers(p) proc connect*(socket: TAsyncFD, address: string, port: TPort, - af = AF_INET): PFuture[void] = + af = AF_INET): Future[void] = var retFuture = newFuture[void]("connect") proc cb(sock: TAsyncFD): bool = @@ -824,7 +828,7 @@ else: return retFuture proc recv*(socket: TAsyncFD, size: int, - flags = {TSocketFlags.SafeDisconn}): PFuture[string] = + flags = {TSocketFlags.SafeDisconn}): Future[string] = var retFuture = newFuture[string]("recv") var readBuffer = newString(size) @@ -855,7 +859,7 @@ else: return retFuture proc send*(socket: TAsyncFD, data: string, - flags = {TSocketFlags.SafeDisconn}): PFuture[void] = + flags = {TSocketFlags.SafeDisconn}): Future[void] = var retFuture = newFuture[void]("send") var written = 0 @@ -887,7 +891,7 @@ else: return retFuture proc acceptAddr*(socket: TAsyncFD, flags = {TSocketFlags.SafeDisconn}): - PFuture[tuple[address: string, client: TAsyncFD]] = + Future[tuple[address: string, client: TAsyncFD]] = var retFuture = newFuture[tuple[address: string, client: TAsyncFD]]("acceptAddr") proc cb(sock: TAsyncFD): bool = @@ -912,7 +916,7 @@ else: addRead(socket, cb) return retFuture -proc sleepAsync*(ms: int): PFuture[void] = +proc sleepAsync*(ms: int): Future[void] = ## Suspends the execution of the current async procedure for the next ## ``ms`` miliseconds. var retFuture = newFuture[void]("sleepAsync") @@ -921,14 +925,14 @@ proc sleepAsync*(ms: int): PFuture[void] = return retFuture proc accept*(socket: TAsyncFD, - flags = {TSocketFlags.SafeDisconn}): PFuture[TAsyncFD] = + flags = {TSocketFlags.SafeDisconn}): Future[TAsyncFD] = ## Accepts a new connection. Returns a future containing the client socket ## corresponding to that connection. ## The future will complete when the connection is successfully accepted. var retFut = newFuture[TAsyncFD]("accept") var fut = acceptAddr(socket, flags) fut.callback = - proc (future: PFuture[tuple[address: string, client: TAsyncFD]]) = + proc (future: Future[tuple[address: string, client: TAsyncFD]]) = assert future.finished if future.failed: retFut.fail(future.error) @@ -1111,12 +1115,12 @@ macro async*(prc: stmt): stmt {.immediate.} = hint("Processing " & prc[0].getName & " as an async proc.") let returnType = prc[3][0] - # Verify that the return type is a PFuture[T] + # Verify that the return type is a Future[T] if returnType.kind == nnkIdent: - error("Expected return type of 'PFuture' got '" & $returnType & "'") + error("Expected return type of 'Future' got '" & $returnType & "'") elif returnType.kind == nnkBracketExpr: - if $returnType[0] != "PFuture": - error("Expected return type of 'PFuture' got '" & $returnType[0] & "'") + if $returnType[0] != "Future": + error("Expected return type of 'Future' got '" & $returnType[0] & "'") let subtypeIsVoid = returnType.kind == nnkEmpty or (returnType.kind == nnkBracketExpr and @@ -1137,7 +1141,7 @@ macro async*(prc: stmt): stmt {.immediate.} = subRetType), newLit(prc[0].getName)))) # Get type from return type of this proc - # -> iterator nameIter(): PFutureBase {.closure.} = + # -> iterator nameIter(): FutureBase {.closure.} = # -> var result: T # -> <proc_body> # -> complete(retFuture, result) @@ -1153,7 +1157,7 @@ macro async*(prc: stmt): stmt {.immediate.} = # -> complete(retFuture) procBody.add(newCall(newIdentNode("complete"), retFutureSym)) - var closureIterator = newProc(iteratorNameSym, [newIdentNode("PFutureBase")], + var closureIterator = newProc(iteratorNameSym, [newIdentNode("FutureBase")], procBody, nnkIteratorDef) closureIterator[4] = newNimNode(nnkPragma, prc[6]).add(newIdentNode("closure")) outerProcBody.add(closureIterator) @@ -1176,8 +1180,8 @@ macro async*(prc: stmt): stmt {.immediate.} = if subtypeIsVoid: # Add discardable pragma. if returnType.kind == nnkEmpty: - # Add PFuture[void] - result[3][0] = parseExpr("PFuture[void]") + # Add Future[void] + result[3][0] = parseExpr("Future[void]") result[6] = outerProcBody @@ -1185,7 +1189,7 @@ macro async*(prc: stmt): stmt {.immediate.} = #if prc[0].getName == "processClient": # echo(toStrLit(result)) -proc recvLine*(socket: TAsyncFD): PFuture[string] {.async.} = +proc recvLine*(socket: TAsyncFD): Future[string] {.async.} = ## Reads a line of data from ``socket``. Returned future will complete once ## a full line is read or an error occurs. ## diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim index 26e3a2a7b..54d0b1b8e 100644 --- a/lib/pure/asynchttpserver.nim +++ b/lib/pure/asynchttpserver.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2014 Dominik Picheta # # See the file "copying.txt", included in this @@ -13,7 +13,7 @@ import strtabs, asyncnet, asyncdispatch, parseutils, uri, strutils type - TRequest* = object + Request* = object client*: PAsyncSocket # TODO: Separate this into a Response object? reqMethod*: string headers*: PStringTable @@ -22,10 +22,10 @@ type hostname*: string ## The hostname of the client that made the request. body*: string - PAsyncHttpServer* = ref object + AsyncHttpServer* = ref object socket: PAsyncSocket - THttpCode* = enum + HttpCode* = enum Http200 = "200 OK", Http303 = "303 Moved", Http400 = "400 Bad Request", @@ -33,10 +33,13 @@ type Http500 = "500 Internal Server Error", Http502 = "502 Bad Gateway" - THttpVersion* = enum + HttpVersion* = enum HttpVer11, HttpVer10 +{.deprecated: [TRequest: Request, PAsyncHttpServer: AsyncHttpServer, + THttpCode: HttpCode, THttpVersion: HttpVersion].} + proc `==`*(protocol: tuple[orig: string, major, minor: int], ver: THttpVersion): bool = let major = diff --git a/lib/pure/asyncio.nim b/lib/pure/asyncio.nim index 6b67bf4b5..54aa19079 100644 --- a/lib/pure/asyncio.nim +++ b/lib/pure/asyncio.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf, Dominik Picheta # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -10,8 +10,8 @@ include "system/inclrtl" import sockets, os -## This module implements an asynchronous event loop together with asynchronous sockets -## which use this event loop. +## 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 @@ -31,10 +31,10 @@ import sockets, os ## ## 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 -## TObject! +## ``RootObj``! ## ## **Note:** If you want to provide async ability to your module please do not -## use the ``TDelegate`` object, instead use ``PAsyncSocket``. It is possible +## 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. ## @@ -44,10 +44,10 @@ import sockets, os ## Asynchronous sockets ## ==================== ## -## For most purposes you do not need to worry about the ``TDelegate`` type. The -## ``PAsyncSocket`` is what you are after. It's a reference to the ``TAsyncSocket`` -## object. This object defines events which you should overwrite by your own -## procedures. +## For most purposes you do not need to worry about the ``Delegate`` type. The +## ``AsyncSocket`` is what you are after. It's a reference to +## the ``AsyncSocketObj`` object. This object defines events which you should +## overwrite by your own procedures. ## ## For server sockets the only event you need to worry about is the ``handleAccept`` ## event, in your handleAccept proc you should call ``accept`` on the server @@ -57,13 +57,13 @@ import sockets, os ## ## An example ``handleAccept`` follows: ## -## .. code-block:: nimrod +## .. code-block:: nim ## -## var disp: PDispatcher = newDispatcher() +## var disp = newDispatcher() ## ... -## proc handleAccept(s: PAsyncSocket) = +## proc handleAccept(s: AsyncSocket) = ## echo("Accepted client.") -## var client: PAsyncSocket +## var client: AsyncSocket ## new(client) ## s.accept(client) ## client.handleRead = ... @@ -76,29 +76,29 @@ import sockets, os ## the socket has established a connection to a server socket; from that point ## it can be safely written to. ## -## Getting a blocking client from a PAsyncSocket +## 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 TSocket -## object from the PAsyncSocket object, this can then be combined with ``accept`` -## like so: +## 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:: nimrod +## .. code-block:: nim ## -## proc handleAccept(s: PAsyncSocket) = -## var client: TSocket +## proc handleAccept(s: AsyncSocket) = +## var client: Socket ## getSocket(s).accept(client) when defined(windows): - from winlean import TTimeVal, TSocketHandle, TFdSet, FD_ZERO, FD_SET, FD_ISSET, select + from winlean import TimeVal, SocketHandle, FdSet, FD_ZERO, FD_SET, FD_ISSET, select else: - from posix import TTimeVal, TSocketHandle, TFdSet, FD_ZERO, FD_SET, FD_ISSET, select + from posix import TimeVal, SocketHandle, FdSet, FD_ZERO, FD_SET, FD_ISSET, select type - TDelegate* = object - fd*: TSocketHandle - deleVal*: PObject + DelegateObj* = object + fd*: SocketHandle + deleVal*: RootRef handleRead*: proc (h: PObject) {.nimcall, gcsafe.} handleWrite*: proc (h: PObject) {.nimcall, gcsafe.} @@ -107,18 +107,18 @@ type open*: bool task*: proc (h: PObject) {.nimcall, gcsafe.} - mode*: TFileMode + mode*: FileMode - PDelegate* = ref TDelegate + Delegate* = ref DelegateObj - PDispatcher* = ref TDispatcher - TDispatcher = object + Dispatcher* = ref DispatcherObj + DispatcherObj = object delegates: seq[PDelegate] - PAsyncSocket* = ref TAsyncSocket - TAsyncSocket* = object of TObject - socket: TSocket - info: TInfo + AsyncSocket* = ref AsyncSocketObj + AsyncSocketObj* = object of RootObj + socket: Socket + info: SocketStatus handleRead*: proc (s: PAsyncSocket) {.closure, gcsafe.} handleWrite: proc (s: PAsyncSocket) {.closure, gcsafe.} @@ -134,10 +134,17 @@ type proto: TProtocol deleg: PDelegate - TInfo* = enum + SocketStatus* = enum SockIdle, SockConnecting, SockConnected, SockListening, SockClosed, SockUDPBound +{.deprecated: [TDelegate: DelegateObj, PDelegate: Delegate, + TProcessOption: ProcessOption, + TInfo: SocketStatus, PAsyncSocket: AsyncSocket, TAsyncSocket: AsyncSocketObj, + TDispatcher: DispatcherObj, PDispatcher: Dispatcher, + ].} + + proc newDelegate*(): PDelegate = ## Creates a new delegate. new(result) diff --git a/lib/pure/asyncnet.nim b/lib/pure/asyncnet.nim index 5095d9461..ecaf0b9f9 100644 --- a/lib/pure/asyncnet.nim +++ b/lib/pure/asyncnet.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2014 Dominik Picheta # # See the file "copying.txt", included in this @@ -19,9 +19,9 @@ ## ## import asyncnet, asyncdispatch ## -## var clients: seq[PAsyncSocket] = @[] +## var clients: seq[AsyncSocket] = @[] ## -## proc processClient(client: PAsyncSocket) {.async.} = +## proc processClient(client: AsyncSocket) {.async.} = ## while true: ## let line = await client.recvLine() ## for c in clients: @@ -29,7 +29,7 @@ ## ## proc serve() {.async.} = ## var server = newAsyncSocket() -## server.bindAddr(TPort(12345)) +## server.bindAddr(Port(12345)) ## server.listen() ## ## while true: @@ -54,8 +54,10 @@ when defined(ssl): type # TODO: I would prefer to just do: # PAsyncSocket* {.borrow: `.`.} = distinct PSocket. But that doesn't work. - TAsyncSocket {.borrow: `.`.} = distinct TSocketImpl - PAsyncSocket* = ref TAsyncSocket + AsyncSocketDesc {.borrow: `.`.} = distinct TSocketImpl + AsyncSocket* = ref AsyncSocketDesc + +{.deprecated: [PAsyncSocket: AsyncSocket].} # TODO: Save AF, domain etc info and reuse it in procs which need it like connect. diff --git a/lib/pure/base64.nim b/lib/pure/base64.nim index 7b3b0e6f5..3d3cea25c 100644 --- a/lib/pure/base64.nim +++ b/lib/pure/base64.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2010 Andreas Rumpf # # See the file "copying.txt", included in this diff --git a/lib/pure/basic2d.nim b/lib/pure/basic2d.nim index f8391a368..40f59db74 100644 --- a/lib/pure/basic2d.nim +++ b/lib/pure/basic2d.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2013 Robert Persson # # See the file "copying.txt", included in this diff --git a/lib/pure/basic3d.nim b/lib/pure/basic3d.nim index 540d53fd9..47856e11d 100644 --- a/lib/pure/basic3d.nim +++ b/lib/pure/basic3d.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2013 Robert Persson # # See the file "copying.txt", included in this diff --git a/lib/pure/browsers.nim b/lib/pure/browsers.nim index 3a8429f81..52035ee48 100644 --- a/lib/pure/browsers.nim +++ b/lib/pure/browsers.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -44,5 +44,5 @@ proc openDefaultBrowser*(url: string) = # we use ``startProcess`` here because we don't want to block! discard startProcess(command=b, args=[url], options={poUseShell}) return - except EOS: + except OSError: discard diff --git a/lib/pure/cgi.nim b/lib/pure/cgi.nim index 0d3231b93..bb7934faa 100644 --- a/lib/pure/cgi.nim +++ b/lib/pure/cgi.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -9,7 +9,7 @@ ## This module implements helper procs for CGI applications. Example: ## -## .. code-block:: Nimrod +## .. code-block:: Nim ## ## import strtabs, cgi ## @@ -93,12 +93,14 @@ proc XMLencode*(s: string): string = for i in 0..len(s)-1: addXmlChar(result, s[i]) type - ECgi* = object of IOError ## the exception that is raised, if a CGI error occurs - TRequestMethod* = enum ## the used request method + CgiError* = object of IOError ## exception that is raised if a CGI error occurs + RequestMethod* = enum ## the used request method methodNone, ## no REQUEST_METHOD environment variable methodPost, ## query uses the POST method methodGet ## query uses the GET method +{.deprecated: [TRequestMethod: RequestMethod, ECgi: CgiError].} + proc cgiError*(msg: string) {.noreturn.} = ## raises an ECgi exception with message `msg`. var e: ref ECgi @@ -377,7 +379,7 @@ proc setCookie*(name, value: string) = write(stdout, "Set-Cookie: ", name, "=", value, "\n") var - gcookies {.threadvar.}: PStringTable + gcookies {.threadvar.}: StringTableRef proc getCookie*(name: string): TaintedString = ## Gets a cookie. If no cookie of `name` exists, "" is returned. diff --git a/lib/pure/collections/LockFreeHash.nim b/lib/pure/collections/LockFreeHash.nim index b94b542ff..57beb83c9 100644 --- a/lib/pure/collections/LockFreeHash.nim +++ b/lib/pure/collections/LockFreeHash.nim @@ -1,8 +1,40 @@ #nimrod c -t:-march=i686 --cpu:amd64 --threads:on -d:release lockfreehash.nim -import baseutils, unsigned, math, hashes +import unsigned, math, hashes +#------------------------------------------------------------------------------ +## Memory Utility Functions + +proc newHeap*[T](): ptr T = + result = cast[ptr T](alloc0(sizeof(T))) + +proc copyNew*[T](x: var T): ptr T = + var + size = sizeof(T) + mem = alloc(size) + copyMem(mem, x.addr, size) + return cast[ptr T](mem) + +proc copyTo*[T](val: var T, dest: int) = + copyMem(pointer(dest), val.addr, sizeof(T)) + +proc allocType*[T](): pointer = alloc(sizeof(T)) + +proc newShared*[T](): ptr T = + result = cast[ptr T](allocShared0(sizeof(T))) + +proc copyShared*[T](x: var T): ptr T = + var + size = sizeof(T) + mem = allocShared(size) + copyMem(mem, x.addr, size) + return cast[ptr T](mem) +#------------------------------------------------------------------------------ +## Pointer arithmetic + +proc `+`*(p: pointer, i: int): pointer {.inline.} = + cast[pointer](cast[int](p) + i) const minTableSize = 8 @@ -194,7 +226,7 @@ proc copySlot[K,V](idx: int, oldTbl: var PConcTable[K,V], newTbl: var PConcTable #Prevent new values from appearing in the old table by priming oldVal = atomic_load_n(oldTbl[idx].value.addr, ATOMIC_RELAXED) while not isPrime(oldVal): - var box = if oldVal == NULL or isTomb(oldVal) : oldVal.setTomb.setPrime + var box = if oldVal == 0 or isTomb(oldVal) : oldVal.setTomb.setPrime else: oldVal.setPrime if atomic_compare_exchange_n(oldTbl[idx].value.addr, oldVal.addr, box, false, ATOMIC_RELAXED, ATOMIC_RELAXED): @@ -209,8 +241,8 @@ proc copySlot[K,V](idx: int, oldTbl: var PConcTable[K,V], newTbl: var PConcTable return false if isTomb(oldVal): echo("oldVal is Tomb!!!, should not happen") - if pop(oldVal) != NULL: - result = setVal(newTbl, pop(oldKey), pop(oldVal), NULL, true) == NULL + if pop(oldVal) != 0: + result = setVal(newTbl, pop(oldKey), pop(oldVal), 0, true) == 0 if result: #echo("Copied a Slot! idx= " & $idx & " key= " & $oldKey & " val= " & $oldVal) else: @@ -323,7 +355,7 @@ proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int, idx = idx and (table.len - 1) #echo("try set idx = " & $idx & "for" & $key) var - probedKey = NULL + probedKey = 0 openKey = atomic_compare_exchange_n(table[idx].key.addr, probedKey.addr, key, false, ATOMIC_RELAXED, ATOMIC_RELAXED) if openKey: @@ -339,7 +371,7 @@ proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int, if keyEQ[K](probedKey, key): #echo("we found the matching slot") break # We found a matching slot - if (not(expVal != NULL and match)) and (probes >= reProbeLimit or key.isTomb): + if (not(expVal != 0 and match)) and (probes >= reProbeLimit or key.isTomb): if key.isTomb: echo("Key is Tombstone") #if probes >= reProbeLimit: echo("Too much probing " & $probes) #echo("try to resize") @@ -361,7 +393,7 @@ proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int, return oldVal nextTable = atomic_load_n(table.next.addr, ATOMIC_SEQ_CST) if nextTable == nil and - ((oldVal == NULL and + ((oldVal == 0 and (probes >= reProbeLimit or table.used / table.len > 0.8)) or (isPrime(oldVal))): if table.used / table.len > 0.8: echo("resize because usage ratio = " & @@ -380,12 +412,12 @@ proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int, if atomic_compare_exchange_n(table[idx].value.addr, oldVal.addr, val, false, ATOMIC_RELEASE, ATOMIC_RELAXED): #echo("val set at table " & $cast[int](table)) - if expVal != NULL: - if (oldVal == NULL or isTomb(oldVal)) and not isTomb(val): + if expVal != 0: + if (oldVal == 0 or isTomb(oldVal)) and not isTomb(val): discard atomic_add_fetch(table.active.addr, 1, ATOMIC_RELAXED) - elif not (oldVal == NULL or isTomb(oldVal)) and isTomb(val): + elif not (oldVal == 0 or isTomb(oldVal)) and isTomb(val): discard atomic_add_fetch(table.active.addr, -1, ATOMIC_RELAXED) - if oldVal == NULL and expVal != NULL: + if oldVal == 0 and expVal != 0: return setTomb(oldVal) else: return oldVal if isPrime(oldVal): @@ -415,7 +447,7 @@ proc getVal[K,V](table: var PConcTable[K,V], key: int): int = if not isPrime(val): if isTomb(val): #echo("val was tomb but not prime") - return NULL + return 0 else: #echo("-GotIt- idx = ", idx, " key = ", key, " val ", val ) return val @@ -427,7 +459,7 @@ proc getVal[K,V](table: var PConcTable[K,V], key: int): int = if probes >= reProbeLimit*4 or key.isTomb: if newTable == nil: #echo("too many probes and no new table ", key, " ", idx ) - return NULL + return 0 else: newTable = helpCopy(table) return getVal(newTable, key) @@ -437,10 +469,10 @@ proc getVal[K,V](table: var PConcTable[K,V], key: int): int = #------------------------------------------------------------------------------ #proc set*(table: var PConcTable[TRaw,TRaw], key: TRaw, val: TRaw) = -# discard setVal(table, pack(key), pack(key), NULL, false) +# discard setVal(table, pack(key), pack(key), 0, false) #proc set*[V](table: var PConcTable[TRaw,V], key: TRaw, val: ptr V) = -# discard setVal(table, pack(key), cast[int](val), NULL, false) +# discard setVal(table, pack(key), cast[int](val), 0, false) proc set*[K,V](table: var PConcTable[K,V], key: var K, val: var V) = when not (K is TRaw): @@ -451,10 +483,10 @@ proc set*[K,V](table: var PConcTable[K,V], key: var K, val: var V) = var newVal = cast[int](copyShared(val)) else: var newVal = pack(val) - var oldPtr = pop(setVal(table, newKey, newVal, NULL, false)) + var oldPtr = pop(setVal(table, newKey, newVal, 0, false)) #echo("oldPtr = ", cast[int](oldPtr), " newPtr = ", cast[int](newPtr)) when not (V is TRaw): - if newVal != oldPtr and oldPtr != NULL: + if newVal != oldPtr and oldPtr != 0: deallocShared(cast[ptr V](oldPtr)) @@ -573,10 +605,3 @@ when isMainModule: # echo(i, " = ", hashInt(i) and 8191) deleteConcTable(table) - - - - - - - diff --git a/lib/pure/collections/baseutils.nim b/lib/pure/collections/baseutils.nim deleted file mode 100644 index 565a89ccb..000000000 --- a/lib/pure/collections/baseutils.nim +++ /dev/null @@ -1,41 +0,0 @@ - - - -#------------------------------------------------------------------------------ -## Useful Constants -const NULL* = 0 - - -#------------------------------------------------------------------------------ -## Memory Utility Functions - -proc newHeap*[T](): ptr T = - result = cast[ptr T](alloc0(sizeof(T))) - -proc copyNew*[T](x: var T): ptr T = - var - size = sizeof(T) - mem = alloc(size) - copyMem(mem, x.addr, size) - return cast[ptr T](mem) - -proc copyTo*[T](val: var T, dest: int) = - copyMem(pointer(dest), val.addr, sizeof(T)) - -proc allocType*[T](): pointer = alloc(sizeof(T)) - -proc newShared*[T](): ptr T = - result = cast[ptr T](allocShared0(sizeof(T))) - -proc copyShared*[T](x: var T): ptr T = - var - size = sizeof(T) - mem = allocShared(size) - copyMem(mem, x.addr, size) - return cast[ptr T](mem) - -#------------------------------------------------------------------------------ -## Pointer arithmetic - -proc `+`*(p: pointer, i: int): pointer {.inline.} = - cast[pointer](cast[int](p) + i) \ No newline at end of file diff --git a/lib/pure/collections/critbits.nim b/lib/pure/collections/critbits.nim index 1fde1f419..8f506409b 100644 --- a/lib/pure/collections/critbits.nim +++ b/lib/pure/collections/critbits.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -12,30 +12,32 @@ ## by Adam Langley. type - TNode[T] = object {.pure, final, acyclic.} + NodeObj[T] = object {.pure, final, acyclic.} byte: int ## byte index of the difference otherbits: char case isLeaf: bool - of false: child: array[0..1, ref TNode[T]] + of false: child: array[0..1, ref NodeObj[T]] of true: key: string when T isnot void: val: T - PNode[T] = ref TNode[T] - TCritBitTree*[T] = object {. + Node[T] = ref NodeObj[T] + CritBitTree*[T] = object {. pure, final.} ## The crit bit tree can either be used ## as a mapping from strings to ## some type ``T`` or as a set of ## strings if ``T`` is void. - root: PNode[T] + root: Node[T] count: int - -proc len*[T](c: TCritBitTree[T]): int = + +{.deprecated: [TCritBitTree: CritBitTree].} + +proc len*[T](c: CritBitTree[T]): int = ## returns the number of elements in `c` in O(1). result = c.count -proc rawGet[T](c: TCritBitTree[T], key: string): PNode[T] = +proc rawGet[T](c: CritBitTree[T], key: string): Node[T] = var it = c.root while it != nil: if not it.isLeaf: @@ -45,15 +47,15 @@ proc rawGet[T](c: TCritBitTree[T], key: string): PNode[T] = else: return if it.key == key: it else: nil -proc contains*[T](c: TCritBitTree[T], key: string): bool {.inline.} = +proc contains*[T](c: CritBitTree[T], key: string): bool {.inline.} = ## returns true iff `c` contains the given `key`. result = rawGet(c, key) != nil -proc hasKey*[T](c: TCritBitTree[T], key: string): bool {.inline.} = +proc hasKey*[T](c: CritBitTree[T], key: string): bool {.inline.} = ## alias for `contains`. result = rawGet(c, key) != nil -proc rawInsert[T](c: var TCritBitTree[T], key: string): PNode[T] = +proc rawInsert[T](c: var CritBitTree[T], key: string): Node[T] = if c.root == nil: new c.root c.root.isleaf = true @@ -84,7 +86,7 @@ proc rawInsert[T](c: var TCritBitTree[T], key: string): PNode[T] = let ch = it.key[newByte] let dir = (1 + (ord(ch) or newOtherBits)) shr 8 - var inner: PNode[T] + var inner: Node[T] new inner new result result.isLeaf = true @@ -106,7 +108,7 @@ proc rawInsert[T](c: var TCritBitTree[T], key: string): PNode[T] = wherep[] = inner inc c.count -proc containsOrIncl*[T](c: var TCritBitTree[T], key: string, val: T): bool = +proc containsOrIncl*[T](c: var CritBitTree[T], key: string, val: T): bool = ## returns true iff `c` contains the given `key`. If the key does not exist ## ``c[key] = val`` is performed. let oldCount = c.count @@ -115,23 +117,23 @@ proc containsOrIncl*[T](c: var TCritBitTree[T], key: string, val: T): bool = when T isnot void: if not result: n.val = val -proc containsOrIncl*(c: var TCritBitTree[void], key: string): bool = +proc containsOrIncl*(c: var CritBitTree[void], key: string): bool = ## returns true iff `c` contains the given `key`. If the key does not exist ## it is inserted into `c`. let oldCount = c.count var n = rawInsert(c, key) result = c.count == oldCount -proc incl*(c: var TCritBitTree[void], key: string) = +proc incl*(c: var CritBitTree[void], key: string) = ## includes `key` in `c`. discard rawInsert(c, key) -proc `[]=`*[T](c: var TCritBitTree[T], key: string, val: T) = +proc `[]=`*[T](c: var CritBitTree[T], key: string, val: T) = ## puts a (key, value)-pair into `t`. var n = rawInsert(c, key) n.val = val -proc `[]`*[T](c: TCritBitTree[T], key: string): T {.inline.} = +proc `[]`*[T](c: CritBitTree[T], key: string): T {.inline.} = ## retrieves the value at ``c[key]``. If `key` is not in `t`, ## default empty value for the type `B` is returned ## and no exception is raised. One can check with ``hasKey`` whether the key @@ -139,22 +141,22 @@ proc `[]`*[T](c: TCritBitTree[T], key: string): T {.inline.} = let n = rawGet(c, key) if n != nil: result = n.val -proc mget*[T](c: var TCritBitTree[T], key: string): var T {.inline.} = +proc mget*[T](c: var CritBitTree[T], key: string): var T {.inline.} = ## retrieves the value at ``c[key]``. The value can be modified. - ## If `key` is not in `t`, the ``EInvalidKey`` exception is raised. + ## If `key` is not in `t`, the ``KeyError`` exception is raised. let n = rawGet(c, key) if n != nil: result = n.val - else: raise newException(EInvalidKey, "key not found: " & $key) + else: raise newException(KeyError, "key not found: " & $key) -proc excl*[T](c: var TCritBitTree[T], key: string) = +proc excl*[T](c: var CritBitTree[T], key: string) = ## removes `key` (and its associated value) from the set `c`. ## If the `key` does not exist, nothing happens. var p = c.root var wherep = addr(c.root) - var whereq: ptr PNode = nil + var whereq: ptr Node[T] = nil if p == nil: return var dir = 0 - var q: PNode + var q: Node[T] while not p.isLeaf: whereq = wherep q = p @@ -170,7 +172,7 @@ proc excl*[T](c: var TCritBitTree[T], key: string) = whereq[] = q.child[1 - dir] dec c.count -iterator leaves[T](n: PNode[T]): PNode[T] = +iterator leaves[T](n: Node[T]): Node[T] = if n != nil: # XXX actually we could compute the necessary stack size in advance: # it's rougly log2(c.count). @@ -183,33 +185,33 @@ iterator leaves[T](n: PNode[T]): PNode[T] = assert(it != nil) yield it -iterator keys*[T](c: TCritBitTree[T]): string = +iterator keys*[T](c: CritBitTree[T]): string = ## yields all keys in lexicographical order. for x in leaves(c.root): yield x.key -iterator values*[T](c: TCritBitTree[T]): T = +iterator values*[T](c: CritBitTree[T]): T = ## yields all values of `c` in the lexicographical order of the ## corresponding keys. for x in leaves(c.root): yield x.val -iterator mvalues*[T](c: var TCritBitTree[T]): var T = +iterator mvalues*[T](c: var CritBitTree[T]): var T = ## yields all values of `c` in the lexicographical order of the ## corresponding keys. The values can be modified. for x in leaves(c.root): yield x.val -iterator items*[T](c: TCritBitTree[T]): string = +iterator items*[T](c: CritBitTree[T]): string = ## yields all keys in lexicographical order. for x in leaves(c.root): yield x.key -iterator pairs*[T](c: TCritBitTree[T]): tuple[key: string, val: T] = +iterator pairs*[T](c: CritBitTree[T]): tuple[key: string, val: T] = ## yields all (key, value)-pairs of `c`. for x in leaves(c.root): yield (x.key, x.val) -iterator mpairs*[T](c: var TCritBitTree[T]): tuple[key: string, val: var T] = +iterator mpairs*[T](c: var CritBitTree[T]): tuple[key: string, val: var T] = ## yields all (key, value)-pairs of `c`. The yielded values can be modified. for x in leaves(c.root): yield (x.key, x.val) -proc allprefixedAux[T](c: TCritBitTree[T], key: string): PNode[T] = +proc allprefixedAux[T](c: CritBitTree[T], key: string): Node[T] = var p = c.root var top = p if p != nil: @@ -223,42 +225,42 @@ proc allprefixedAux[T](c: TCritBitTree[T], key: string): PNode[T] = if p.key[i] != key[i]: return result = top -iterator itemsWithPrefix*[T](c: TCritBitTree[T], prefix: string): string = +iterator itemsWithPrefix*[T](c: CritBitTree[T], prefix: string): string = ## yields all keys starting with `prefix`. let top = allprefixedAux(c, prefix) for x in leaves(top): yield x.key -iterator keysWithPrefix*[T](c: TCritBitTree[T], prefix: string): string = +iterator keysWithPrefix*[T](c: CritBitTree[T], prefix: string): string = ## yields all keys starting with `prefix`. let top = allprefixedAux(c, prefix) for x in leaves(top): yield x.key -iterator valuesWithPrefix*[T](c: TCritBitTree[T], prefix: string): T = +iterator valuesWithPrefix*[T](c: CritBitTree[T], prefix: string): T = ## yields all values of `c` starting with `prefix` of the ## corresponding keys. let top = allprefixedAux(c, prefix) for x in leaves(top): yield x.val -iterator mvaluesWithPrefix*[T](c: var TCritBitTree[T], prefix: string): var T = +iterator mvaluesWithPrefix*[T](c: var CritBitTree[T], prefix: string): var T = ## yields all values of `c` starting with `prefix` of the ## corresponding keys. The values can be modified. let top = allprefixedAux(c, prefix) for x in leaves(top): yield x.val -iterator pairsWithPrefix*[T](c: TCritBitTree[T], +iterator pairsWithPrefix*[T](c: CritBitTree[T], prefix: string): tuple[key: string, val: T] = ## yields all (key, value)-pairs of `c` starting with `prefix`. let top = allprefixedAux(c, prefix) for x in leaves(top): yield (x.key, x.val) -iterator mpairsWithPrefix*[T](c: var TCritBitTree[T], +iterator mpairsWithPrefix*[T](c: var CritBitTree[T], prefix: string): tuple[key: string, val: var T] = ## yields all (key, value)-pairs of `c` starting with `prefix`. ## The yielded values can be modified. let top = allprefixedAux(c, prefix) for x in leaves(top): yield (x.key, x.val) -proc `$`*[T](c: TCritBitTree[T]): string = +proc `$`*[T](c: CritBitTree[T]): string = ## turns `c` into a string representation. Example outputs: ## ``{keyA: value, keyB: value}``, ``{:}`` ## If `T` is void the outputs look like: @@ -285,7 +287,7 @@ proc `$`*[T](c: TCritBitTree[T]): string = result.add("}") when isMainModule: - var r: TCritBitTree[void] + var r: CritBitTree[void] r.incl "abc" r.incl "xyz" r.incl "def" diff --git a/lib/pure/collections/intsets.nim b/lib/pure/collections/intsets.nim index f1e67fc0e..678c428c1 100644 --- a/lib/pure/collections/intsets.nim +++ b/lib/pure/collections/intsets.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -9,7 +9,7 @@ ## The ``intsets`` module implements an efficient int set implemented as a ## sparse bit set. -## **Note**: Since Nimrod currently does not allow the assignment operator to +## **Note**: Since Nim currently does not allow the assignment operator to ## be overloaded, ``=`` for int sets performs some rather meaningless shallow ## copy; use ``assign`` to get a deep copy. @@ -17,7 +17,7 @@ import os, hashes, math type - TBitScalar = int + BitScalar = int const InitIntSetSize = 8 # must be a power of two! @@ -25,8 +25,8 @@ const BitsPerTrunk = 1 shl TrunkShift # needs to be a power of 2 and # divisible by 64 TrunkMask = BitsPerTrunk - 1 - IntsPerTrunk = BitsPerTrunk div (sizeof(TBitScalar) * 8) - IntShift = 5 + ord(sizeof(TBitScalar) == 8) # 5 or 6, depending on int width + IntsPerTrunk = BitsPerTrunk div (sizeof(BitScalar) * 8) + IntShift = 5 + ord(sizeof(BitScalar) == 8) # 5 or 6, depending on int width IntMask = 1 shl IntShift - 1 type @@ -34,15 +34,16 @@ type TTrunk {.final.} = object next: PTrunk # all nodes are connected with this pointer key: int # start address at bit 0 - bits: array[0..IntsPerTrunk - 1, TBitScalar] # a bit vector + bits: array[0..IntsPerTrunk - 1, BitScalar] # a bit vector TTrunkSeq = seq[PTrunk] - TIntSet* {.final.} = object ## an efficient set of 'int' implemented as a - ## sparse bit set + IntSet* = object ## an efficient set of 'int' implemented as a sparse bit set counter, max: int head: PTrunk data: TTrunkSeq +{.deprecated: [TIntSet: IntSet].} + proc mustRehash(length, counter: int): bool {.inline.} = assert(length > counter) result = (length * 2 < counter * 3) or (length - counter < 4) diff --git a/lib/pure/collections/lists.nim b/lib/pure/collections/lists.nim index b8f8d20b5..b7ca5a7af 100644 --- a/lib/pure/collections/lists.nim +++ b/lib/pure/collections/lists.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -15,52 +15,58 @@ when not defined(nimhygiene): {.pragma: dirty.} type - TDoublyLinkedNode* {.pure, - final.}[T] = object ## a node a doubly linked list consists of - next*, prev*: ref TDoublyLinkedNode[T] + DoublyLinkedNodeObj*[T] = object ## a node a doubly linked list consists of + next*, prev*: ref DoublyLinkedNodeObj[T] value*: T - PDoublyLinkedNode*[T] = ref TDoublyLinkedNode[T] + DoublyLinkedNode*[T] = ref DoublyLinkedNodeObj[T] - TSinglyLinkedNode* {.pure, - final.}[T] = object ## a node a singly linked list consists of - next*: ref TSinglyLinkedNode[T] + SinglyLinkedNodeObj*[T] = object ## a node a singly linked list consists of + next*: ref SinglyLinkedNodeObj[T] value*: T - PSinglyLinkedNode*[T] = ref TSinglyLinkedNode[T] + SinglyLinkedNode*[T] = ref SinglyLinkedNodeObj[T] - TSinglyLinkedList* {.pure, final.}[T] = object ## a singly linked list - head*, tail*: PSinglyLinkedNode[T] + SinglyLinkedList*[T] = object ## a singly linked list + head*, tail*: SinglyLinkedNode[T] - TDoublyLinkedList* {.pure, final.}[T] = object ## a doubly linked list - head*, tail*: PDoublyLinkedNode[T] + DoublyLinkedList*[T] = object ## a doubly linked list + head*, tail*: DoublyLinkedNode[T] - TSinglyLinkedRing* {.pure, final.}[T] = object ## a singly linked ring - head*: PSinglyLinkedNode[T] + SinglyLinkedRing*[T] = object ## a singly linked ring + head*: SinglyLinkedNode[T] - TDoublyLinkedRing* {.pure, final.}[T] = object ## a doubly linked ring - head*: PDoublyLinkedNode[T] - -proc initSinglyLinkedList*[T](): TSinglyLinkedList[T] = + DoublyLinkedRing*[T] = object ## a doubly linked ring + head*: DoublyLinkedNode[T] + +{.deprecated: [TDoublyLinkedNode: DoublyLinkedNodeObj, + PDoublyLinkedNode: DoublyLinkedNode, + TSinglyLinkedNode: SinglyLinkedNodeObj, + PSinglyLinkedNode: SinglyLinkedNode, + TDoublyLinkedList: DoublyLinkedList, + TSinglyLinkedRing: SinglyLinkedRing, + TDoublyLinkedRing: DoublyLinkedRing].} + +proc initSinglyLinkedList*[T](): SinglyLinkedList[T] = ## creates a new singly linked list that is empty. discard -proc initDoublyLinkedList*[T](): TDoublyLinkedList[T] = +proc initDoublyLinkedList*[T](): DoublyLinkedList[T] = ## creates a new doubly linked list that is empty. discard -proc initSinglyLinkedRing*[T](): TSinglyLinkedRing[T] = +proc initSinglyLinkedRing*[T](): SinglyLinkedRing[T] = ## creates a new singly linked ring that is empty. discard -proc initDoublyLinkedRing*[T](): TDoublyLinkedRing[T] = +proc initDoublyLinkedRing*[T](): DoublyLinkedRing[T] = ## creates a new doubly linked ring that is empty. discard -proc newDoublyLinkedNode*[T](value: T): PDoublyLinkedNode[T] = +proc newDoublyLinkedNode*[T](value: T): DoublyLinkedNode[T] = ## creates a new doubly linked node with the given `value`. new(result) result.value = value -proc newSinglyLinkedNode*[T](value: T): PSinglyLinkedNode[T] = +proc newSinglyLinkedNode*[T](value: T): SinglyLinkedNode[T] = ## creates a new singly linked node with the given `value`. new(result) result.value = value @@ -99,38 +105,38 @@ template findImpl() {.dirty.} = for x in nodes(L): if x.value == value: return x -iterator items*[T](L: TDoublyLinkedList[T]): T = +iterator items*[T](L: DoublyLinkedList[T]): T = ## yields every value of `L`. itemsListImpl() -iterator items*[T](L: TSinglyLinkedList[T]): T = +iterator items*[T](L: SinglyLinkedList[T]): T = ## yields every value of `L`. itemsListImpl() -iterator items*[T](L: TSinglyLinkedRing[T]): T = +iterator items*[T](L: SinglyLinkedRing[T]): T = ## yields every value of `L`. itemsRingImpl() -iterator items*[T](L: TDoublyLinkedRing[T]): T = +iterator items*[T](L: DoublyLinkedRing[T]): T = ## yields every value of `L`. itemsRingImpl() -iterator nodes*[T](L: TSinglyLinkedList[T]): PSinglyLinkedNode[T] = +iterator nodes*[T](L: SinglyLinkedList[T]): SinglyLinkedNode[T] = ## iterates over every node of `x`. Removing the current node from the ## list during traversal is supported. nodesListImpl() -iterator nodes*[T](L: TDoublyLinkedList[T]): PDoublyLinkedNode[T] = +iterator nodes*[T](L: DoublyLinkedList[T]): DoublyLinkedNode[T] = ## iterates over every node of `x`. Removing the current node from the ## list during traversal is supported. nodesListImpl() -iterator nodes*[T](L: TSinglyLinkedRing[T]): PSinglyLinkedNode[T] = +iterator nodes*[T](L: SinglyLinkedRing[T]): SinglyLinkedNode[T] = ## iterates over every node of `x`. Removing the current node from the ## list during traversal is supported. nodesRingImpl() -iterator nodes*[T](L: TDoublyLinkedRing[T]): PDoublyLinkedNode[T] = +iterator nodes*[T](L: DoublyLinkedRing[T]): DoublyLinkedNode[T] = ## iterates over every node of `x`. Removing the current node from the ## list during traversal is supported. nodesRingImpl() @@ -142,33 +148,33 @@ template dollarImpl() {.dirty.} = result.add($x.value) result.add("]") -proc `$`*[T](L: TSinglyLinkedList[T]): string = +proc `$`*[T](L: SinglyLinkedList[T]): string = ## turns a list into its string representation. dollarImpl() -proc `$`*[T](L: TDoublyLinkedList[T]): string = +proc `$`*[T](L: DoublyLinkedList[T]): string = ## turns a list into its string representation. dollarImpl() -proc `$`*[T](L: TSinglyLinkedRing[T]): string = +proc `$`*[T](L: SinglyLinkedRing[T]): string = ## turns a list into its string representation. dollarImpl() -proc `$`*[T](L: TDoublyLinkedRing[T]): string = +proc `$`*[T](L: DoublyLinkedRing[T]): string = ## turns a list into its string representation. dollarImpl() -proc find*[T](L: TSinglyLinkedList[T], value: T): PSinglyLinkedNode[T] = +proc find*[T](L: SinglyLinkedList[T], value: T): SinglyLinkedNode[T] = ## searches in the list for a value. Returns nil if the value does not ## exist. findImpl() -proc find*[T](L: TDoublyLinkedList[T], value: T): PDoublyLinkedNode[T] = +proc find*[T](L: DoublyLinkedList[T], value: T): DoublyLinkedNode[T] = ## searches in the list for a value. Returns nil if the value does not ## exist. findImpl() -proc find*[T](L: TSinglyLinkedRing[T], value: T): PSinglyLinkedNode[T] = +proc find*[T](L: SinglyLinkedRing[T], value: T): SinglyLinkedNode[T] = ## searches in the list for a value. Returns nil if the value does not ## exist. findImpl() @@ -300,5 +306,3 @@ proc remove*[T](L: var TDoublyLinkedRing[T], n: PDoublyLinkedNode[T]) = L.head = nil else: L.head = L.head.prev - - diff --git a/lib/pure/collections/queues.nim b/lib/pure/collections/queues.nim index 5481272f0..d1c94868a 100644 --- a/lib/pure/collections/queues.nim +++ b/lib/pure/collections/queues.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -12,13 +12,15 @@ import math type - TQueue* {.pure, final.}[T] = object ## a queue + Queue*[T] = object ## a queue data: seq[T] rd, wr, count, mask: int - + +{.deprecated: [TQueue: Queue].} + proc initQueue*[T](initialSize=4): TQueue[T] = ## creates a new queue. `initialSize` needs to be a power of 2. - assert IsPowerOfTwo(initialSize) + assert isPowerOfTwo(initialSize) result.mask = initialSize-1 newSeq(result.data, initialSize) diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim index 2629e9f40..9d22f0c3c 100644 --- a/lib/pure/collections/sequtils.nim +++ b/lib/pure/collections/sequtils.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2011 Alex Mitchell # # See the file "copying.txt", included in this @@ -31,7 +31,7 @@ proc concat*[T](seqs: varargs[seq[T]]): seq[T] = ## ## Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## let ## s1 = @[1, 2, 3] ## s2 = @[4, 5] @@ -50,7 +50,7 @@ proc concat*[T](seqs: varargs[seq[T]]): seq[T] = proc deduplicate*[T](seq1: seq[T]): seq[T] = ## Returns a new sequence without duplicates. ## - ## .. code-block:: nimrod + ## .. code-block:: ## let ## dup1 = @[1, 1, 3, 4, 2, 2, 8, 1, 4] ## dup2 = @["a", "a", "c", "d", "d"] @@ -69,7 +69,7 @@ proc zip*[S, T](seq1: seq[S], seq2: seq[T]): seq[tuple[a: S, b: T]] = ## fields `a` and `b`. If one sequence is shorter, the remaining items in the ## longer sequence are discarded. Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## let ## short = @[1, 2, 3] ## long = @[6, 5, 4, 3, 2, 1] @@ -104,7 +104,7 @@ proc distribute*[T](s: seq[T], num: int, spread = true): seq[seq[T]] = ## ## Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## let numbers = @[1, 2, 3, 4, 5, 6, 7] ## assert numbers.distribute(3) == @[@[1, 2, 3], @[4, 5], @[6, 7]] ## assert numbers.distribute(3, false) == @[@[1, 2, 3], @[4, 5, 6], @[7]] @@ -155,7 +155,7 @@ iterator filter*[T](seq1: seq[T], pred: proc(item: T): bool {.closure.}): T = ## ## Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## let numbers = @[1, 4, 5, 8, 9, 7, 4] ## for n in filter(numbers, proc (x: int): bool = x mod 2 == 0): ## echo($n) @@ -169,7 +169,7 @@ proc filter*[T](seq1: seq[T], pred: proc(item: T): bool {.closure.}): seq[T] = ## ## Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## let ## colors = @["red", "yellow", "black"] ## f1 = filter(colors, proc(x: string): bool = x.len < 6) @@ -184,7 +184,7 @@ proc keepIf*[T](seq1: var seq[T], pred: proc(item: T): bool {.closure.}) = ## ## Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## var floats = @[13.0, 12.5, 5.8, 2.0, 6.1, 9.9, 10.1] ## keepIf(floats, proc(x: float): bool = x > 10) ## assert floats == @[13.0, 12.5, 10.1] @@ -202,7 +202,7 @@ proc delete*[T](s: var seq[T], first=0, last=0) = ## ## Example: ## - ##.. code-block:: nimrod + ##.. code-block:: ## let outcome = @[1,1,1,1,1,1,1,1] ## var dest = @[1,1,1,2,2,2,2,2,2,1,1,1,1,1] ## dest.delete(3, 8) @@ -223,7 +223,7 @@ proc insert*[T](dest: var seq[T], src: openArray[T], pos=0) = ## ## Example: ## - ##.. code-block:: nimrod + ##.. code-block:: ## var dest = @[1,1,1,1,1,1,1,1] ## let ## src = @[2,2,2,2,2,2] @@ -254,7 +254,7 @@ template filterIt*(seq1, pred: expr): expr {.immediate.} = ## the ``it`` variable for testing, like: ``filterIt("abcxyz", it == 'x')``. ## Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## let ## temperatures = @[-272.15, -2.0, 24.5, 44.31, 99.9, -113.44] ## acceptable = filterIt(temperatures, it < 50 and it > -10) @@ -273,7 +273,7 @@ template keepItIf*(varSeq, pred: expr) = ## the ``it`` variable for testing, like: ``keepItIf("abcxyz", it == 'x')``. ## Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## var candidates = @["foo", "bar", "baz", "foobar"] ## keepItIf(candidates, it.len == 3 and it[0] == 'b') ## assert candidates == @["bar", "baz"] @@ -292,7 +292,7 @@ template toSeq*(iter: expr): expr {.immediate.} = ## ## Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## let ## numeric = @[1, 2, 3, 4, 5, 6, 7, 8, 9] ## odd_numbers = toSeq(filter(numeric) do (x: int) -> bool: @@ -318,18 +318,18 @@ template foldl*(sequence, operation: expr): expr = ## the sequence of numbers 1, 2 and 3 will be parenthesized as (((1) - 2) - ## 3). Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## let ## numbers = @[5, 9, 11] ## addition = foldl(numbers, a + b) ## substraction = foldl(numbers, a - b) ## multiplication = foldl(numbers, a * b) - ## words = @["nim", "rod", "is", "cool"] + ## words = @["nim", "is", "cool"] ## concatenation = foldl(words, a & b) ## assert addition == 25, "Addition is (((5)+9)+11)" ## assert substraction == -15, "Substraction is (((5)-9)-11)" ## assert multiplication == 495, "Multiplication is (((5)*9)*11)" - ## assert concatenation == "nimrodiscool" + ## assert concatenation == "nimiscool" assert sequence.len > 0, "Can't fold empty sequences" var result {.gensym.}: type(sequence[0]) result = sequence[0] @@ -354,18 +354,18 @@ template foldr*(sequence, operation: expr): expr = ## the sequence of numbers 1, 2 and 3 will be parenthesized as (1 - (2 - ## (3))). Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## let ## numbers = @[5, 9, 11] ## addition = foldr(numbers, a + b) ## substraction = foldr(numbers, a - b) ## multiplication = foldr(numbers, a * b) - ## words = @["nim", "rod", "is", "cool"] + ## words = @["nim", "is", "cool"] ## concatenation = foldr(words, a & b) ## assert addition == 25, "Addition is (5+(9+(11)))" ## assert substraction == 7, "Substraction is (5-(9-(11)))" ## assert multiplication == 495, "Multiplication is (5*(9*(11)))" - ## assert concatenation == "nimrodiscool" + ## assert concatenation == "nimiscool" assert sequence.len > 0, "Can't fold empty sequences" var result {.gensym.}: type(sequence[0]) result = sequence[sequence.len - 1] @@ -384,7 +384,7 @@ template mapIt*(seq1, typ, pred: expr): expr = ## since the new returned sequence can have a different type than the ## original. Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## let ## nums = @[1, 2, 3, 4] ## strings = nums.mapIt(string, $(4 * it)) @@ -401,7 +401,7 @@ template mapIt*(varSeq, pred: expr) = ## expression. The expression has to return the same type as the sequence you ## are mutating. Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## var nums = @[1, 2, 3, 4] ## nums.mapIt(it * 3) ## assert nums[0] + nums[3] == 15 @@ -412,7 +412,7 @@ template mapIt*(varSeq, pred: expr) = template newSeqWith*(len: int, init: expr): expr = ## creates a new sequence, calling `init` to initialize each value. Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## var seq2D = newSeqWith(20, newSeq[bool](10)) ## seq2D[0][0] = true ## seq2D[1][0] = true @@ -503,12 +503,12 @@ when isMainModule: addition = foldl(numbers, a + b) substraction = foldl(numbers, a - b) multiplication = foldl(numbers, a * b) - words = @["nim", "rod", "is", "cool"] + words = @["nim", "is", "cool"] concatenation = foldl(words, a & b) assert addition == 25, "Addition is (((5)+9)+11)" assert substraction == -15, "Substraction is (((5)-9)-11)" assert multiplication == 495, "Multiplication is (((5)*9)*11)" - assert concatenation == "nimrodiscool" + assert concatenation == "nimiscool" block: # foldr tests let @@ -516,12 +516,12 @@ when isMainModule: addition = foldr(numbers, a + b) substraction = foldr(numbers, a - b) multiplication = foldr(numbers, a * b) - words = @["nim", "rod", "is", "cool"] + words = @["nim", "is", "cool"] concatenation = foldr(words, a & b) assert addition == 25, "Addition is (5+(9+(11)))" assert substraction == 7, "Substraction is (5-(9-(11)))" assert multiplication == 495, "Multiplication is (5*(9*(11)))" - assert concatenation == "nimrodiscool" + assert concatenation == "nimiscool" block: # delete tests let outcome = @[1,1,1,1,1,1,1,1] diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim index 3adf21a25..1201241f1 100644 --- a/lib/pure/collections/sets.nim +++ b/lib/pure/collections/sets.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -24,17 +24,19 @@ when not defined(nimhygiene): {.pragma: dirty.} type - TSlotEnum = enum seEmpty, seFilled, seDeleted - TKeyValuePair[A] = tuple[slot: TSlotEnum, key: A] - TKeyValuePairSeq[A] = seq[TKeyValuePair[A]] - TSet* {.final, myShallow.}[A] = object ## \ + SlotEnum = enum seEmpty, seFilled, seDeleted + KeyValuePair[A] = tuple[slot: SlotEnum, key: A] + KeyValuePairSeq[A] = seq[KeyValuePair[A]] + HashSet* {.myShallow.}[A] = object ## \ ## A generic hash set. ## - ## Use `init() <#init,TSet[A],int>`_ or `initSet[type]() <#initSet>`_ + ## Use `init() <#init,HashSet[A],int>`_ or `initSet[type]() <#initSet>`_ ## before calling other procs on it. - data: TKeyValuePairSeq[A] + data: KeyValuePairSeq[A] counter: int +{.deprecated: [TSet: HashSet].} + proc isValid*[A](s: TSet[A]): bool = ## Returns `true` if the set has been initialized with `initSet <#initSet>`_. ## @@ -43,7 +45,7 @@ proc isValid*[A](s: TSet[A]): bool = ## your own procs to verify that sets passed to your procs are correctly ## initialized. Example: ## - ## .. code-block :: nimrod + ## .. code-block :: ## proc savePreferences(options: TSet[string]) = ## assert options.isValid, "Pass an initialized set!" ## # Do stuff here, may crash in release builds! @@ -490,19 +492,20 @@ proc map*[A, B](data: TSet[A], op: proc (x: A): B {.closure.}): TSet[B] = # ------------------------------ ordered set ------------------------------ type - TOrderedKeyValuePair[A] = tuple[ - slot: TSlotEnum, next: int, key: A] - TOrderedKeyValuePairSeq[A] = seq[TOrderedKeyValuePair[A]] - TOrderedSet* {. - final, myShallow.}[A] = object ## \ + OrderedKeyValuePair[A] = tuple[ + slot: SlotEnum, next: int, key: A] + OrderedKeyValuePairSeq[A] = seq[OrderedKeyValuePair[A]] + OrderedSet* {.myShallow.}[A] = object ## \ ## A generic hash set that remembers insertion order. ## - ## Use `init() <#init,TOrderedSet[A],int>`_ or `initOrderedSet[type]() + ## Use `init() <#init,OrderedSet[A],int>`_ or `initOrderedSet[type]() ## <#initOrderedSet>`_ before calling other procs on it. data: TOrderedKeyValuePairSeq[A] counter, first, last: int -proc isValid*[A](s: TOrderedSet[A]): bool = +{.deprecated: [TOrderedSet: OrderedSet].} + +proc isValid*[A](s: OrderedSet[A]): bool = ## Returns `true` if the ordered set has been initialized with `initSet ## <#initOrderedSet>`_. ## @@ -511,13 +514,13 @@ proc isValid*[A](s: TOrderedSet[A]): bool = ## in your own procs to verify that ordered sets passed to your procs are ## correctly initialized. Example: ## - ## .. code-block :: nimrod + ## .. code-block:: ## proc saveTarotCards(cards: TOrderedSet[int]) = ## assert cards.isValid, "Pass an initialized set!" ## # Do stuff here, may crash in release builds! result = not s.data.isNil -proc len*[A](s: TOrderedSet[A]): int {.inline.} = +proc len*[A](s: OrderedSet[A]): int {.inline.} = ## Returns the number of keys in `s`. ## ## Due to an implementation detail you can call this proc on variables which @@ -734,14 +737,14 @@ proc `==`*[A](s, t: TOrderedSet[A]): bool = proc testModule() = ## Internal micro test to validate docstrings and such. block isValidTest: - var options: TSet[string] + var options: HashSet[string] proc savePreferences(options: TSet[string]) = assert options.isValid, "Pass an initialized set!" options = initSet[string]() options.savePreferences block lenTest: - var values: TSet[int] + var values: HashSet[int] assert(not values.isValid) assert values.len == 0 assert values.card == 0 @@ -835,14 +838,14 @@ proc testModule() = assert b == toSet(["1", "2", "3"]) block isValidTest: - var cards: TOrderedSet[string] + var cards: OrderedSet[string] proc saveTarotCards(cards: TOrderedSet[string]) = assert cards.isValid, "Pass an initialized set!" cards = initOrderedSet[string]() cards.saveTarotCards block lenTest: - var values: TOrderedSet[int] + var values: OrderedSet[int] assert(not values.isValid) assert values.len == 0 assert values.card == 0 @@ -879,7 +882,7 @@ proc testModule() = assert(a == b) # https://github.com/Araq/Nimrod/issues/1413 block initBlocks: - var a: TOrderedSet[int] + var a: OrderedSet[int] a.init(4) a.incl(2) a.init diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim index 95caf9195..320d54111 100644 --- a/lib/pure/collections/tables.nim +++ b/lib/pure/collections/tables.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2013 Andreas Rumpf # # See the file "copying.txt", included in this @@ -28,7 +28,7 @@ ## you add such a proc for your custom type everything will work. See this ## example: ## -## .. code-block:: nimrod +## .. code-block:: ## type ## Person = object ## firstName, lastName: string @@ -61,13 +61,15 @@ import {.pragma: myShallow.} type - TSlotEnum = enum seEmpty, seFilled, seDeleted - TKeyValuePair[A, B] = tuple[slot: TSlotEnum, key: A, val: B] - TKeyValuePairSeq[A, B] = seq[TKeyValuePair[A, B]] - TTable* {.final, myShallow.}[A, B] = object ## generic hash table - data: TKeyValuePairSeq[A, B] + SlotEnum = enum seEmpty, seFilled, seDeleted + KeyValuePair[A, B] = tuple[slot: SlotEnum, key: A, val: B] + KeyValuePairSeq[A, B] = seq[KeyValuePair[A, B]] + Table* {.myShallow.}[A, B] = object ## generic hash table + data: KeyValuePairSeq[A, B] counter: int - PTable*[A,B] = ref TTable[A, B] + TableRef*[A,B] = ref Table[A, B] + +{.deprecated: [TTable: Table, PTable: TableRef].} when not defined(nimhygiene): {.pragma: dirty.} @@ -158,12 +160,12 @@ proc hasKey*[A, B](t: TTable[A, B], key: A): bool = ## returns true iff `key` is in the table `t`. result = rawGet(t, key) >= 0 -proc rawInsert[A, B](t: var TTable[A, B], data: var TKeyValuePairSeq[A, B], +proc rawInsert[A, B](t: var TTable[A, B], data: var KeyValuePairSeq[A, B], key: A, val: B) = rawInsertImpl() proc enlarge[A, B](t: var TTable[A, B]) = - var n: TKeyValuePairSeq[A, B] + var n: KeyValuePairSeq[A, B] newSeq(n, len(t.data) * growthFactor) for i in countup(0, high(t.data)): if t.data[i].slot == seFilled: rawInsert(t, n, t.data[i].key, t.data[i].val) @@ -347,14 +349,16 @@ proc newTableFrom*[A, B, C](collection: A, index: proc(x: B): C): PTable[C, B] = # ------------------------------ ordered table ------------------------------ type - TOrderedKeyValuePair[A, B] = tuple[ - slot: TSlotEnum, next: int, key: A, val: B] - TOrderedKeyValuePairSeq[A, B] = seq[TOrderedKeyValuePair[A, B]] - TOrderedTable* {. - final, myShallow.}[A, B] = object ## table that remembers insertion order - data: TOrderedKeyValuePairSeq[A, B] + OrderedKeyValuePair[A, B] = tuple[ + slot: SlotEnum, next: int, key: A, val: B] + OrderedKeyValuePairSeq[A, B] = seq[OrderedKeyValuePair[A, B]] + OrderedTable* {. + myShallow.}[A, B] = object ## table that remembers insertion order + data: OrderedKeyValuePairSeq[A, B] counter, first, last: int - POrderedTable*[A, B] = ref TOrderedTable[A, B] + OrderedTableRef*[A, B] = ref OrderedTable[A, B] + +{.deprecated: [TOrderedTable: OrderedTable, POrderedTable: OrderedTableRef].} proc len*[A, B](t: TOrderedTable[A, B]): int {.inline.} = ## returns the number of keys in `t`. @@ -608,11 +612,13 @@ proc sort*[A, B](t: POrderedTable[A, B], # ------------------------------ count tables ------------------------------- type - TCountTable* {.final, myShallow.}[ + CountTable* {.myShallow.}[ A] = object ## table that counts the number of each key data: seq[tuple[key: A, val: int]] counter: int - PCountTable*[A] = ref TCountTable[A] + CountTableRef*[A] = ref CountTable[A] + +{.deprecated: [TCountTable: CountTable, PCountTable: CountTableRef].} proc len*[A](t: TCountTable[A]): int = ## returns the number of keys in `t`. diff --git a/lib/pure/colors.nim b/lib/pure/colors.nim index 9f824e5de..7942255cb 100644 --- a/lib/pure/colors.nim +++ b/lib/pure/colors.nim @@ -1,5 +1,5 @@ # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2010 Andreas Rumpf # # See the file "copying.txt", included in this @@ -12,18 +12,20 @@ import strutils type - TColor* = distinct int ## a color stored as RGB + Color* = distinct int ## a color stored as RGB -proc `==` *(a, b: TColor): bool {.borrow.} +{.deprecated: [TColor: Color].} + +proc `==` *(a, b: Color): bool {.borrow.} ## compares two colors. -template extract(a: TColor, r, g, b: expr) {.immediate.}= +template extract(a: Color, r, g, b: expr) {.immediate.}= var r = a.int shr 16 and 0xff var g = a.int shr 8 and 0xff var b = a.int and 0xff template rawRGB(r, g, b: int): expr = - TColor(r shl 16 or g shl 8 or b) + Color(r shl 16 or g shl 8 or b) template colorOp(op: expr) {.immediate.} = extract(a, ar, ag, ab) @@ -38,23 +40,23 @@ proc satMinus(a, b: int): int {.inline.} = result = a -% b if result < 0: result = 0 -proc `+`*(a, b: TColor): TColor = +proc `+`*(a, b: Color): Color = ## adds two colors: This uses saturated artithmetic, so that each color ## component cannot overflow (255 is used as a maximum). colorOp(satPlus) -proc `-`*(a, b: TColor): TColor = +proc `-`*(a, b: Color): Color = ## substracts two colors: This uses saturated artithmetic, so that each color ## component cannot overflow (255 is used as a maximum). colorOp(satMinus) -proc extractRGB*(a: TColor): tuple[r, g, b: range[0..255]] = +proc extractRGB*(a: Color): tuple[r, g, b: range[0..255]] = ## extracts the red/green/blue components of the color `a`. result.r = a.int shr 16 and 0xff result.g = a.int shr 8 and 0xff result.b = a.int and 0xff -proc intensity*(a: TColor, f: float): TColor = +proc intensity*(a: Color, f: float): Color = ## returns `a` with intensity `f`. `f` should be a float from 0.0 (completely ## dark) to 1.0 (full color intensity). var r = toInt(toFloat(a.int shr 16 and 0xff) * f) @@ -65,7 +67,7 @@ proc intensity*(a: TColor, f: float): TColor = if b >% 255: b = 255 result = rawRGB(r, g, b) -template mix*(a, b: TColor, fn: expr): expr = +template mix*(a, b: Color, fn: expr): expr = ## uses `fn` to mix the colors `a` and `b`. `fn` is invoked for each component ## R, G, and B. This is a template because `fn` should be inlined and the ## compiler cannot inline proc pointers yet. If `fn`'s result is not in the @@ -84,146 +86,146 @@ template mix*(a, b: TColor, fn: expr): expr = const - colAliceBlue* = TColor(0xF0F8FF) - colAntiqueWhite* = TColor(0xFAEBD7) - colAqua* = TColor(0x00FFFF) - colAquamarine* = TColor(0x7FFFD4) - colAzure* = TColor(0xF0FFFF) - colBeige* = TColor(0xF5F5DC) - colBisque* = TColor(0xFFE4C4) - colBlack* = TColor(0x000000) - colBlanchedAlmond* = TColor(0xFFEBCD) - colBlue* = TColor(0x0000FF) - colBlueViolet* = TColor(0x8A2BE2) - colBrown* = TColor(0xA52A2A) - colBurlyWood* = TColor(0xDEB887) - colCadetBlue* = TColor(0x5F9EA0) - colChartreuse* = TColor(0x7FFF00) - colChocolate* = TColor(0xD2691E) - colCoral* = TColor(0xFF7F50) - colCornflowerBlue* = TColor(0x6495ED) - colCornsilk* = TColor(0xFFF8DC) - colCrimson* = TColor(0xDC143C) - colCyan* = TColor(0x00FFFF) - colDarkBlue* = TColor(0x00008B) - colDarkCyan* = TColor(0x008B8B) - colDarkGoldenRod* = TColor(0xB8860B) - colDarkGray* = TColor(0xA9A9A9) - colDarkGreen* = TColor(0x006400) - colDarkKhaki* = TColor(0xBDB76B) - colDarkMagenta* = TColor(0x8B008B) - colDarkOliveGreen* = TColor(0x556B2F) - colDarkorange* = TColor(0xFF8C00) - colDarkOrchid* = TColor(0x9932CC) - colDarkRed* = TColor(0x8B0000) - colDarkSalmon* = TColor(0xE9967A) - colDarkSeaGreen* = TColor(0x8FBC8F) - colDarkSlateBlue* = TColor(0x483D8B) - colDarkSlateGray* = TColor(0x2F4F4F) - colDarkTurquoise* = TColor(0x00CED1) - colDarkViolet* = TColor(0x9400D3) - colDeepPink* = TColor(0xFF1493) - colDeepSkyBlue* = TColor(0x00BFFF) - colDimGray* = TColor(0x696969) - colDodgerBlue* = TColor(0x1E90FF) - colFireBrick* = TColor(0xB22222) - colFloralWhite* = TColor(0xFFFAF0) - colForestGreen* = TColor(0x228B22) - colFuchsia* = TColor(0xFF00FF) - colGainsboro* = TColor(0xDCDCDC) - colGhostWhite* = TColor(0xF8F8FF) - colGold* = TColor(0xFFD700) - colGoldenRod* = TColor(0xDAA520) - colGray* = TColor(0x808080) - colGreen* = TColor(0x008000) - colGreenYellow* = TColor(0xADFF2F) - colHoneyDew* = TColor(0xF0FFF0) - colHotPink* = TColor(0xFF69B4) - colIndianRed* = TColor(0xCD5C5C) - colIndigo* = TColor(0x4B0082) - colIvory* = TColor(0xFFFFF0) - colKhaki* = TColor(0xF0E68C) - colLavender* = TColor(0xE6E6FA) - colLavenderBlush* = TColor(0xFFF0F5) - colLawnGreen* = TColor(0x7CFC00) - colLemonChiffon* = TColor(0xFFFACD) - colLightBlue* = TColor(0xADD8E6) - colLightCoral* = TColor(0xF08080) - colLightCyan* = TColor(0xE0FFFF) - colLightGoldenRodYellow* = TColor(0xFAFAD2) - colLightGrey* = TColor(0xD3D3D3) - colLightGreen* = TColor(0x90EE90) - colLightPink* = TColor(0xFFB6C1) - colLightSalmon* = TColor(0xFFA07A) - colLightSeaGreen* = TColor(0x20B2AA) - colLightSkyBlue* = TColor(0x87CEFA) - colLightSlateGray* = TColor(0x778899) - colLightSteelBlue* = TColor(0xB0C4DE) - colLightYellow* = TColor(0xFFFFE0) - colLime* = TColor(0x00FF00) - colLimeGreen* = TColor(0x32CD32) - colLinen* = TColor(0xFAF0E6) - colMagenta* = TColor(0xFF00FF) - colMaroon* = TColor(0x800000) - colMediumAquaMarine* = TColor(0x66CDAA) - colMediumBlue* = TColor(0x0000CD) - colMediumOrchid* = TColor(0xBA55D3) - colMediumPurple* = TColor(0x9370D8) - colMediumSeaGreen* = TColor(0x3CB371) - colMediumSlateBlue* = TColor(0x7B68EE) - colMediumSpringGreen* = TColor(0x00FA9A) - colMediumTurquoise* = TColor(0x48D1CC) - colMediumVioletRed* = TColor(0xC71585) - colMidnightBlue* = TColor(0x191970) - colMintCream* = TColor(0xF5FFFA) - colMistyRose* = TColor(0xFFE4E1) - colMoccasin* = TColor(0xFFE4B5) - colNavajoWhite* = TColor(0xFFDEAD) - colNavy* = TColor(0x000080) - colOldLace* = TColor(0xFDF5E6) - colOlive* = TColor(0x808000) - colOliveDrab* = TColor(0x6B8E23) - colOrange* = TColor(0xFFA500) - colOrangeRed* = TColor(0xFF4500) - colOrchid* = TColor(0xDA70D6) - colPaleGoldenRod* = TColor(0xEEE8AA) - colPaleGreen* = TColor(0x98FB98) - colPaleTurquoise* = TColor(0xAFEEEE) - colPaleVioletRed* = TColor(0xD87093) - colPapayaWhip* = TColor(0xFFEFD5) - colPeachPuff* = TColor(0xFFDAB9) - colPeru* = TColor(0xCD853F) - colPink* = TColor(0xFFC0CB) - colPlum* = TColor(0xDDA0DD) - colPowderBlue* = TColor(0xB0E0E6) - colPurple* = TColor(0x800080) - colRed* = TColor(0xFF0000) - colRosyBrown* = TColor(0xBC8F8F) - colRoyalBlue* = TColor(0x4169E1) - colSaddleBrown* = TColor(0x8B4513) - colSalmon* = TColor(0xFA8072) - colSandyBrown* = TColor(0xF4A460) - colSeaGreen* = TColor(0x2E8B57) - colSeaShell* = TColor(0xFFF5EE) - colSienna* = TColor(0xA0522D) - colSilver* = TColor(0xC0C0C0) - colSkyBlue* = TColor(0x87CEEB) - colSlateBlue* = TColor(0x6A5ACD) - colSlateGray* = TColor(0x708090) - colSnow* = TColor(0xFFFAFA) - colSpringGreen* = TColor(0x00FF7F) - colSteelBlue* = TColor(0x4682B4) - colTan* = TColor(0xD2B48C) - colTeal* = TColor(0x008080) - colThistle* = TColor(0xD8BFD8) - colTomato* = TColor(0xFF6347) - colTurquoise* = TColor(0x40E0D0) - colViolet* = TColor(0xEE82EE) - colWheat* = TColor(0xF5DEB3) - colWhite* = TColor(0xFFFFFF) - colWhiteSmoke* = TColor(0xF5F5F5) - colYellow* = TColor(0xFFFF00) - colYellowGreen* = TColor(0x9ACD32) + colAliceBlue* = Color(0xF0F8FF) + colAntiqueWhite* = Color(0xFAEBD7) + colAqua* = Color(0x00FFFF) + colAquamarine* = Color(0x7FFFD4) + colAzure* = Color(0xF0FFFF) + colBeige* = Color(0xF5F5DC) + colBisque* = Color(0xFFE4C4) + colBlack* = Color(0x000000) + colBlanchedAlmond* = Color(0xFFEBCD) + colBlue* = Color(0x0000FF) + colBlueViolet* = Color(0x8A2BE2) + colBrown* = Color(0xA52A2A) + colBurlyWood* = Color(0xDEB887) + colCadetBlue* = Color(0x5F9EA0) + colChartreuse* = Color(0x7FFF00) + colChocolate* = Color(0xD2691E) + colCoral* = Color(0xFF7F50) + colCornflowerBlue* = Color(0x6495ED) + colCornsilk* = Color(0xFFF8DC) + colCrimson* = Color(0xDC143C) + colCyan* = Color(0x00FFFF) + colDarkBlue* = Color(0x00008B) + colDarkCyan* = Color(0x008B8B) + colDarkGoldenRod* = Color(0xB8860B) + colDarkGray* = Color(0xA9A9A9) + colDarkGreen* = Color(0x006400) + colDarkKhaki* = Color(0xBDB76B) + colDarkMagenta* = Color(0x8B008B) + colDarkOliveGreen* = Color(0x556B2F) + colDarkorange* = Color(0xFF8C00) + colDarkOrchid* = Color(0x9932CC) + colDarkRed* = Color(0x8B0000) + colDarkSalmon* = Color(0xE9967A) + colDarkSeaGreen* = Color(0x8FBC8F) + colDarkSlateBlue* = Color(0x483D8B) + colDarkSlateGray* = Color(0x2F4F4F) + colDarkTurquoise* = Color(0x00CED1) + colDarkViolet* = Color(0x9400D3) + colDeepPink* = Color(0xFF1493) + colDeepSkyBlue* = Color(0x00BFFF) + colDimGray* = Color(0x696969) + colDodgerBlue* = Color(0x1E90FF) + colFireBrick* = Color(0xB22222) + colFloralWhite* = Color(0xFFFAF0) + colForestGreen* = Color(0x228B22) + colFuchsia* = Color(0xFF00FF) + colGainsboro* = Color(0xDCDCDC) + colGhostWhite* = Color(0xF8F8FF) + colGold* = Color(0xFFD700) + colGoldenRod* = Color(0xDAA520) + colGray* = Color(0x808080) + colGreen* = Color(0x008000) + colGreenYellow* = Color(0xADFF2F) + colHoneyDew* = Color(0xF0FFF0) + colHotPink* = Color(0xFF69B4) + colIndianRed* = Color(0xCD5C5C) + colIndigo* = Color(0x4B0082) + colIvory* = Color(0xFFFFF0) + colKhaki* = Color(0xF0E68C) + colLavender* = Color(0xE6E6FA) + colLavenderBlush* = Color(0xFFF0F5) + colLawnGreen* = Color(0x7CFC00) + colLemonChiffon* = Color(0xFFFACD) + colLightBlue* = Color(0xADD8E6) + colLightCoral* = Color(0xF08080) + colLightCyan* = Color(0xE0FFFF) + colLightGoldenRodYellow* = Color(0xFAFAD2) + colLightGrey* = Color(0xD3D3D3) + colLightGreen* = Color(0x90EE90) + colLightPink* = Color(0xFFB6C1) + colLightSalmon* = Color(0xFFA07A) + colLightSeaGreen* = Color(0x20B2AA) + colLightSkyBlue* = Color(0x87CEFA) + colLightSlateGray* = Color(0x778899) + colLightSteelBlue* = Color(0xB0C4DE) + colLightYellow* = Color(0xFFFFE0) + colLime* = Color(0x00FF00) + colLimeGreen* = Color(0x32CD32) + colLinen* = Color(0xFAF0E6) + colMagenta* = Color(0xFF00FF) + colMaroon* = Color(0x800000) + colMediumAquaMarine* = Color(0x66CDAA) + colMediumBlue* = Color(0x0000CD) + colMediumOrchid* = Color(0xBA55D3) + colMediumPurple* = Color(0x9370D8) + colMediumSeaGreen* = Color(0x3CB371) + colMediumSlateBlue* = Color(0x7B68EE) + colMediumSpringGreen* = Color(0x00FA9A) + colMediumTurquoise* = Color(0x48D1CC) + colMediumVioletRed* = Color(0xC71585) + colMidnightBlue* = Color(0x191970) + colMintCream* = Color(0xF5FFFA) + colMistyRose* = Color(0xFFE4E1) + colMoccasin* = Color(0xFFE4B5) + colNavajoWhite* = Color(0xFFDEAD) + colNavy* = Color(0x000080) + colOldLace* = Color(0xFDF5E6) + colOlive* = Color(0x808000) + colOliveDrab* = Color(0x6B8E23) + colOrange* = Color(0xFFA500) + colOrangeRed* = Color(0xFF4500) + colOrchid* = Color(0xDA70D6) + colPaleGoldenRod* = Color(0xEEE8AA) + colPaleGreen* = Color(0x98FB98) + colPaleTurquoise* = Color(0xAFEEEE) + colPaleVioletRed* = Color(0xD87093) + colPapayaWhip* = Color(0xFFEFD5) + colPeachPuff* = Color(0xFFDAB9) + colPeru* = Color(0xCD853F) + colPink* = Color(0xFFC0CB) + colPlum* = Color(0xDDA0DD) + colPowderBlue* = Color(0xB0E0E6) + colPurple* = Color(0x800080) + colRed* = Color(0xFF0000) + colRosyBrown* = Color(0xBC8F8F) + colRoyalBlue* = Color(0x4169E1) + colSaddleBrown* = Color(0x8B4513) + colSalmon* = Color(0xFA8072) + colSandyBrown* = Color(0xF4A460) + colSeaGreen* = Color(0x2E8B57) + colSeaShell* = Color(0xFFF5EE) + colSienna* = Color(0xA0522D) + colSilver* = Color(0xC0C0C0) + colSkyBlue* = Color(0x87CEEB) + colSlateBlue* = Color(0x6A5ACD) + colSlateGray* = Color(0x708090) + colSnow* = Color(0xFFFAFA) + colSpringGreen* = Color(0x00FF7F) + colSteelBlue* = Color(0x4682B4) + colTan* = Color(0xD2B48C) + colTeal* = Color(0x008080) + colThistle* = Color(0xD8BFD8) + colTomato* = Color(0xFF6347) + colTurquoise* = Color(0x40E0D0) + colViolet* = Color(0xEE82EE) + colWheat* = Color(0xF5DEB3) + colWhite* = Color(0xFFFFFF) + colWhiteSmoke* = Color(0xF5F5F5) + colYellow* = Color(0xFFFF00) + colYellowGreen* = Color(0x9ACD32) colorNames = [ ("aliceblue", colAliceBlue), @@ -367,11 +369,11 @@ const ("yellow", colYellow), ("yellowgreen", colYellowGreen)] -proc `$`*(c: TColor): string = +proc `$`*(c: Color): string = ## converts a color into its textual representation. Example: ``#00FF00``. result = '#' & toHex(int(c), 6) -proc binaryStrSearch(x: openarray[tuple[name: string, col: TColor]], +proc binaryStrSearch(x: openArray[tuple[name: string, col: Color]], y: string): int = var a = 0 var b = len(x) - 1 @@ -383,14 +385,14 @@ proc binaryStrSearch(x: openarray[tuple[name: string, col: TColor]], else: return mid result = - 1 -proc parseColor*(name: string): TColor = +proc parseColor*(name: string): Color = ## parses `name` to a color value. If no valid color could be ## parsed ``EInvalidValue`` is raised. if name[0] == '#': - result = TColor(parseHexInt(name)) + result = Color(parseHexInt(name)) else: var idx = binaryStrSearch(colorNames, name) - if idx < 0: raise newException(EInvalidValue, "unkown color: " & name) + if idx < 0: raise newException(ValueError, "unkown color: " & name) result = colorNames[idx][1] proc isColor*(name: string): bool = @@ -403,7 +405,7 @@ proc isColor*(name: string): bool = else: result = binaryStrSearch(colorNames, name) >= 0 -proc rgb*(r, g, b: range[0..255]): TColor = +proc rgb*(r, g, b: range[0..255]): Color = ## constructs a color from RGB values. result = rawRGB(r, g, b) diff --git a/lib/pure/complex.nim b/lib/pure/complex.nim index 1392b73aa..d31d56f83 100644 --- a/lib/pure/complex.nim +++ b/lib/pure/complex.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2010 Andreas Rumpf # # See the file "copying.txt", included in this @@ -25,9 +25,11 @@ const type - TComplex* = tuple[re, im: float] + Complex* = tuple[re, im: float] ## a complex number, consisting of a real and an imaginary part +{.deprecated: [TComplex: Complex].} + proc `==` *(x, y: TComplex): bool = ## Compare two complex numbers `x` and `y` for equality. result = x.re == y.re and x.im == y.im diff --git a/lib/pure/concurrency/cpuload.nim b/lib/pure/concurrency/cpuload.nim index 3cf6a7392..74a639be1 100644 --- a/lib/pure/concurrency/cpuload.nim +++ b/lib/pure/concurrency/cpuload.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2014 Andreas Rumpf # # See the file "copying.txt", included in this diff --git a/lib/pure/concurrency/threadpool.nim b/lib/pure/concurrency/threadpool.nim index e0a2ac678..dfde610f2 100644 --- a/lib/pure/concurrency/threadpool.nim +++ b/lib/pure/concurrency/threadpool.nim @@ -1,13 +1,13 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2014 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # -## Implements Nimrod's 'spawn'. +## Implements Nim's 'spawn'. when not compileOption("threads"): {.error: "Threadpool requires --threads:on option.".} diff --git a/lib/pure/cookies.nim b/lib/pure/cookies.nim index 54ca164c7..c85f60915 100644 --- a/lib/pure/cookies.nim +++ b/lib/pure/cookies.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -11,7 +11,7 @@ import strtabs, times -proc parseCookies*(s: string): PStringTable = +proc parseCookies*(s: string): StringTableRef = ## parses cookies into a string table. result = newStringTable(modeCaseInsensitive) var i = 0 @@ -39,7 +39,7 @@ proc setCookie*(key, value: string, domain = "", path = "", if path != "": result.add("; Path=" & path) if expires != "": result.add("; Expires=" & expires) -proc setCookie*(key, value: string, expires: TTimeInfo, +proc setCookie*(key, value: string, expires: TimeInfo, domain = "", path = "", noName = false): string = ## Creates a command in the format of ## ``Set-Cookie: key=value; Domain=...; ...`` @@ -50,7 +50,7 @@ proc setCookie*(key, value: string, expires: TTimeInfo, format(expires, "ddd',' dd MMM yyyy HH:mm:ss 'UTC'"), noName) when isMainModule: - var tim = TTime(int(getTime()) + 76 * (60 * 60 * 24)) + var tim = Time(int(getTime()) + 76 * (60 * 60 * 24)) echo(setCookie("test", "value", tim.getGMTime())) diff --git a/lib/pure/dynlib.nim b/lib/pure/dynlib.nim index 54a553173..77ef20ad9 100644 --- a/lib/pure/dynlib.nim +++ b/lib/pure/dynlib.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -12,7 +12,9 @@ ## Windows ``LoadLibrary``. type - TLibHandle* = pointer ## a handle to a dynamically loaded library + LibHandle* = pointer ## a handle to a dynamically loaded library + +{.deprecated: [TLibHandle: LibHandle].} proc loadLib*(path: string, global_symbols=false): TLibHandle ## loads a library from `path`. Returns nil if the library could not diff --git a/lib/pure/encodings.nim b/lib/pure/encodings.nim index 633ea6020..f10c4e40b 100644 --- a/lib/pure/encodings.nim +++ b/lib/pure/encodings.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2014 Andreas Rumpf # # See the file "copying.txt", included in this @@ -14,18 +14,20 @@ import os, parseutils, strutils when not defined(windows): type - TConverter = object - PConverter* = ptr TConverter ## can convert between two character sets + ConverterObj = object + EncodingConverter* = ptr ConverterObj ## can convert between two character sets else: type - TCodePage = distinct int32 - PConverter* = object - dest, src: TCodePage + CodePage = distinct int32 + EncodingConverter* = object + dest, src: CodePage type - EInvalidEncoding* = object of EInvalidValue ## exception that is raised - ## for encoding errors + EncodingError* = object of ValueError ## exception that is raised + ## for encoding errors + +{.deprecated: [EInvalidEncoding: EncodingError, PConverter: EncodingConverter].} when defined(windows): proc eqEncodingNames(a, b: string): bool = @@ -214,26 +216,26 @@ when defined(windows): defaultChar: array[0..1, char] leadByte: array[0..12-1, char] - proc getCPInfo(codePage: TCodePage, lpCPInfo: var TCpInfo): int32 {. + proc getCPInfo(codePage: CodePage, lpCPInfo: var TCpInfo): int32 {. stdcall, importc: "GetCPInfo", dynlib: "kernel32".} - proc nameToCodePage(name: string): TCodePage = + proc nameToCodePage(name: string): CodePage = var nameAsInt: int if parseInt(name, nameAsInt) == 0: nameAsInt = -1 for no, na in items(winEncodings): - if no == nameAsInt or eqEncodingNames(na, name): return TCodePage(no) - result = TCodePage(-1) + if no == nameAsInt or eqEncodingNames(na, name): return CodePage(no) + result = CodePage(-1) - proc codePageToName(c: TCodePage): string = + proc codePageToName(c: CodePage): string = for no, na in items(winEncodings): if no == int(c): return if na.len != 0: na else: $no result = "" - proc getACP(): TCodePage {.stdcall, importc: "GetACP", dynlib: "kernel32".} + proc getACP(): CodePage {.stdcall, importc: "GetACP", dynlib: "kernel32".} proc multiByteToWideChar( - codePage: TCodePage, + codePage: CodePage, dwFlags: int32, lpMultiByteStr: cstring, cbMultiByte: cint, @@ -242,7 +244,7 @@ when defined(windows): stdcall, importc: "MultiByteToWideChar", dynlib: "kernel32".} proc wideCharToMultiByte( - codePage: TCodePage, + codePage: CodePage, dwFlags: int32, lpWideCharStr: cstring, cchWideChar: cint, diff --git a/lib/pure/endians.nim b/lib/pure/endians.nim index 73017464d..6e33d4624 100644 --- a/lib/pure/endians.nim +++ b/lib/pure/endians.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this diff --git a/lib/pure/events.nim b/lib/pure/events.nim index 5830d9109..7868050d1 100644 --- a/lib/pure/events.nim +++ b/lib/pure/events.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2011 Alex Mitchell # # See the file "copying.txt", included in this @@ -14,10 +14,10 @@ ## it was inspired by Python's PyEE module. There are two ways you can use ## events: one is a python-inspired way; the other is more of a C-style way. ## -## .. code-block:: Nimrod +## .. code-block:: Nim ## var ee = initEventEmitter() -## var genericargs: TEventArgs -## proc handleevent(e: TEventArgs) = +## var genericargs: EventArgs +## proc handleevent(e: EventArgs) = ## echo("Handled!") ## ## # Python way @@ -27,21 +27,24 @@ ## # C/Java way ## # Declare a type ## type -## TSomeObject = object of TObject -## SomeEvent: TEventHandler -## var myobj: TSomeObject +## SomeObject = object of RootObj +## SomeEvent: EventHandler +## var myobj: SomeObject ## myobj.SomeEvent = initEventHandler("SomeEvent") ## myobj.SomeEvent.addHandler(handleevent) ## ee.emit(myobj.SomeEvent, genericargs) type - TEventArgs* = object of TObject ## Base object for event arguments that are passed to callback functions. - TEventHandler* = tuple[name: string, handlers: seq[proc(e:TEventArgs) {.closure.}]] ## An eventhandler for an event. + EventArgs* = object of RootObj ## Base object for event arguments that are passed to callback functions. + EventHandler* = tuple[name: string, handlers: seq[proc(e: EventArgs) {.closure.}]] ## An eventhandler for an event. type - TEventEmitter* = object {.pure, final.} ## An object that fires events and holds event handlers for an object. - s: seq[TEventHandler] - EInvalidEvent* = object of EInvalidValue + EventEmitter* = object ## An object that fires events and holds event handlers for an object. + s: seq[EventHandler] + EventError* = object of ValueError + +{.deprecated: [TEventArgs: EventArgs, TEventHandler: EventHandler, + TEventEmitter: EventEmitter, EInvalidEvent: EventError].} proc initEventHandler*(name: string): TEventHandler = ## Initializes an EventHandler with the specified name and returns it. diff --git a/lib/pure/fsmonitor.nim b/lib/pure/fsmonitor.nim index b35466771..cfee8d0ea 100644 --- a/lib/pure/fsmonitor.nim +++ b/lib/pure/fsmonitor.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Dominik Picheta # # See the file "copying.txt", included in this @@ -25,13 +25,13 @@ else: import inotify, os, asyncio, tables type - PFSMonitor* = ref TFSMonitor - TFSMonitor = object of TObject + FSMonitor* = ref FSMonitorObj + FSMonitorObj = object of RootObj fd: cint - handleEvent: proc (m: PFSMonitor, ev: TMonitorEvent) {.closure.} + handleEvent: proc (m: FSMonitor, ev: MonitorEvent) {.closure.} targets: TTable[cint, string] - TMonitorEventType* = enum ## Monitor event type + MonitorEventType* = enum ## Monitor event type MonitorAccess, ## File was accessed. MonitorAttrib, ## Metadata changed. MonitorCloseWrite, ## Writtable file was closed. @@ -45,8 +45,8 @@ type MonitorOpen, ## File was opened. MonitorAll ## Filter for all event types. - TMonitorEvent* = object - case kind*: TMonitorEventType ## Type of the event. + MonitorEvent* = object + case kind*: MonitorEventType ## Type of the event. of MonitorMoveSelf, MonitorMoved: oldPath*: string ## Old absolute location newPath*: string ## New absolute location @@ -58,6 +58,9 @@ type ## watched. wd*: cint ## Watch descriptor. +{.deprecated: [PFSMonitor: FSMonitor, TFSMonitor: FSMonitorObj, + TMonitorEventType: MonitorEventType, TMonitorEvent: MonitorEvent].} + const MaxEvents = 100 @@ -67,7 +70,7 @@ proc newMonitor*(): PFSMonitor = result.targets = initTable[cint, string]() result.fd = inotifyInit() if result.fd < 0: - OSError(OSLastError()) + raiseOSError(osLastError()) proc add*(monitor: PFSMonitor, target: string, filters = {MonitorAll}): cint {.discardable.} = @@ -101,7 +104,7 @@ proc del*(monitor: PFSMonitor, wd: cint) = ## ## If ``wd`` is not a part of ``monitor`` an EOS error is raised. if inotifyRmWatch(monitor.fd, wd) < 0: - OSError(OSLastError()) + raiseOSError(osLastError()) proc getEvent(m: PFSMonitor, fd: cint): seq[TMonitorEvent] = result = @[] @@ -197,18 +200,19 @@ proc register*(d: PDispatcher, monitor: PFSMonitor, d.register(deleg) when isMainModule: - var disp = newDispatcher() - var monitor = newMonitor() - echo monitor.add("/home/dom/inotifytests/") - disp.register(monitor, - proc (m: PFSMonitor, ev: TMonitorEvent) = - echo("Got event: ", ev.kind) - if ev.kind == MonitorMoved: - echo("From ", ev.oldPath, " to ", ev.newPath) - echo("Name is ", ev.name) - else: - echo("Name ", ev.name, " fullname ", ev.fullName)) - - while true: - if not disp.poll(): break - + proc main = + var disp = newDispatcher() + var monitor = newMonitor() + echo monitor.add("/home/dom/inotifytests/") + disp.register(monitor, + proc (m: PFSMonitor, ev: TMonitorEvent) = + echo("Got event: ", ev.kind) + if ev.kind == MonitorMoved: + echo("From ", ev.oldPath, " to ", ev.newPath) + echo("Name is ", ev.name) + else: + echo("Name ", ev.name, " fullname ", ev.fullName)) + + while true: + if not disp.poll(): break + main() diff --git a/lib/pure/ftpclient.nim b/lib/pure/ftpclient.nim index d4922d1ab..ccb0929f6 100644 --- a/lib/pure/ftpclient.nim +++ b/lib/pure/ftpclient.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Dominik Picheta # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -14,8 +14,8 @@ import sockets, strutils, parseutils, times, os, asyncio ## by `RFC 959 <http://tools.ietf.org/html/rfc959>`_. ## ## This module provides both a synchronous and asynchronous implementation. -## The asynchronous implementation requires you to use the ``AsyncFTPClient`` -## function. You are then required to register the ``PAsyncFTPClient`` with a +## The asynchronous implementation requires you to use the ``asyncFTPClient`` +## function. You are then required to register the ``AsyncFTPClient`` with a ## asyncio dispatcher using the ``register`` function. Take a look at the ## asyncio module documentation for more information. ## @@ -24,64 +24,63 @@ import sockets, strutils, parseutils, times, os, asyncio ## ## Here is some example usage of this module: ## -## .. code-block:: Nimrod -## var ftp = FTPClient("example.org", user = "user", pass = "pass") +## .. code-block:: Nim +## var ftp = ftpClient("example.org", user = "user", pass = "pass") ## ftp.connect() ## ftp.retrFile("file.ext", "file.ext") ## ## **Warning:** The API of this module is unstable, and therefore is subject ## to change. - type - TFTPClient* = object of TObject + FTPClientObj* = object of RootObj case isAsync: bool of false: - csock: TSocket # Command connection socket - dsock: TSocket # Data connection socket + csock: Socket # Command connection socket + dsock: Socket # Data connection socket else: dummyA, dummyB: pointer # workaround a Nimrod API issue - asyncCSock: PAsyncSocket - asyncDSock: PAsyncSocket - handleEvent*: proc (ftp: PAsyncFTPClient, ev: TFTPEvent){.closure,gcsafe.} - disp: PDispatcher - asyncDSockID: PDelegate + asyncCSock: AsyncSocket + asyncDSock: AsyncSocket + handleEvent*: proc (ftp: AsyncFTPClient, ev: FTPEvent){.closure,gcsafe.} + disp: Dispatcher + asyncDSockID: Delegate user, pass: string address: string - port: TPort + port: Port jobInProgress: bool - job: ref TFTPJob + job: ref FTPJob dsockConnected: bool - PFTPClient* = ref TFTPClient + FTPClient* = ref FTPClientObj FTPJobType* = enum JRetrText, JRetr, JStore - TFTPJob = object + FTPJob = object prc: proc (ftp: PFTPClient, async: bool): bool {.nimcall, gcsafe.} case typ*: FTPJobType of JRetrText: lines: string of JRetr, JStore: - file: TFile + file: File filename: string - total: biggestInt # In bytes. - progress: biggestInt # In bytes. - oneSecond: biggestInt # Bytes transferred in one second. + total: BiggestInt # In bytes. + progress: BiggestInt # In bytes. + oneSecond: BiggestInt # Bytes transferred in one second. lastProgressReport: float # Time toStore: string # Data left to upload (Only used with async) else: nil - PAsyncFTPClient* = ref TAsyncFTPClient ## Async alternative to TFTPClient. - TAsyncFTPClient* = object of TFTPClient + AsyncFTPClient* = ref AsyncFTPClientObj ## Async alternative to TFTPClient. + AsyncFTPClientObj* = object of FTPClientObj FTPEventType* = enum EvTransferProgress, EvLines, EvRetr, EvStore - TFTPEvent* = object ## Event + FTPEvent* = object ## Event filename*: string case typ*: FTPEventType of EvLines: @@ -89,13 +88,19 @@ type of EvRetr, EvStore: ## Retr/Store operation finished. nil of EvTransferProgress: - bytesTotal*: biggestInt ## Bytes total. - bytesFinished*: biggestInt ## Bytes transferred. - speed*: biggestInt ## Speed in bytes/s + bytesTotal*: BiggestInt ## Bytes total. + bytesFinished*: BiggestInt ## Bytes transferred. + speed*: BiggestInt ## Speed in bytes/s currentJob*: FTPJobType ## The current job being performed. - EInvalidReply* = object of ESynch - EFTP* = object of ESynch + ReplyError* = object of IOError + FTPError* = object of IOError + +{.deprecated: [ + TFTPClient: FTPClientObj, TFTPJob: FTPJob, PAsyncFTPClient: AsyncFTPClient, + TAsyncFTPClient: AsyncFTPClientObj, TFTPEvent: FTPEvent, + EInvalidReply: ReplyError, EFTP: FTPError +].} proc ftpClient*(address: string, port = TPort(21), user, pass = ""): PFTPClient = diff --git a/lib/pure/future.nim b/lib/pure/future.nim index b7df05207..c467d2c73 100644 --- a/lib/pure/future.nim +++ b/lib/pure/future.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2014 Dominik Picheta # # See the file "copying.txt", included in this diff --git a/lib/pure/gentabs.nim b/lib/pure/gentabs.nim index 617473c14..87a55ea1e 100644 --- a/lib/pure/gentabs.nim +++ b/lib/pure/gentabs.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -12,6 +12,8 @@ ## may be any Nimrod or user defined type. This module supports matching ## of keys in case-sensitive, case-insensitive and style-insensitive modes. +{.deprecated.} + import os, hashes, strutils diff --git a/lib/pure/hashes.nim b/lib/pure/hashes.nim index 740355e55..30daaf2dc 100644 --- a/lib/pure/hashes.nim +++ b/lib/pure/hashes.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -8,13 +8,13 @@ # ## This module implements efficient computations of hash values for diverse -## Nimrod types. All the procs are based on these two building blocks: the `!& +## Nim types. All the procs are based on these two building blocks: the `!& ## proc <#!&>`_ used to start or mix a hash value, and the `!$ proc <#!$>`_ ## used to *finish* the hash value. If you want to implement hash procs for ## your custom types you will end up writing the following kind of skeleton of ## code: ## -## .. code-block:: nimrod +## .. code-block:: Nim ## proc hash(x: Something): THash = ## ## Computes a THash from `x`. ## var h: THash = 0 @@ -29,7 +29,7 @@ ## like for example objects made up of ``strings``, you can simply hash ## together the hash value of the individual fields: ## -## .. code-block:: nimrod +## .. code-block:: Nim ## proc hash(x: Something): THash = ## ## Computes a THash from `x`. ## var h: THash = 0 diff --git a/lib/pure/htmlgen.nim b/lib/pure/htmlgen.nim index b9d6aec7b..a1440b6f4 100644 --- a/lib/pure/htmlgen.nim +++ b/lib/pure/htmlgen.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2014 Andreas Rumpf # # See the file "copying.txt", included in this @@ -18,13 +18,13 @@ ## ## Example: ## -## .. code-block:: nimrod -## var nim = "Nimrod" -## echo h1(a(href="http://nimrod-lang.org", nim)) +## .. code-block:: Nim +## var nim = "Nim" +## echo h1(a(href="http://nim-lang.org", nim)) ## ## Writes the string:: ## -## <h1><a href="http://nimrod-lang.org">Nimrod</a></h1> +## <h1><a href="http://nim-lang.org">Nim</a></h1> ## import @@ -53,8 +53,7 @@ proc delete[T](s: var seq[T], attr: T): bool = setLen(s, L-1) result = true -proc xmlCheckedTag*(e: PNimrodNode, tag: string, - optAttr = "", reqAttr = "", +proc xmlCheckedTag*(e: PNimrodNode, tag: string, optAttr = "", reqAttr = "", isLeaf = false): PNimrodNode {.compileTime.} = ## use this procedure to define a new XML tag @@ -484,7 +483,7 @@ macro `var`*(e: expr): expr {.immediate.} = result = xmlCheckedTag(e, "var", commonAttr) when isMainModule: - var nim = "Nimrod" - echo h1(a(href="http://nimrod-code.org", nim)) + var nim = "Nim" + echo h1(a(href="http://nim-lang.org", nim)) echo form(action="test", `accept-charset` = "Content-Type") diff --git a/lib/pure/htmlparser.nim b/lib/pure/htmlparser.nim index c38eb7063..54e917110 100644 --- a/lib/pure/htmlparser.nim +++ b/lib/pure/htmlparser.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2013 Andreas Rumpf # # See the file "copying.txt", included in this @@ -13,7 +13,7 @@ ## It can be used to parse a wild HTML document and output it as valid XHTML ## document (well, if you are lucky): ## -## .. code-block:: nimrod +## .. code-block:: Nim ## ## echo loadHtml("mydirty.html") ## @@ -29,7 +29,7 @@ ## and write back the modified version. In this case we look for hyperlinks ## ending with the extension ``.rst`` and convert them to ``.html``. ## -## .. code-block:: nimrod +## .. code-block:: Nim ## ## import htmlparser ## import xmltree # To use '$' for PXmlNode diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim index 9bacc80d6..3fbb04fc8 100644 --- a/lib/pure/httpclient.nim +++ b/lib/pure/httpclient.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2010 Dominik Picheta, Andreas Rumpf # # See the file "copying.txt", included in this @@ -21,7 +21,7 @@ ## This example uses HTTP GET to retrieve ## ``http://google.com`` ## -## .. code-block:: nimrod +## .. code-block:: Nim ## echo(getContent("http://google.com")) ## ## Using HTTP POST @@ -31,7 +31,7 @@ ## uses ``multipart/form-data`` as the ``Content-Type`` to send the HTML to ## the server. ## -## .. code-block:: nimrod +## .. code-block:: Nim ## var headers: string = "Content-Type: multipart/form-data; boundary=xyz\c\L" ## var body: string = "--xyz\c\L" ## # soap 1.2 output @@ -54,7 +54,7 @@ ## on many operating systems. httpclient will use SSL automatically if you give ## any of the functions a url with the ``https`` schema, for example: ## ``https://github.com/``, you also have to compile with ``ssl`` defined like so: -## ``nimrod c -d:ssl ...``. +## ``nim c -d:ssl ...``. ## ## Timeouts ## ======== @@ -80,34 +80,38 @@ import asyncnet, asyncdispatch import rawsockets type - TResponse* = tuple[ + Response* = tuple[ version: string, status: string, - headers: PStringTable, + headers: StringTableRef, body: string] - PProxy* = ref object + Proxy* = ref object url*: TUrl auth*: string - EInvalidProtocol* = object of ESynch ## exception that is raised when server + ProtocolError* = object of IOError ## exception that is raised when server ## does not conform to the implemented ## protocol - EHttpRequestErr* = object of ESynch ## Thrown in the ``getContent`` proc - ## and ``postContent`` proc, - ## when the server returns an error + HttpRequestError* = object of IOError ## Thrown in the ``getContent`` proc + ## and ``postContent`` proc, + ## when the server returns an error -const defUserAgent* = "Nimrod httpclient/0.1" +{.deprecated: [TResponse: Response, PProxy: Proxy, + EInvalidProtocol: ProtocolError, EHttpRequestErr: HttpRequestError +].} + +const defUserAgent* = "Nim httpclient/0.1" proc httpError(msg: string) = - var e: ref EInvalidProtocol + var e: ref ProtocolError new(e) e.msg = msg raise e proc fileError(msg: string) = - var e: ref EIO + var e: ref IOError new(e) e.msg = msg raise e @@ -232,7 +236,7 @@ proc parseResponse(s: TSocket, getBody: bool, timeout: int): TResponse = result.body = "" type - THttpMethod* = enum ## the requested HttpMethod + HttpMethod* = enum ## the requested HttpMethod httpHEAD, ## Asks for the response identical to the one that would ## correspond to a GET request, but without the response ## body. @@ -250,6 +254,8 @@ type httpCONNECT ## Converts the request connection to a transparent ## TCP/IP tunnel, usually used for proxies. +{.deprecated: [THttpMethod: HttpMethod].} + when not defined(ssl): type PSSLContext = ref object let defaultSSLContext: PSSLContext = nil @@ -288,7 +294,7 @@ proc request*(url: string, httpMethod = httpGET, extraHeaders = "", add(headers, "\c\L") var s = socket() - if s == InvalidSocket: osError(osLastError()) + if s == InvalidSocket: raiseOSError(osLastError()) var port = sockets.TPort(80) if r.scheme == "https": when defined(ssl): @@ -431,16 +437,18 @@ proc generateHeaders(r: TURL, httpMethod: THttpMethod, add(result, "\c\L") type - PAsyncHttpClient* = ref object - socket: PAsyncSocket + AsyncHttpClient* = ref object + socket: AsyncSocket connected: bool currentURL: TURL ## Where we are currently connected. - headers: PStringTable + headers: StringTableRef maxRedirects: int userAgent: string +{.deprecated: [PAsyncHttpClient: AsyncHttpClient].} + proc newAsyncHttpClient*(userAgent = defUserAgent, - maxRedirects = 5): PAsyncHttpClient = + maxRedirects = 5): AsyncHttpClient = ## Creates a new PAsyncHttpClient instance. ## ## ``userAgent`` specifies the user agent that will be used when making @@ -453,7 +461,7 @@ proc newAsyncHttpClient*(userAgent = defUserAgent, result.userAgent = defUserAgent result.maxRedirects = maxRedirects -proc close*(client: PAsyncHttpClient) = +proc close*(client: AsyncHttpClient) = ## Closes any connections held by the HTTP client. if client.connected: client.socket.close() diff --git a/lib/pure/httpserver.nim b/lib/pure/httpserver.nim index 885742b64..a41dc9450 100644 --- a/lib/pure/httpserver.nim +++ b/lib/pure/httpserver.nim @@ -145,7 +145,7 @@ when false: var buf = alloc(contentLength) if recv(client, buf, contentLength) != contentLength: dealloc(buf) - OSError() + raiseOSError() var inp = process.inputStream inp.writeData(buf, contentLength) dealloc(buf) diff --git a/lib/pure/json.nim b/lib/pure/json.nim index 383f924ca..b2c0db3d1 100644 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -1,7 +1,7 @@ # # -# Nimrod's Runtime Library -# (c) Copyright 2012 Andreas Rumpf, Dominik Picheta +# Nim's Runtime Library +# (c) Copyright 2014 Andreas Rumpf, Dominik Picheta # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -35,7 +35,7 @@ import hashes, strutils, lexbase, streams, unicode type - TJsonEventKind* = enum ## enumeration of all events that may occur when parsing + JsonEventKind* = enum ## enumeration of all events that may occur when parsing jsonError, ## an error ocurred during parsing jsonEof, ## end of file reached jsonString, ## a string literal @@ -65,7 +65,7 @@ type tkColon, tkComma - TJsonError* = enum ## enumeration that lists all errors that can occur + JsonError* = enum ## enumeration that lists all errors that can occur errNone, ## no error errInvalidToken, ## invalid token errStringExpected, ## string expected @@ -78,20 +78,23 @@ type errEofExpected, ## EOF expected errExprExpected ## expr expected - TParserState = enum + ParserState = enum stateEof, stateStart, stateObject, stateArray, stateExpectArrayComma, stateExpectObjectComma, stateExpectColon, stateExpectValue - TJsonParser* = object of TBaseLexer ## the parser object. + JsonParser* = object of TBaseLexer ## the parser object. a: string tok: TTokKind - kind: TJsonEventKind - err: TJsonError - state: seq[TParserState] + kind: JsonEventKind + err: JsonError + state: seq[ParserState] filename: string + +{.deprecated: [TJsonEventKind: JsonEventKind, TJsonError: JsonError, + TJsonParser: JsonParser].} const - errorMessages: array [TJsonError, string] = [ + errorMessages: array [JsonError, string] = [ "no error", "invalid token", "string expected", @@ -116,7 +119,7 @@ const "{", "}", "[", "]", ":", "," ] -proc open*(my: var TJsonParser, input: PStream, filename: string) = +proc open*(my: var JsonParser, input: PStream, filename: string) = ## initializes the parser with an input stream. `Filename` is only used ## for nice error messages. lexbase.open(my, input) @@ -125,49 +128,49 @@ proc open*(my: var TJsonParser, input: PStream, filename: string) = my.kind = jsonError my.a = "" -proc close*(my: var TJsonParser) {.inline.} = +proc close*(my: var JsonParser) {.inline.} = ## closes the parser `my` and its associated input stream. lexbase.close(my) -proc str*(my: TJsonParser): string {.inline.} = +proc str*(my: JsonParser): string {.inline.} = ## returns the character data for the events: ``jsonInt``, ``jsonFloat``, ## ``jsonString`` assert(my.kind in {jsonInt, jsonFloat, jsonString}) return my.a -proc getInt*(my: TJsonParser): BiggestInt {.inline.} = +proc getInt*(my: JsonParser): BiggestInt {.inline.} = ## returns the number for the event: ``jsonInt`` assert(my.kind == jsonInt) return parseBiggestInt(my.a) -proc getFloat*(my: TJsonParser): float {.inline.} = +proc getFloat*(my: JsonParser): float {.inline.} = ## returns the number for the event: ``jsonFloat`` assert(my.kind == jsonFloat) return parseFloat(my.a) -proc kind*(my: TJsonParser): TJsonEventKind {.inline.} = +proc kind*(my: JsonParser): JsonEventKind {.inline.} = ## returns the current event type for the JSON parser return my.kind -proc getColumn*(my: TJsonParser): int {.inline.} = +proc getColumn*(my: JsonParser): int {.inline.} = ## get the current column the parser has arrived at. result = getColNumber(my, my.bufpos) -proc getLine*(my: TJsonParser): int {.inline.} = +proc getLine*(my: JsonParser): int {.inline.} = ## get the current line the parser has arrived at. result = my.lineNumber -proc getFilename*(my: TJsonParser): string {.inline.} = +proc getFilename*(my: JsonParser): string {.inline.} = ## get the filename of the file that the parser processes. result = my.filename -proc errorMsg*(my: TJsonParser): string = +proc errorMsg*(my: JsonParser): string = ## returns a helpful error message for the event ``jsonError`` assert(my.kind == jsonError) result = "$1($2, $3) Error: $4" % [ my.filename, $getLine(my), $getColumn(my), errorMessages[my.err]] -proc errorMsgExpected*(my: TJsonParser, e: string): string = +proc errorMsgExpected*(my: JsonParser, e: string): string = ## returns an error message "`e` expected" in the same format as the ## other error messages result = "$1($2, $3) Error: $4" % [ @@ -181,7 +184,7 @@ proc handleHexChar(c: char, x: var int): bool = of 'A'..'F': x = (x shl 4) or (ord(c) - ord('A') + 10) else: result = false # error -proc parseString(my: var TJsonParser): TTokKind = +proc parseString(my: var JsonParser): TTokKind = result = tkString var pos = my.bufpos + 1 var buf = my.buf @@ -239,7 +242,7 @@ proc parseString(my: var TJsonParser): TTokKind = inc(pos) my.bufpos = pos # store back -proc skip(my: var TJsonParser) = +proc skip(my: var JsonParser) = var pos = my.bufpos var buf = my.buf while true: @@ -297,7 +300,7 @@ proc skip(my: var TJsonParser) = break my.bufpos = pos -proc parseNumber(my: var TJsonParser) = +proc parseNumber(my: var JsonParser) = var pos = my.bufpos var buf = my.buf if buf[pos] == '-': @@ -328,7 +331,7 @@ proc parseNumber(my: var TJsonParser) = inc(pos) my.bufpos = pos -proc parseName(my: var TJsonParser) = +proc parseName(my: var JsonParser) = var pos = my.bufpos var buf = my.buf if buf[pos] in IdentStartChars: @@ -337,7 +340,7 @@ proc parseName(my: var TJsonParser) = inc(pos) my.bufpos = pos -proc getTok(my: var TJsonParser): TTokKind = +proc getTok(my: var JsonParser): TTokKind = setLen(my.a, 0) skip(my) # skip whitespace, comments case my.buf[my.bufpos] @@ -381,7 +384,7 @@ proc getTok(my: var TJsonParser): TTokKind = result = tkError my.tok = result -proc next*(my: var TJsonParser) = +proc next*(my: var JsonParser) = ## retrieves the first/next event. This controls the parser. var tk = getTok(my) var i = my.state.len-1 @@ -529,7 +532,10 @@ type of JArray: elems*: seq[PJsonNode] - EJsonParsingError* = object of ValueError ## is raised for a JSON error + JsonParsingError* = object of ValueError ## is raised for a JSON error + +{.deprecated: [EJsonParsingError: JsonParsingError, TJsonNode: JsonNodeObj, + PJsonNode: JsonNode, TJsonNodeKind: JsonNodeKind].} proc raiseParseErr*(p: TJsonParser, msg: string) {.noinline, noreturn.} = ## raises an `EJsonParsingError` exception. diff --git a/lib/pure/lexbase.nim b/lib/pure/lexbase.nim index 0e10b95e4..361374177 100644 --- a/lib/pure/lexbase.nim +++ b/lib/pure/lexbase.nim @@ -1,6 +1,6 @@ # # -# The Nimrod Compiler +# The Nim Compiler # (c) Copyright 2009 Andreas Rumpf # # See the file "copying.txt", included in this @@ -36,6 +36,8 @@ type lineStart: int # index of last line start in buffer fileOpened: bool +{.deprecated: [TBaseLexer: BaseLexer].} + proc open*(L: var TBaseLexer, input: PStream, bufLen: int = 8192) ## inits the TBaseLexer with a stream to read from diff --git a/lib/pure/logging.nim b/lib/pure/logging.nim index 284384b37..a0773f40b 100644 --- a/lib/pure/logging.nim +++ b/lib/pure/logging.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2014 Andreas Rumpf, Dominik Picheta # # See the file "copying.txt", included in this @@ -26,7 +26,7 @@ ## The following example demonstrates logging to three different handlers ## simultaneously: ## -## .. code-block:: nimrod +## .. code-block:: nim ## ## var L = newConsoleLogger() ## var fL = newFileLogger("test.log", fmtStr = verboseFmtStr) @@ -42,7 +42,7 @@ import strutils, os, times type - TLevel* = enum ## logging level + Level* = enum ## logging level lvlAll, ## all levels active lvlDebug, ## debug level (and any above) active lvlInfo, ## info level (and any above) active @@ -52,7 +52,7 @@ type lvlNone ## no levels active const - LevelNames*: array [TLevel, string] = [ + LevelNames*: array [Level, string] = [ "DEBUG", "DEBUG", "INFO", "WARN", "ERROR", "FATAL", "NONE" ] @@ -60,26 +60,29 @@ const verboseFmtStr* = "$date $time " type - PLogger* = ref object of PObject ## abstract logger; the base type of all loggers - levelThreshold*: TLevel ## only messages of level >= levelThreshold + Logger* = ref object of RootObj ## abstract logger; the base type of all loggers + levelThreshold*: Leve l ## only messages of level >= levelThreshold ## should be processed fmtStr: string ## = defaultFmtStr by default, see substituteLog for $date etc. - PConsoleLogger* = ref object of PLogger ## logger that writes the messages to the - ## console + ConsoleLogger* = ref object of Logger ## logger that writes the messages to the + ## console - PFileLogger* = ref object of PLogger ## logger that writes the messages to a file + FileLogger* = ref object of Logger ## logger that writes the messages to a file f: TFile - PRollingFileLogger* = ref object of PFileLogger ## logger that writes the - ## messages to a file and - ## performs log rotation + RollingFileLogger* = ref object of FileLogger ## logger that writes the + ## messages to a file and + ## performs log rotation maxLines: int # maximum number of lines curLine : int baseName: string # initial filename - baseMode: TFileMode # initial file mode + baseMode: FileMode # initial file mode logFiles: int # how many log files already created, e.g. basename.1, basename.2... +{.deprecated: [TLevel: Level, PLogger: Logger, PConsoleLogger: ConsoleLogger, + PFileLogger: FileLogger, PRollingFileLogger: RollingFileLogger].} + proc substituteLog(frmt: string): string = ## converts $date to the current date ## converts $time to the current time @@ -105,7 +108,7 @@ proc substituteLog(frmt: string): string = of "appdir": result.add(app.splitFile.dir) of "appname": result.add(app.splitFile.name) -method log*(logger: PLogger, level: TLevel, +method log*(logger: Logger, level: Level, frmt: string, args: varargs[string, `$`]) {.raises: [EBase], tags: [FTime, FWriteIO, FReadIO].} = ## Override this method in custom loggers. Default implementation does ## nothing. diff --git a/lib/pure/marshal.nim b/lib/pure/marshal.nim index 789f6ad76..7857e9a94 100644 --- a/lib/pure/marshal.nim +++ b/lib/pure/marshal.nim @@ -1,20 +1,20 @@ # # -# Nimrod's Runtime Library -# (c) Copyright 2013 Andreas Rumpf +# Nim's Runtime Library +# (c) Copyright 2014 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # ## This module contains procs for serialization and deseralization of -## arbitrary Nimrod data structures. The serialization format uses JSON. +## arbitrary Nim data structures. The serialization format uses JSON. ## ## **Restriction**: For objects their type is **not** serialized. This means ## essentially that it does not work if the object has some other runtime ## type than its compiletime type: ## -## .. code-block:: nimrod +## .. code-block:: nim ## ## type ## TA = object @@ -211,7 +211,7 @@ proc loadAny(p: var TJsonParser, a: TAny, t: var TTable[biggestInt, pointer]) = raiseParseErr(p, "float expected") of akRange: loadAny(p, a.skipRange, t) -proc loadAny(s: PStream, a: TAny, t: var TTable[biggestInt, pointer]) = +proc loadAny(s: PStream, a: TAny, t: var TTable[BiggestInt, pointer]) = var p: TJsonParser open(p, s, "unknown file") next(p) diff --git a/lib/pure/matchers.nim b/lib/pure/matchers.nim index 2db7fa660..c3ad7235f 100644 --- a/lib/pure/matchers.nim +++ b/lib/pure/matchers.nim @@ -1,7 +1,7 @@ # # -# Nimrod's Runtime Library -# (c) Copyright 2012 Andreas Rumpf +# Nim's Runtime Library +# (c) Copyright 2014 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -44,7 +44,7 @@ proc validEmailAddress*(s: string): bool {.noSideEffect, "aero", "jobs", "museum": return true return false -proc parseInt*(s: string, value: var int, validRange: TSlice[int]) {. +proc parseInt*(s: string, value: var int, validRange: Slice[int]) {. noSideEffect, rtl, extern: "nmatchParseInt".} = ## parses `s` into an integer in the range `validRange`. If successful, ## `value` is modified to contain the result. Otherwise no exception is @@ -53,7 +53,7 @@ proc parseInt*(s: string, value: var int, validRange: TSlice[int]) {. var x = value try: discard parseutils.parseInt(s, x, 0) - except EOverflow: + except OverflowError: discard if x in validRange: value = x diff --git a/lib/pure/math.nim b/lib/pure/math.nim index 99849d98e..c6a0305d2 100644 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -1,7 +1,7 @@ # # -# Nimrod's Runtime Library -# (c) Copyright 2012 Andreas Rumpf +# Nim's Runtime Library +# (c) Copyright 2014 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -9,7 +9,7 @@ ## Constructive mathematics is naturally typed. -- Simon Thompson ## -## Basic math routines for Nimrod. +## Basic math routines for Nim. ## This module is available for the `JavaScript target ## <backends.html#the-javascript-target>`_. @@ -41,8 +41,8 @@ const ## for Nimrod's ``float`` type. type - TFloatClass* = enum ## describes the class a floating point value belongs to. - ## This is the type that is returned by `classify`. + FloatClass* = enum ## describes the class a floating point value belongs to. + ## This is the type that is returned by `classify`. fcNormal, ## value is an ordinary nonzero floating point value fcSubnormal, ## value is a subnormal (a very small) floating point value fcZero, ## value is zero @@ -51,10 +51,10 @@ type fcInf, ## value is positive infinity fcNegInf ## value is negative infinity -proc classify*(x: float): TFloatClass = +proc classify*(x: float): FloatClass = ## classifies a floating point value. Returns `x`'s class as specified by - ## `TFloatClass`. - + ## `FloatClass`. + # JavaScript and most C compilers have no classify: if x == 0.0: if 1.0/x == Inf: @@ -287,12 +287,14 @@ proc random[T](a: openArray[T]): T = result = a[random(a.low..a.len)] type - TRunningStat* {.pure,final.} = object ## an accumulator for statistical data - n*: int ## number of pushed data - sum*, min*, max*, mean*: float ## self-explaining + RunningStat* = object ## an accumulator for statistical data + n*: int ## number of pushed data + sum*, min*, max*, mean*: float ## self-explaining oldM, oldS, newS: float -proc push*(s: var TRunningStat, x: float) = +{.deprecated: [TFloatClass: FloatClass, TRunningStat: RunningStat].} + +proc push*(s: var RunningStat, x: float) = ## pushes a value `x` for processing inc(s.n) # See Knuth TAOCP vol 2, 3rd edition, page 232 @@ -313,16 +315,16 @@ proc push*(s: var TRunningStat, x: float) = s.oldS = s.newS s.sum = s.sum + x -proc push*(s: var TRunningStat, x: int) = +proc push*(s: var RunningStat, x: int) = ## pushes a value `x` for processing. `x` is simply converted to ``float`` ## and the other push operation is called. push(s, toFloat(x)) -proc variance*(s: TRunningStat): float = +proc variance*(s: RunningStat): float = ## computes the current variance of `s` if s.n > 1: result = s.newS / (toFloat(s.n - 1)) -proc standardDeviation*(s: TRunningStat): float = +proc standardDeviation*(s: RunningStat): float = ## computes the current standard deviation of `s` result = sqrt(variance(s)) diff --git a/lib/pure/md5.nim b/lib/pure/md5.nim index 0328932fd..322dbbe1d 100644 --- a/lib/pure/md5.nim +++ b/lib/pure/md5.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2010 Andreas Rumpf # # See the file "copying.txt", included in this diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim index 5577fa5cf..8712df7f6 100644 --- a/lib/pure/memfiles.nim +++ b/lib/pure/memfiles.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2014 Nimrod Contributors # # See the file "copying.txt", included in this @@ -22,7 +22,7 @@ else: import os type - TMemFile* = object {.pure.} ## represents a memory mapped file + MemFile* = object ## represents a memory mapped file mem*: pointer ## a pointer to the memory mapped file. The pointer ## can be used directly to change the contents of the ## file, if it was opened with write access. @@ -34,8 +34,9 @@ type else: handle: cint +{.deprecated: [TMemFile: MemFile].} -proc mapMem*(m: var TMemFile, mode: FileMode = fmRead, +proc mapMem*(m: var MemFile, mode: FileMode = fmRead, mappedSize = -1, offset = 0): pointer = var readonly = mode == fmRead when defined(windows): @@ -60,27 +61,27 @@ proc mapMem*(m: var TMemFile, mode: FileMode = fmRead, osError(osLastError()) -proc unmapMem*(f: var TMemFile, p: pointer, size: int) = +proc unmapMem*(f: var MemFile, p: pointer, size: int) = ## unmaps the memory region ``(p, <p+size)`` of the mapped file `f`. ## All changes are written back to the file system, if `f` was opened ## with write access. ``size`` must be of exactly the size that was requested ## via ``mapMem``. when defined(windows): - if unmapViewOfFile(p) == 0: osError(osLastError()) + if unmapViewOfFile(p) == 0: raiseOSError(osLastError()) else: - if munmap(p, size) != 0: osError(osLastError()) + if munmap(p, size) != 0: raiseOSError(osLastError()) proc open*(filename: string, mode: FileMode = fmRead, - mappedSize = -1, offset = 0, newFileSize = -1): TMemFile = + mappedSize = -1, offset = 0, newFileSize = -1): MemFile = ## opens a memory mapped file. If this fails, ``EOS`` is raised. ## `newFileSize` can only be set if the file does not exist and is opened ## with write access (e.g., with fmReadWrite). `mappedSize` and `offset` ## can be used to map only a slice of the file. Example: ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## var - ## mm, mm_full, mm_half: TMemFile + ## mm, mm_full, mm_half: MemFile ## ## mm = memfiles.open("/tmp/test.mmap", mode = fmWrite, newFileSize = 1024) # Create a new file ## mm.close() @@ -100,11 +101,11 @@ proc open*(filename: string, mode: FileMode = fmRead, result.size = 0 when defined(windows): - template fail(errCode: TOSErrorCode, msg: expr) = + template fail(errCode: OSErrorCode, msg: expr) = rollback() if result.fHandle != 0: discard closeHandle(result.fHandle) if result.mapHandle != 0: discard closeHandle(result.mapHandle) - osError(errCode) + raiseOSError(errCode) # return false #raise newException(EIO, msg) @@ -169,10 +170,10 @@ proc open*(filename: string, mode: FileMode = fmRead, else: result.size = fileSize.int else: - template fail(errCode: TOSErrorCode, msg: expr) = + template fail(errCode: OSErrorCode, msg: expr) = rollback() if result.handle != 0: discard close(result.handle) - osError(errCode) + raiseOSError(errCode) var flags = if readonly: O_RDONLY else: O_RDWR @@ -214,12 +215,12 @@ proc open*(filename: string, mode: FileMode = fmRead, if result.mem == cast[pointer](MAP_FAILED): fail(osLastError(), "file mapping failed") -proc close*(f: var TMemFile) = +proc close*(f: var MemFile) = ## closes the memory mapped file `f`. All changes are written back to the ## file system, if `f` was opened with write access. var error = false - var lastErr: TOSErrorCode + var lastErr: OSErrorCode when defined(windows): if f.fHandle != INVALID_HANDLE_VALUE: @@ -242,5 +243,5 @@ proc close*(f: var TMemFile) = else: f.handle = 0 - if error: osError(lastErr) + if error: raiseOSError(lastErr) diff --git a/lib/pure/mersenne.nim b/lib/pure/mersenne.nim index 2b12cce73..a6a781cb8 100644 --- a/lib/pure/mersenne.nim +++ b/lib/pure/mersenne.nim @@ -1,24 +1,26 @@ import unsigned type - TMersenneTwister* = object + MersenneTwister* = object mt: array[0..623, uint32] index: int -proc newMersenneTwister*(seed: int): TMersenneTwister = +{.deprecated: [TMersenneTwister: MersenneTwister].} + +proc newMersenneTwister*(seed: int): MersenneTwister = result.index = 0 result.mt[0]= uint32(seed) for i in 1..623'u32: result.mt[i]= (0x6c078965'u32 * (result.mt[i-1] xor (result.mt[i-1] shr 30'u32)) + i) -proc generateNumbers(m: var TMersenneTwister) = +proc generateNumbers(m: var MersenneTwister) = for i in 0..623: var y = (m.mt[i] and 0x80000000'u32) + (m.mt[(i+1) mod 624] and 0x7fffffff'u32) m.mt[i] = m.mt[(i+397) mod 624] xor uint32(y shr 1'u32) if (y mod 2'u32) != 0: m.mt[i] = m.mt[i] xor 0x9908b0df'u32 -proc getNum*(m: var TMersenneTwister): int = +proc getNum*(m: var MersenneTwister): int = if m.index == 0: generateNumbers(m) var y = m.mt[m.index] @@ -29,11 +31,9 @@ proc getNum*(m: var TMersenneTwister): int = m.index = (m.index+1) mod 624 return int(y) - - # Test when isMainModule: var mt = newMersenneTwister(2525) for i in 0..99: - echo mt.getNum \ No newline at end of file + echo mt.getNum diff --git a/lib/pure/mimetypes.nim b/lib/pure/mimetypes.nim index 92baf0549..a52ba4ebe 100644 --- a/lib/pure/mimetypes.nim +++ b/lib/pure/mimetypes.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Dominik Picheta # # See the file "copying.txt", included in this @@ -10,8 +10,10 @@ ## This module implements a mimetypes database import strtabs type - TMimeDB* = object - mimes: PStringTable + MimeDB* = object + mimes: StringTableRef + +{.deprecated: [TMimeDB: MimeDB].} const mimes* = { "ez": "application/andrew-inset", @@ -489,20 +491,19 @@ const mimes* = { "vrml": "x-world/x-vrml", "wrl": "x-world/x-vrml"} -proc newMimetypes*(): TMimeDB = +proc newMimetypes*(): MimeDB = ## Creates a new Mimetypes database. The database will contain the most ## common mimetypes. - result.mimes = mimes.newStringTable() -proc getMimetype*(mimedb: TMimeDB, ext: string, default = "text/plain"): string = +proc getMimetype*(mimedb: MimeDB, ext: string, default = "text/plain"): string = ## Gets mimetype which corresponds to ``ext``. Returns ``default`` if ``ext`` ## could not be found. result = mimedb.mimes[ext] if result == "": return default -proc getExt*(mimedb: TMimeDB, mimetype: string, default = "txt"): string = +proc getExt*(mimedb: MimeDB, mimetype: string, default = "txt"): string = ## Gets extension which corresponds to ``mimetype``. Returns ``default`` if ## ``mimetype`` could not be found. Extensions are returned without the ## leading dot. @@ -511,11 +512,11 @@ proc getExt*(mimedb: TMimeDB, mimetype: string, default = "txt"): string = if m == mimetype: result = e -proc register*(mimedb: var TMimeDB, ext: string, mimetype: string) = +proc register*(mimedb: var MimeDB, ext: string, mimetype: string) = ## Adds ``mimetype`` to the ``mimedb``. mimedb.mimes[ext] = mimetype when isMainModule: var m = newMimetypes() echo m.getMimetype("mp4") - echo m.getExt("text/html") \ No newline at end of file + echo m.getExt("text/html") diff --git a/lib/pure/net.nim b/lib/pure/net.nim index 696527467..1e17f1d7a 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2014 Dominik Picheta # # See the file "copying.txt", included in this @@ -11,7 +11,7 @@ {.deadCodeElim: on.} import rawsockets, os, strutils, unsigned, parseutils, times -export TPort, `$`, `==` +export Port, `$`, `==` const useWinVersion = defined(Windows) or defined(nimdoc) @@ -22,25 +22,25 @@ when defined(ssl): when defined(ssl): type - ESSL* = object of ESynch + SSLError* = object of Exception - TSSLCVerifyMode* = enum + SSLCVerifyMode* = enum CVerifyNone, CVerifyPeer - TSSLProtVersion* = enum + SSLProtVersion* = enum protSSLv2, protSSLv3, protTLSv1, protSSLv23 - PSSLContext* = distinct PSSLCTX + SSLContext* = distinct PSSLCTX - TSSLAcceptResult* = enum + SSLAcceptResult* = enum AcceptNoClient = 0, AcceptNoHandshake, AcceptSuccess const BufferSize*: int = 4000 ## size of a buffered socket's buffer type - TSocketImpl* = object ## socket type - fd*: TSocketHandle + SocketImpl* = object ## socket type + fd*: SocketHandle case isBuffered*: bool # determines whether this socket is buffered. of true: buffer*: array[0..BufferSize, char] @@ -57,34 +57,40 @@ type sslPeekChar*: char of false: nil - PSocket* = ref TSocketImpl + Socket* = ref SocketImpl - TSOBool* = enum ## Boolean socket options. + SOBool* = enum ## Boolean socket options. OptAcceptConn, OptBroadcast, OptDebug, OptDontRoute, OptKeepAlive, OptOOBInline, OptReuseAddr - TReadLineResult* = enum ## result for readLineAsync + ReadLineResult* = enum ## result for readLineAsync ReadFullLine, ReadPartialLine, ReadDisconnected, ReadNone - ETimeout* = object of ESynch + TimeoutError* = object of Exception - TSocketFlags* {.pure.} = enum + SocketFlag* {.pure.} = enum Peek, SafeDisconn ## Ensures disconnection exceptions (ECONNRESET, EPIPE etc) are not thrown. -proc isDisconnectionError*(flags: set[TSocketFlags], - lastError: TOSErrorCode): bool = +{.deprecated: [TSocketFlags: SocketFlag, ETimeout: TimeoutError, + TReadLineResult: ReadLineResult, TSOBool: SOBool, PSocket: Socket, + TSocketImpl: SocketImpl, ESSL: SSLError, TSSLCVerifyMode: SSLCVerifyMode, + TSSLProtVersion: SSLProtVersion, PSSLContext: SSLContext, + TSSLAcceptResult: SSLAcceptResult].} + +proc isDisconnectionError*(flags: set[SocketFlag], + lastError: OSErrorCode): bool = ## Determines whether ``lastError`` is a disconnection error. Only does this ## if flags contains ``SafeDisconn``. when useWinVersion: - TSocketFlags.SafeDisconn in flags and + SocketFlag.SafeDisconn in flags and lastError.int32 in {WSAECONNRESET, WSAECONNABORTED, WSAENETRESET, WSAEDISCON, ERROR_NETNAME_DELETED} else: - TSocketFlags.SafeDisconn in flags and + SocketFlag.SafeDisconn in flags and lastError.int32 in {ECONNRESET, EPIPE, ENETRESET} -proc toOSFlags*(socketFlags: set[TSocketFlags]): cint = +proc toOSFlags*(socketFlags: set[SocketFlag]): cint = ## Converts the flags into the underlying OS representation. for f in socketFlags: case f diff --git a/lib/pure/nimprof.nim b/lib/pure/nimprof.nim index 6f94d0656..6b8fe1ce5 100644 --- a/lib/pure/nimprof.nim +++ b/lib/pure/nimprof.nim @@ -1,13 +1,13 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # -## Profiling support for Nimrod. This is an embedded profiler that requires +## Profiling support for Nim. This is an embedded profiler that requires ## ``--profiler:on``. You only need to import this module to get a profiling ## report at program exit. @@ -64,7 +64,7 @@ when withThreads: var profilingLock: TLock - InitLock profilingLock + initLock profilingLock proc hookAux(st: TStackTrace, costs: int) = # this is quite performance sensitive! diff --git a/lib/pure/numeric.nim b/lib/pure/numeric.nim index 8ef5fabda..9b298c0a0 100644 --- a/lib/pure/numeric.nim +++ b/lib/pure/numeric.nim @@ -1,16 +1,17 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2013 Robert Persson # # See the file "copying.txt", included in this # distribution, for details about the copyright. # +type OneVarFunction* = proc (x: float): float -type TOneVarFunction* =proc (x:float):float +{.deprecated: [TOneVarFunction: OneVarFunction].} -proc brent*(xmin,xmax:float ,function:TOneVarFunction, tol:float,maxiter=1000): +proc brent*(xmin,xmax:float, function:OneVarFunction, tol:float,maxiter=1000): tuple[rootx, rooty: float, success: bool]= ## Searches `function` for a root between `xmin` and `xmax` ## using brents method. If the function value at `xmin`and `xmax` has the diff --git a/lib/pure/oids.nim b/lib/pure/oids.nim index 2843e6c65..c0bfb7c08 100644 --- a/lib/pure/oids.nim +++ b/lib/pure/oids.nim @@ -1,13 +1,13 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2013 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # -## Nimrod OID support. An OID is a global ID that consists of a timestamp, +## Nim OID support. An OID is a global ID that consists of a timestamp, ## a unique counter and a random value. This combination should suffice to ## produce a globally distributed unique ID. This implementation was extracted ## from the Mongodb interface and it thus binary compatible with a Mongo OID. @@ -18,11 +18,13 @@ import times, endians type - Toid* {.pure, final.} = object ## an OID + Oid* = object ## an OID time: int32 ## fuzz: int32 ## count: int32 ## +{.deprecated: [Toid: Oid].} + proc hexbyte*(hex: char): int = case hex of '0'..'9': result = (ord(hex) - ord('0')) @@ -30,7 +32,7 @@ proc hexbyte*(hex: char): int = of 'A'..'F': result = (ord(hex) - ord('A') + 10) else: discard -proc parseOid*(str: cstring): TOid = +proc parseOid*(str: cstring): Oid = ## parses an OID. var bytes = cast[cstring](addr(result.time)) var i = 0 @@ -38,7 +40,7 @@ proc parseOid*(str: cstring): TOid = bytes[i] = chr((hexbyte(str[2 * i]) shl 4) or hexbyte(str[2 * i + 1])) inc(i) -proc oidToString*(oid: TOid, str: cstring) = +proc oidToString*(oid: Oid, str: cstring) = const hex = "0123456789abcdef" # work around a compiler bug: var str = str @@ -52,7 +54,7 @@ proc oidToString*(oid: TOid, str: cstring) = inc(i) str[24] = '\0' -proc `$`*(oid: TOid): string = +proc `$`*(oid: Oid): string = result = newString(25) oidToString(oid, result) @@ -60,7 +62,7 @@ var incr: int fuzz: int32 -proc genOid*(): TOid = +proc genOid*(): Oid = ## generates a new OID. proc rand(): cint {.importc: "rand", header: "<stdlib.h>", nodecl.} proc gettime(dummy: ptr cint): cint {.importc: "time", header: "<time.h>".} @@ -79,12 +81,12 @@ proc genOid*(): TOid = result.fuzz = fuzz bigEndian32(addr result.count, addr(i)) -proc generatedTime*(oid: TOid): TTime = +proc generatedTime*(oid: Oid): Time = ## returns the generated timestamp of the OID. var tmp: int32 var dummy = oid.time bigEndian32(addr(tmp), addr(dummy)) - result = TTime(tmp) + result = Time(tmp) when isMainModule: let xo = genOID() diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 483044d0a..0b4cf24c5 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2014 Andreas Rumpf # # See the file "copying.txt", included in this @@ -29,18 +29,23 @@ else: include "system/ansi_c" type - FReadEnv* = object of ReadIOEffect ## effect that denotes a read - ## from an environment variable - FWriteEnv* = object of WriteIOEffect ## effect that denotes a write - ## to an environment variable - - FReadDir* = object of ReadIOEffect ## effect that denotes a write operation to - ## the directory structure - FWriteDir* = object of WriteIOEffect ## effect that denotes a write operation to - ## the directory structure - - TOSErrorCode* = distinct int32 ## Specifies an OS Error Code. - + ReadEnvEffect* = object of ReadIOEffect ## effect that denotes a read + ## from an environment variable + WriteEnvEffect* = object of WriteIOEffect ## effect that denotes a write + ## to an environment variable + + ReadDirEffect* = object of ReadIOEffect ## effect that denotes a write + ## operation to the directory structure + WriteDirEffect* = object of WriteIOEffect ## effect that denotes a write operation to + ## the directory structure + + OSErrorCode* = distinct int32 ## Specifies an OS Error Code. + +{.deprecated: [FReadEnv: ReadEnvEffect, FWriteEnv: WriteEnvEffect, + FReadDir: ReadDirEffect, + FWriteDir: WriteDirEffect, + TOSErrorCode: OSErrorCode +].} const doslike = defined(windows) or defined(OS2) or defined(DOS) # DOS-like filesystem @@ -204,7 +209,8 @@ proc osErrorMsg*(): string {.rtl, extern: "nos$1", deprecated.} = result = $os.strerror(errno) {.push warning[deprecated]: off.} -proc osError*(msg: string = "") {.noinline, rtl, extern: "nos$1", deprecated.} = +proc raiseOSError*(msg: string = "") {.noinline, rtl, extern: "nos$1", + deprecated.} = ## raises an EOS exception with the given message ``msg``. ## If ``msg == ""``, the operating system's error flag ## (``errno``) is converted to a readable error message. On Windows @@ -219,10 +225,12 @@ proc osError*(msg: string = "") {.noinline, rtl, extern: "nos$1", deprecated.} = raise newException(OSError, msg) {.pop.} -proc `==`*(err1, err2: TOSErrorCode): bool {.borrow.} -proc `$`*(err: TOSErrorCode): string {.borrow.} +{.deprecated: [osError: raiseOSError].} + +proc `==`*(err1, err2: OSErrorCode): bool {.borrow.} +proc `$`*(err: OSErrorCode): string {.borrow.} -proc osErrorMsg*(errorCode: TOSErrorCode): string = +proc osErrorMsg*(errorCode: OSErrorCode): string = ## Converts an OS error code into a human readable string. ## ## The error code can be retrieved using the ``OSLastError`` proc. @@ -249,10 +257,10 @@ proc osErrorMsg*(errorCode: TOSErrorCode): string = result = $msgbuf if msgbuf != nil: localFree(msgbuf) else: - if errorCode != TOSErrorCode(0'i32): + if errorCode != OSErrorCode(0'i32): result = $os.strerror(errorCode.int32) -proc osError*(errorCode: TOSErrorCode) = +proc raiseOSError*(errorCode: OSErrorCode) = ## Raises an ``EOS`` exception. The ``errorCode`` will determine the ## message, ``OSErrorMsg`` will be used to get this message. ## @@ -268,7 +276,7 @@ proc osError*(errorCode: TOSErrorCode) = raise e {.push stackTrace:off.} -proc osLastError*(): TOSErrorCode = +proc osLastError*(): OSErrorCode = ## Retrieves the last operating system error code. ## ## This procedure is useful in the event when an OS call fails. In that case @@ -285,7 +293,7 @@ proc osLastError*(): TOSErrorCode = when defined(windows): result = TOSErrorCode(getLastError()) else: - result = TOSErrorCode(errno) + result = OSErrorCode(errno) {.pop.} proc unixToNativePath*(path: string, drive=""): string {. @@ -371,7 +379,7 @@ when defined(windows): f.cFileName[1].int == dot and f.cFileName[2].int == 0) proc existsFile*(filename: string): bool {.rtl, extern: "nos$1", - tags: [FReadDir].} = + tags: [ReadDirEffect].} = ## Returns true if the file exists, false otherwise. when defined(windows): when useWinUnicode: @@ -384,7 +392,7 @@ proc existsFile*(filename: string): bool {.rtl, extern: "nos$1", var res: TStat return stat(filename, res) >= 0'i32 and S_ISREG(res.st_mode) -proc existsDir*(dir: string): bool {.rtl, extern: "nos$1", tags: [FReadDir].} = +proc existsDir*(dir: string): bool {.rtl, extern: "nos$1", tags: [ReadDirEffect].} = ## Returns true iff the directory `dir` exists. If `dir` is a file, false ## is returned. when defined(windows): @@ -399,7 +407,7 @@ proc existsDir*(dir: string): bool {.rtl, extern: "nos$1", tags: [FReadDir].} = return stat(dir, res) >= 0'i32 and S_ISDIR(res.st_mode) proc symlinkExists*(link: string): bool {.rtl, extern: "nos$1", - tags: [FReadDir].} = + tags: [ReadDirEffect].} = ## Returns true iff the symlink `link` exists. Will return true ## regardless of whether the link points to a directory or file. when defined(windows): @@ -701,7 +709,7 @@ proc extractFilename*(path: string): string {. result = splitPath(path).tail proc expandFilename*(filename: string): string {.rtl, extern: "nos$1", - tags: [FReadDir].} = + tags: [ReadDirEffect].} = ## Returns the full path of `filename`, raises EOS in case of an error. when defined(windows): const bufsize = 3072'i32 @@ -800,7 +808,7 @@ when defined(Windows): ) proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1", - tags: [FReadDir].} = + tags: [ReadDirEffect].} = ## Returns True if both pathname arguments refer to the same physical ## file or directory. Raises an exception if any of the files does not ## exist or information about it can not be obtained. @@ -883,7 +891,7 @@ type fpOthersRead ## read access for others proc getFilePermissions*(filename: string): set[TFilePermission] {. - rtl, extern: "nos$1", tags: [FReadDir].} = + rtl, extern: "nos$1", tags: [ReadDirEffect].} = ## retrieves file permissions for `filename`. `OSError` is raised in case of ## an error. On Windows, only the ``readonly`` flag is checked, every other ## permission is available in any case. @@ -915,7 +923,7 @@ proc getFilePermissions*(filename: string): set[TFilePermission] {. result = {fpUserExec..fpOthersRead} proc setFilePermissions*(filename: string, permissions: set[TFilePermission]) {. - rtl, extern: "nos$1", tags: [FWriteDir].} = + rtl, extern: "nos$1", tags: [WriteDirEffect].} = ## sets the file permissions for `filename`. `OSError` is raised in case of ## an error. On Windows, only the ``readonly`` flag is changed, depending on ## ``fpUserWrite``. @@ -1014,7 +1022,7 @@ when defined(Windows): template setFileAttributes(file, attrs: expr): expr {.immediate.} = setFileAttributesA(file, attrs) -proc removeFile*(file: string) {.rtl, extern: "nos$1", tags: [FWriteDir].} = +proc removeFile*(file: string) {.rtl, extern: "nos$1", tags: [WriteDirEffect].} = ## Removes the `file`. If this fails, `EOS` is raised. This does not fail ## if the file never existed in the first place. ## On Windows, ignores the read-only attribute. @@ -1076,7 +1084,7 @@ when defined(windows): while true: var eend = strEnd(e) add(environment, $e) - e = cast[WideCString](cast[ByteAddress](eend)+2) + e = cast[WideCString](cast[TAddress](eend)+2) if eend[1].int == 0: break discard freeEnvironmentStringsW(env) else: @@ -1130,7 +1138,7 @@ proc findEnvVar(key: string): int = if startsWith(environment[i], temp): return i return -1 -proc getEnv*(key: string): TaintedString {.tags: [FReadEnv].} = +proc getEnv*(key: string): TaintedString {.tags: [ReadEnvEffect].} = ## Returns the value of the `environment variable`:idx: named `key`. ## ## If the variable does not exist, "" is returned. To distinguish @@ -1144,13 +1152,13 @@ proc getEnv*(key: string): TaintedString {.tags: [FReadEnv].} = if env == nil: return TaintedString("") result = TaintedString($env) -proc existsEnv*(key: string): bool {.tags: [FReadEnv].} = +proc existsEnv*(key: string): bool {.tags: [ReadEnvEffect].} = ## Checks whether the environment variable named `key` exists. ## Returns true if it exists, false otherwise. if c_getenv(key) != nil: return true else: return findEnvVar(key) >= 0 -proc putEnv*(key, val: string) {.tags: [FWriteEnv].} = +proc putEnv*(key, val: string) {.tags: [WriteEnvEffect].} = ## Sets the value of the `environment variable`:idx: named `key` to `val`. ## If an error occurs, `EInvalidEnvVar` is raised. @@ -1175,7 +1183,7 @@ proc putEnv*(key, val: string) {.tags: [FWriteEnv].} = else: if setEnvironmentVariableA(key, val) == 0'i32: osError(osLastError()) -iterator envPairs*(): tuple[key, value: TaintedString] {.tags: [FReadEnv].} = +iterator envPairs*(): tuple[key, value: TaintedString] {.tags: [ReadEnvEffect].} = ## Iterate over all `environments variables`:idx:. In the first component ## of the tuple is the name of the current variable stored, in the second ## its value. @@ -1185,7 +1193,7 @@ iterator envPairs*(): tuple[key, value: TaintedString] {.tags: [FReadEnv].} = yield (TaintedString(substr(environment[i], 0, p-1)), TaintedString(substr(environment[i], p+1))) -iterator walkFiles*(pattern: string): string {.tags: [FReadDir].} = +iterator walkFiles*(pattern: string): string {.tags: [ReadDirEffect].} = ## Iterate over all the files that match the `pattern`. On POSIX this uses ## the `glob`:idx: call. ## @@ -1225,7 +1233,7 @@ type pcLinkToDir ## path refers to a symbolic link to a directory iterator walkDir*(dir: string): tuple[kind: TPathComponent, path: string] {. - tags: [FReadDir].} = + tags: [ReadDirEffect].} = ## walks over the directory `dir` and yields for each directory or file in ## `dir`. The component type and full path for each item is returned. ## Walking is not recursive. @@ -1278,7 +1286,7 @@ iterator walkDir*(dir: string): tuple[kind: TPathComponent, path: string] {. discard closedir(d) iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string {. - tags: [FReadDir].} = + tags: [ReadDirEffect].} = ## walks over the directory `dir` and yields for each file in `dir`. The ## full path for each file is returned. ## **Warning**: @@ -1318,7 +1326,7 @@ proc rawRemoveDir(dir: string) = if rmdir(dir) != 0'i32 and errno != ENOENT: osError(osLastError()) proc removeDir*(dir: string) {.rtl, extern: "nos$1", tags: [ - FWriteDir, FReadDir].} = + WriteDirEffect, ReadDirEffect].} = ## Removes the directory `dir` including all subdirectories and files ## in `dir` (recursively). ## @@ -1345,7 +1353,7 @@ proc rawCreateDir(dir: string) = if res == 0'i32 and getLastError() != 183'i32: osError(osLastError()) -proc createDir*(dir: string) {.rtl, extern: "nos$1", tags: [FWriteDir].} = +proc createDir*(dir: string) {.rtl, extern: "nos$1", tags: [WriteDirEffect].} = ## Creates the `directory`:idx: `dir`. ## ## The directory may contain several subdirectories that do not exist yet. @@ -1568,7 +1576,7 @@ proc copyDirWithPermissions*(source, dest: string, proc inclFilePermissions*(filename: string, permissions: set[TFilePermission]) {. - rtl, extern: "nos$1", tags: [FReadDir, FWriteDir].} = + rtl, extern: "nos$1", tags: [ReadDirEffect, WriteDirEffect].} = ## a convenience procedure for: ## ## .. code-block:: nimrod @@ -1577,14 +1585,14 @@ proc inclFilePermissions*(filename: string, proc exclFilePermissions*(filename: string, permissions: set[TFilePermission]) {. - rtl, extern: "nos$1", tags: [FReadDir, FWriteDir].} = + rtl, extern: "nos$1", tags: [ReadDirEffect, WriteDirEffect].} = ## a convenience procedure for: ## ## .. code-block:: nimrod ## setFilePermissions(filename, getFilePermissions(filename)-permissions) setFilePermissions(filename, getFilePermissions(filename)-permissions) -proc getHomeDir*(): string {.rtl, extern: "nos$1", tags: [FReadEnv].} = +proc getHomeDir*(): string {.rtl, extern: "nos$1", tags: [ReadEnvEffect].} = ## Returns the home directory of the current user. ## ## This proc is wrapped by the expandTilde proc for the convenience of @@ -1592,12 +1600,12 @@ proc getHomeDir*(): string {.rtl, extern: "nos$1", tags: [FReadEnv].} = when defined(windows): return string(getEnv("USERPROFILE")) & "\\" else: return string(getEnv("HOME")) & "/" -proc getConfigDir*(): string {.rtl, extern: "nos$1", tags: [FReadEnv].} = +proc getConfigDir*(): string {.rtl, extern: "nos$1", tags: [ReadEnvEffect].} = ## Returns the config directory of the current user for applications. when defined(windows): return string(getEnv("APPDATA")) & "\\" else: return string(getEnv("HOME")) & "/.config/" -proc getTempDir*(): string {.rtl, extern: "nos$1", tags: [FReadEnv].} = +proc getTempDir*(): string {.rtl, extern: "nos$1", tags: [ReadEnvEffect].} = ## Returns the temporary directory of the current user for applications to ## save temporary files in. when defined(windows): return string(getEnv("TEMP")) & "\\" @@ -1605,7 +1613,7 @@ proc getTempDir*(): string {.rtl, extern: "nos$1", tags: [FReadEnv].} = when defined(nimdoc): # Common forward declaration docstring block for parameter retrieval procs. - proc paramCount*(): int {.tags: [FReadIO].} = + proc paramCount*(): int {.tags: [ReadIOEffect].} = ## Returns the number of `command line arguments`:idx: given to the ## application. ## @@ -1625,7 +1633,7 @@ when defined(nimdoc): ## else: ## # Do something else! - proc paramStr*(i: int): TaintedString {.tags: [FReadIO].} = + proc paramStr*(i: int): TaintedString {.tags: [ReadIOEffect].} = ## Returns the `i`-th `command line argument`:idx: given to the application. ## ## `i` should be in the range `1..paramCount()`, the `EInvalidIndex` @@ -1826,7 +1834,7 @@ proc getFileSize*(file: string): BiggestInt {.rtl, extern: "nos$1", close(f) else: osError(osLastError()) -proc findExe*(exe: string): string {.tags: [FReadDir, FReadEnv].} = +proc findExe*(exe: string): string {.tags: [ReadDirEffect, ReadEnvEffect].} = ## Searches for `exe` in the current working directory and then ## in directories listed in the ``PATH`` environment variable. ## Returns "" if the `exe` cannot be found. On DOS-like platforms, `exe` @@ -1854,7 +1862,6 @@ proc expandTilde*(path: string): string = ## let configFile = expandTilde("~" / "appname.cfg") ## echo configFile ## # --> C:\Users\amber\appname.cfg - if len(path) > 1 and path[0] == '~' and (path[1] == '/' or path[1] == '\\'): result = getHomeDir() / path[2..len(path)-1] else: @@ -1961,7 +1968,7 @@ proc getFileInfo*(handle: FileHandle): FileInfo = rawToFormalFileInfo(rawInfo, result) proc getFileInfo*(file: File): FileInfo = - result = getFileInfo(file.fileHandle()) + result = getFileInfo(file.getFileHandle()) proc getFileInfo*(path: string, followSymlink = true): FileInfo = ## Retrieves file information for the file object pointed to by `path`. diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index d5ca2f5a5..25782d4f5 100644 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2014 Andreas Rumpf # # See the file "copying.txt", included in this @@ -24,7 +24,7 @@ when defined(linux): import linux type - TProcess = object of RootObj + ProcessObj = object of RootObj when defined(windows): fProcessHandle: THandle inHandle, outHandle, errHandle: FileHandle @@ -35,9 +35,9 @@ type id: TPid exitCode: cint - PProcess* = ref TProcess ## represents an operating system process + Process* = ref ProcessObj ## represents an operating system process - TProcessOption* = enum ## options that can be passed `startProcess` + ProcessOption* = enum ## options that can be passed `startProcess` poEchoCmd, ## echo the command before execution poUsePath, ## Asks system to search for executable using PATH environment ## variable. @@ -47,6 +47,9 @@ type poStdErrToStdOut, ## merge stdout and stderr to the stdout stream poParentStreams ## use the parent's streams +{.deprecated: [TProcess: ProcessObj, PProcess: Process, + TProcessOption: ProcessOption].} + const poUseShell* {.deprecated.} = poUsePath ## Deprecated alias for poUsePath. @@ -125,7 +128,7 @@ proc startProcess*(command: string, args: openArray[string] = [], env: PStringTable = nil, options: set[TProcessOption] = {poStdErrToStdOut}): - PProcess {.rtl, extern: "nosp$1", tags: [ExecIOEffect, FReadEnv].} + PProcess {.rtl, extern: "nosp$1", tags: [ExecIOEffect, ReadEnvEffect].} ## Starts a process. `Command` is the executable file, `workingDir` is the ## process's working directory. If ``workingDir == ""`` the current directory ## is used. `args` are the command line arguments that are passed to the @@ -150,7 +153,7 @@ proc startProcess*(command: string, proc startCmd*(command: string, options: set[TProcessOption] = { poStdErrToStdOut, poUsePath}): PProcess {. - tags: [ExecIOEffect, FReadEnv], deprecated.} = + tags: [ExecIOEffect, ReadEnvEffect], deprecated.} = ## Deprecated - use `startProcess` directly. result = startProcess(command=command, options=options + {poEvalCommand}) @@ -233,7 +236,7 @@ proc countProcessors*(): int {.rtl, extern: "nosp$1".} = proc execProcesses*(cmds: openArray[string], options = {poStdErrToStdOut, poParentStreams}, n = countProcessors()): int {.rtl, extern: "nosp$1", - tags: [ExecIOEffect, TimeEffect, FReadEnv]} = + tags: [ExecIOEffect, TimeEffect, ReadEnvEffect]} = ## executes the commands `cmds` in parallel. Creates `n` processes ## that execute in parallel. The highest return value of all processes ## is returned. @@ -584,12 +587,12 @@ elif not defined(useNimRtl): when not defined(useFork): proc startProcessAuxSpawn(data: TStartProcessData): TPid {. - tags: [ExecIOEffect, FReadEnv], gcsafe.} + tags: [ExecIOEffect, ReadEnvEffect], gcsafe.} proc startProcessAuxFork(data: TStartProcessData): TPid {. - tags: [ExecIOEffect, FReadEnv], gcsafe.} + tags: [ExecIOEffect, ReadEnvEffect], gcsafe.} {.push stacktrace: off, profiler: off.} proc startProcessAfterFork(data: ptr TStartProcessData) {. - tags: [ExecIOEffect, FReadEnv], cdecl, gcsafe.} + tags: [ExecIOEffect, ReadEnvEffect], cdecl, gcsafe.} {.pop.} proc startProcess(command: string, diff --git a/lib/pure/parsecfg.nim b/lib/pure/parsecfg.nim index 1d61a967b..c340bf98b 100644 --- a/lib/pure/parsecfg.nim +++ b/lib/pure/parsecfg.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2010 Andreas Rumpf # # See the file "copying.txt", included in this @@ -20,24 +20,24 @@ ## The file ``examples/parsecfgex.nim`` demonstrates how to use the ## configuration file parser: ## -## .. code-block:: nimrod +## .. code-block:: nim ## :file: examples/parsecfgex.nim -import +import hashes, strutils, lexbase, streams include "system/inclrtl" -type - TCfgEventKind* = enum ## enumeration of all events that may occur when parsing +type + CfgEventKind* = enum ## enumeration of all events that may occur when parsing cfgEof, ## end of file reached cfgSectionStart, ## a ``[section]`` has been parsed cfgKeyValuePair, ## a ``key=value`` pair has been detected cfgOption, ## a ``--key=value`` command line option cfgError ## an error ocurred during parsing - TCfgEvent* = object of TObject ## describes a parsing event + CfgEvent* = object of RootObj ## describes a parsing event case kind*: TCfgEventKind ## the kind of the event of cfgEof: nil of cfgSectionStart: @@ -53,28 +53,30 @@ type msg*: string ## contains the error message. No exceptions ## are thrown if a parse error occurs. - TTokKind = enum + TokKind = enum tkInvalid, tkEof, tkSymbol, tkEquals, tkColon, tkBracketLe, tkBracketRi, tkDashDash - TToken {.final.} = object # a token - kind: TTokKind # the type of the token + Token = object # a token + kind: TokKind # the type of the token literal: string # the parsed (string) literal - TCfgParser* = object of TBaseLexer ## the parser object. - tok: TToken + CfgParser* = object of BaseLexer ## the parser object. + tok: Token filename: string +{.deprecated: [TCfgEventKind: CfgEventKind, TCfgEvent: CfgEvent, + TTokKind: TokKind, TToken: Token, TCfgParser: CfgParser].} + # implementation const - SymChars: TCharSet = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\x80'..'\xFF', '.', - '/', '\\'} + SymChars: CharSet = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\x80'..'\xFF', '.', + '/', '\\'} -proc rawGetTok(c: var TCfgParser, tok: var TToken) {.gcsafe.} +proc rawGetTok(c: var CfgParser, tok: var Token) {.gcsafe.} -proc open*(c: var TCfgParser, input: PStream, filename: string, - lineOffset = 0) {. - rtl, extern: "npc$1".} = +proc open*(c: var CfgParser, input: PStream, filename: string, + lineOffset = 0) {.rtl, extern: "npc$1".} = ## initializes the parser with an input stream. `Filename` is only used ## for nice error messages. `lineOffset` can be used to influence the line ## number information in the generated error messages. @@ -85,23 +87,23 @@ proc open*(c: var TCfgParser, input: PStream, filename: string, inc(c.lineNumber, lineOffset) rawGetTok(c, c.tok) -proc close*(c: var TCfgParser) {.rtl, extern: "npc$1".} = +proc close*(c: var CfgParser) {.rtl, extern: "npc$1".} = ## closes the parser `c` and its associated input stream. lexbase.close(c) -proc getColumn*(c: TCfgParser): int {.rtl, extern: "npc$1".} = +proc getColumn*(c: CfgParser): int {.rtl, extern: "npc$1".} = ## get the current column the parser has arrived at. result = getColNumber(c, c.bufpos) -proc getLine*(c: TCfgParser): int {.rtl, extern: "npc$1".} = +proc getLine*(c: CfgParser): int {.rtl, extern: "npc$1".} = ## get the current line the parser has arrived at. result = c.lineNumber -proc getFilename*(c: TCfgParser): string {.rtl, extern: "npc$1".} = +proc getFilename*(c: CfgParser): string {.rtl, extern: "npc$1".} = ## get the filename of the file that the parser processes. result = c.filename -proc handleHexChar(c: var TCfgParser, xi: var int) = +proc handleHexChar(c: var CfgParser, xi: var int) = case c.buf[c.bufpos] of '0'..'9': xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('0')) @@ -115,12 +117,12 @@ proc handleHexChar(c: var TCfgParser, xi: var int) = else: discard -proc handleDecChars(c: var TCfgParser, xi: var int) = +proc handleDecChars(c: var CfgParser, xi: var int) = while c.buf[c.bufpos] in {'0'..'9'}: xi = (xi * 10) + (ord(c.buf[c.bufpos]) - ord('0')) inc(c.bufpos) -proc getEscapedChar(c: var TCfgParser, tok: var TToken) = +proc getEscapedChar(c: var CfgParser, tok: var TToken) = inc(c.bufpos) # skip '\' case c.buf[c.bufpos] of 'n', 'N': @@ -169,13 +171,13 @@ proc getEscapedChar(c: var TCfgParser, tok: var TToken) = else: tok.kind = tkInvalid else: tok.kind = tkInvalid -proc handleCRLF(c: var TCfgParser, pos: int): int = +proc handleCRLF(c: var CfgParser, pos: int): int = case c.buf[pos] of '\c': result = lexbase.handleCR(c, pos) of '\L': result = lexbase.handleLF(c, pos) else: result = pos -proc getString(c: var TCfgParser, tok: var TToken, rawMode: bool) = +proc getString(c: var CfgParser, tok: var Token, rawMode: bool) = var pos = c.bufpos + 1 # skip " var buf = c.buf # put `buf` in a register tok.kind = tkSymbol @@ -221,7 +223,7 @@ proc getString(c: var TCfgParser, tok: var TToken, rawMode: bool) = inc(pos) c.bufpos = pos -proc getSymbol(c: var TCfgParser, tok: var TToken) = +proc getSymbol(c: var CfgParser, tok: var Token) = var pos = c.bufpos var buf = c.buf while true: @@ -231,7 +233,7 @@ proc getSymbol(c: var TCfgParser, tok: var TToken) = c.bufpos = pos tok.kind = tkSymbol -proc skip(c: var TCfgParser) = +proc skip(c: var CfgParser) = var pos = c.bufpos var buf = c.buf while true: @@ -247,7 +249,7 @@ proc skip(c: var TCfgParser) = break # EndOfFile also leaves the loop c.bufpos = pos -proc rawGetTok(c: var TCfgParser, tok: var TToken) = +proc rawGetTok(c: var CfgParser, tok: var Token) = tok.kind = tkInvalid setLen(tok.literal, 0) skip(c) @@ -286,19 +288,19 @@ proc rawGetTok(c: var TCfgParser, tok: var TToken) = tok.literal = "[EOF]" else: getSymbol(c, tok) -proc errorStr*(c: TCfgParser, msg: string): string {.rtl, extern: "npc$1".} = +proc errorStr*(c: CfgParser, msg: string): string {.rtl, extern: "npc$1".} = ## returns a properly formated error message containing current line and ## column information. result = `%`("$1($2, $3) Error: $4", [c.filename, $getLine(c), $getColumn(c), msg]) -proc warningStr*(c: TCfgParser, msg: string): string {.rtl, extern: "npc$1".} = +proc warningStr*(c: CfgParser, msg: string): string {.rtl, extern: "npc$1".} = ## returns a properly formated warning message containing current line and ## column information. result = `%`("$1($2, $3) Warning: $4", [c.filename, $getLine(c), $getColumn(c), msg]) -proc ignoreMsg*(c: TCfgParser, e: TCfgEvent): string {.rtl, extern: "npc$1".} = +proc ignoreMsg*(c: CfgParser, e: CfgEvent): string {.rtl, extern: "npc$1".} = ## returns a properly formated warning message containing that ## an entry is ignored. case e.kind @@ -309,7 +311,7 @@ proc ignoreMsg*(c: TCfgParser, e: TCfgEvent): string {.rtl, extern: "npc$1".} = of cfgError: result = e.msg of cfgEof: result = "" -proc getKeyValPair(c: var TCfgParser, kind: TCfgEventKind): TCfgEvent = +proc getKeyValPair(c: var CfgParser, kind: CfgEventKind): CfgEvent = if c.tok.kind == tkSymbol: result.kind = kind result.key = c.tok.literal @@ -329,7 +331,7 @@ proc getKeyValPair(c: var TCfgParser, kind: TCfgEventKind): TCfgEvent = result.msg = errorStr(c, "symbol expected, but found: " & c.tok.literal) rawGetTok(c, c.tok) -proc next*(c: var TCfgParser): TCfgEvent {.rtl, extern: "npc$1".} = +proc next*(c: var CfgParser): CfgEvent {.rtl, extern: "npc$1".} = ## retrieves the first/next event. This controls the parser. case c.tok.kind of tkEof: diff --git a/lib/pure/parsecsv.nim b/lib/pure/parsecsv.nim index 4b25babec..d267906a3 100644 --- a/lib/pure/parsecsv.nim +++ b/lib/pure/parsecsv.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2009 Andreas Rumpf # # See the file "copying.txt", included in this @@ -13,16 +13,16 @@ ## Example: How to use the parser ## ============================== ## -## .. code-block:: nimrod +## .. code-block:: nim ## import os, parsecsv, streams -## var s = newFileStream(ParamStr(1), fmRead) -## if s == nil: quit("cannot open the file" & ParamStr(1)) -## var x: TCsvParser -## open(x, s, ParamStr(1)) +## var s = newFileStream(paramStr(1), fmRead) +## if s == nil: quit("cannot open the file" & paramStr(1)) +## var x: CsvParser +## open(x, s, paramStr(1)) ## while readRow(x): -## Echo "new row: " +## echo "new row: " ## for val in items(x.row): -## Echo "##", val, "##" +## echo "##", val, "##" ## close(x) ## @@ -30,28 +30,30 @@ import lexbase, streams type - TCsvRow* = seq[string] ## a row in a CSV file - TCsvParser* = object of TBaseLexer ## the parser object. - row*: TCsvRow ## the current row + CsvRow* = seq[string] ## a row in a CSV file + CsvParser* = object of BaseLexer ## the parser object. + row*: CsvRow ## the current row filename: string sep, quote, esc: char skipWhite: bool currRow: int - EInvalidCsv* = object of EIO ## exception that is raised if - ## a parsing error occurs + CsvError* = object of IOError ## exception that is raised if + ## a parsing error occurs + +{.deprecated: [TCsvRow: CsvRow, TCsvParser: CsvParser, EInvalidCsv: CsvError].} proc raiseEInvalidCsv(filename: string, line, col: int, msg: string) {.noreturn.} = - var e: ref EInvalidCsv + var e: ref CsvError new(e) e.msg = filename & "(" & $line & ", " & $col & ") Error: " & msg raise e -proc error(my: TCsvParser, pos: int, msg: string) = +proc error(my: CsvParser, pos: int, msg: string) = raiseEInvalidCsv(my.filename, my.LineNumber, getColNumber(my, pos), msg) -proc open*(my: var TCsvParser, input: PStream, filename: string, +proc open*(my: var CsvParser, input: Stream, filename: string, separator = ',', quote = '"', escape = '\0', skipInitialSpace = false) = ## initializes the parser with an input stream. `Filename` is only used @@ -75,7 +77,7 @@ proc open*(my: var TCsvParser, input: PStream, filename: string, my.row = @[] my.currRow = 0 -proc parseField(my: var TCsvParser, a: var string) = +proc parseField(my: var CsvParser, a: var string) = var pos = my.bufpos var buf = my.buf if my.skipWhite: @@ -83,7 +85,7 @@ proc parseField(my: var TCsvParser, a: var string) = setLen(a, 0) # reuse memory if buf[pos] == my.quote and my.quote != '\0': inc(pos) - while true: + while true: var c = buf[pos] if c == '\0': my.bufpos = pos # can continue after exception? @@ -121,11 +123,11 @@ proc parseField(my: var TCsvParser, a: var string) = inc(pos) my.bufpos = pos -proc processedRows*(my: var TCsvParser): int = +proc processedRows*(my: var CsvParser): int = ## returns number of the processed rows return my.currRow -proc readRow*(my: var TCsvParser, columns = 0): bool = +proc readRow*(my: var CsvParser, columns = 0): bool = ## reads the next row; if `columns` > 0, it expects the row to have ## exactly this many columns. Returns false if the end of the file ## has been encountered else true. @@ -160,19 +162,19 @@ proc readRow*(my: var TCsvParser, columns = 0): bool = $col & " columns") inc(my.currRow) -proc close*(my: var TCsvParser) {.inline.} = +proc close*(my: var CsvParser) {.inline.} = ## closes the parser `my` and its associated input stream. lexbase.close(my) when isMainModule: import os - var s = newFileStream(ParamStr(1), fmRead) - if s == nil: quit("cannot open the file" & ParamStr(1)) - var x: TCsvParser - open(x, s, ParamStr(1)) + var s = newFileStream(paramStr(1), fmRead) + if s == nil: quit("cannot open the file" & paramStr(1)) + var x: CsvParser + open(x, s, paramStr(1)) while readRow(x): - Echo "new row: " + echo "new row: " for val in items(x.row): - Echo "##", val, "##" + echo "##", val, "##" close(x) diff --git a/lib/pure/parseopt.nim b/lib/pure/parseopt.nim index d7379a9a9..b325bd1f5 100644 --- a/lib/pure/parseopt.nim +++ b/lib/pure/parseopt.nim @@ -1,13 +1,13 @@ # # -# Nimrod's Runtime Library -# (c) Copyright 2012 Andreas Rumpf +# Nim's Runtime Library +# (c) Copyright 2014 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # -## This module provides the standard Nimrod command line parser. +## This module provides the standard Nim command line parser. ## It supports one convenience iterator over all command line options and some ## lower-level features. ## @@ -22,26 +22,28 @@ import os, strutils type - TCmdLineKind* = enum ## the detected command line token + CmdLineKind* = enum ## the detected command line token cmdEnd, ## end of command line reached cmdArgument, ## argument detected cmdLongoption, ## a long option ``--option`` detected cmdShortOption ## a short option ``-c`` detected - TOptParser* = + OptParser* = object of RootObj ## this object implements the command line parser cmd: string pos: int inShortState: bool - kind*: TCmdLineKind ## the dected command line token + kind*: CmdLineKind ## the dected command line token key*, val*: TaintedString ## key and value pair; ``key`` is the option ## or the argument, ``value`` is not "" if ## the option was given a value +{.deprecated: [TCmdLineKind: CmdLineKind, TOptParser: OptParser].} + when declared(os.paramCount): # we cannot provide this for NimRtl creation on Posix, because we can't # access the command line arguments then! - proc initOptParser*(cmdline = ""): TOptParser = + proc initOptParser*(cmdline = ""): OptParser = ## inits the option parser. If ``cmdline == ""``, the real command line ## (as provided by the ``OS`` module) is taken. result.pos = 0 @@ -57,7 +59,7 @@ when declared(os.paramCount): result.val = TaintedString"" proc parseWord(s: string, i: int, w: var string, - delim: TCharSet = {'\x09', ' ', '\0'}): int = + delim: CharSet = {'\x09', ' ', '\0'}): int = result = i if s[result] == '\"': inc(result) @@ -70,7 +72,7 @@ proc parseWord(s: string, i: int, w: var string, add(w, s[result]) inc(result) -proc handleShortOption(p: var TOptParser) = +proc handleShortOption(p: var OptParser) = var i = p.pos p.kind = cmdShortOption add(p.key.string, p.cmd[i]) @@ -87,8 +89,7 @@ proc handleShortOption(p: var TOptParser) = if p.cmd[i] == '\0': p.inShortState = false p.pos = i -proc next*(p: var TOptParser) {. - rtl, extern: "npo$1".} = +proc next*(p: var OptParser) {.rtl, extern: "npo$1".} = ## parses the first or next option; ``p.kind`` describes what token has been ## parsed. ``p.key`` and ``p.val`` are set accordingly. var i = p.pos @@ -122,14 +123,12 @@ proc next*(p: var TOptParser) {. p.kind = cmdArgument p.pos = parseWord(p.cmd, i, p.key.string) -proc cmdLineRest*(p: TOptParser): TaintedString {. - rtl, extern: "npo$1".} = +proc cmdLineRest*(p: OptParser): TaintedString {.rtl, extern: "npo$1".} = ## retrieves the rest of the command line that has not been parsed yet. result = strip(substr(p.cmd, p.pos, len(p.cmd) - 1)).TaintedString when declared(initOptParser): - - iterator getopt*(): tuple[kind: TCmdLineKind, key, val: TaintedString] = + iterator getopt*(): tuple[kind: CmdLineKind, key, val: TaintedString] = ## This is an convenience iterator for iterating over the command line. ## This uses the TOptParser object. Example: ## diff --git a/lib/pure/parseopt2.nim b/lib/pure/parseopt2.nim index 7638171d1..c283a5edf 100644 --- a/lib/pure/parseopt2.nim +++ b/lib/pure/parseopt2.nim @@ -1,13 +1,13 @@ # # -# Nimrod's Runtime Library -# (c) Copyright 2012 Andreas Rumpf +# Nim's Runtime Library +# (c) Copyright 2014 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # -## This module provides the standard Nimrod command line parser. +## This module provides the standard Nim command line parser. ## It supports one convenience iterator over all command line options and some ## lower-level features. ## @@ -25,22 +25,24 @@ import os, strutils type - TCmdLineKind* = enum ## the detected command line token + CmdLineKind* = enum ## the detected command line token cmdEnd, ## end of command line reached cmdArgument, ## argument detected cmdLongOption, ## a long option ``--option`` detected cmdShortOption ## a short option ``-c`` detected - TOptParser* = + OptParser* = object of TObject ## this object implements the command line parser cmd: seq[string] pos: int remainingShortOptions: string - kind*: TCmdLineKind ## the dected command line token + kind*: CmdLineKind ## the dected command line token key*, val*: TaintedString ## key and value pair; ``key`` is the option ## or the argument, ``value`` is not "" if ## the option was given a value -proc initOptParser*(cmdline: seq[string]): TOptParser {.rtl.} = +{.deprecated: [TCmdLineKind: CmdLineKind, TOptParser: OptParser].} + +proc initOptParser*(cmdline: seq[string]): OptParser {.rtl.} = ## Initalizes option parses with cmdline. cmdline should not contain ## argument 0 - program name. ## If cmdline == nil default to current command line arguments. @@ -54,7 +56,7 @@ proc initOptParser*(cmdline: seq[string]): TOptParser {.rtl.} = result.cmd = @cmdline -proc initOptParser*(cmdline: string): TOptParser {.rtl, deprecated.} = +proc initOptParser*(cmdline: string): OptParser {.rtl, deprecated.} = ## Initalizes option parses with cmdline. Splits cmdline in on spaces ## and calls initOptParser(openarray[string]) ## Do not use. @@ -64,13 +66,13 @@ proc initOptParser*(cmdline: string): TOptParser {.rtl, deprecated.} = return initOptParser(cmdline.split) when not defined(createNimRtl): - proc initOptParser*(): TOptParser = + proc initOptParser*(): OptParser = ## Initializes option parser from current command line arguments. return initOptParser(commandLineParams()) -proc next*(p: var TOptParser) {.rtl, extern: "npo$1".} +proc next*(p: var OptParser) {.rtl, extern: "npo$1".} -proc nextOption(p: var TOptParser, token: string, allowEmpty: bool) = +proc nextOption(p: var OptParser, token: string, allowEmpty: bool) = for splitchar in [':', '=']: if splitchar in token: let pos = token.find(splitchar) @@ -85,7 +87,7 @@ proc nextOption(p: var TOptParser, token: string, allowEmpty: bool) = p.remainingShortOptions = token[0..token.len-1] p.next() -proc next(p: var TOptParser) = +proc next(p: var OptParser) = if p.remainingShortOptions.len != 0: p.kind = cmdShortOption p.key = TaintedString(p.remainingShortOptions[0..0]) @@ -111,20 +113,22 @@ proc next(p: var TOptParser) = p.key = token p.val = "" -proc cmdLineRest*(p: TOptParser): TaintedString {.rtl, extern: "npo$1", deprecated.} = +proc cmdLineRest*(p: OptParser): TaintedString {.rtl, extern: "npo$1", deprecated.} = ## Returns part of command line string that has not been parsed yet. ## Do not use - does not correctly handle whitespace. return p.cmd[p.pos..p.cmd.len-1].join(" ") type - TGetoptResult* = tuple[kind: TCmdLineKind, key, val: TaintedString] + GetoptResult* = tuple[kind: CmdLineKind, key, val: TaintedString] + +{.deprecated: [TGetoptResult: GetoptResult].} when declared(paramCount): - iterator getopt*(): TGetoptResult = + iterator getopt*(): GetoptResult = ## This is an convenience iterator for iterating over the command line. - ## This uses the TOptParser object. Example: + ## This uses the OptParser object. Example: ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## var ## filename = "" ## for kind, key, val in getopt(): diff --git a/lib/pure/parsesql.nim b/lib/pure/parsesql.nim index bd8836f7c..fcca0aa44 100644 --- a/lib/pure/parsesql.nim +++ b/lib/pure/parsesql.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2009 Andreas Rumpf # # See the file "copying.txt", included in this @@ -10,13 +10,13 @@ ## The ``parsesql`` module implements a high performance SQL file ## parser. It parses PostgreSQL syntax and the SQL ANSI standard. -import +import hashes, strutils, lexbase, streams # ------------------- scanner ------------------------------------------------- type - TTokKind = enum ## enumeration of all SQL tokens + TokKind = enum ## enumeration of all SQL tokens tkInvalid, ## invalid token tkEof, ## end of file reached tkIdentifier, ## abc @@ -38,33 +38,35 @@ type tkBracketRi, ## ']' tkDot ## '.' - TToken {.final.} = object # a token - kind: TTokKind # the type of the token + Token = object # a token + kind: TokKind # the type of the token literal: string # the parsed (string) literal - TSqlLexer* = object of TBaseLexer ## the parser object. + SqlLexer* = object of BaseLexer ## the parser object. filename: string +{.deprecated: [TToken: Token, TSqlLexer: SqlLexer].} + const - tokKindToStr: array[TTokKind, string] = [ + tokKindToStr: array[TokKind, string] = [ "invalid", "[EOF]", "identifier", "quoted identifier", "string constant", "escape string constant", "dollar quoted constant", "bit string constant", "hex string constant", "integer constant", "numeric constant", "operator", ";", ":", ",", "(", ")", "[", "]", "." ] -proc open(L: var TSqlLexer, input: PStream, filename: string) = +proc open(L: var SqlLexer, input: Stream, filename: string) = lexbase.open(L, input) L.filename = filename -proc close(L: var TSqlLexer) = +proc close(L: var SqlLexer) = lexbase.close(L) -proc getColumn(L: TSqlLexer): int = +proc getColumn(L: SqlLexer): int = ## get the current column the parser has arrived at. result = getColNumber(L, L.bufPos) -proc getLine(L: TSqlLexer): int = +proc getLine(L: SqlLexer): int = result = L.linenumber proc handleHexChar(c: var TSqlLexer, xi: var int) = @@ -137,10 +139,10 @@ proc getEscapedChar(c: var TSqlLexer, tok: var TToken) = else: tok.kind = tkInvalid else: tok.kind = tkInvalid -proc HandleCRLF(c: var TSqlLexer, pos: int): int = +proc handleCRLF(c: var TSqlLexer, pos: int): int = case c.buf[pos] - of '\c': result = lexbase.HandleCR(c, pos) - of '\L': result = lexbase.HandleLF(c, pos) + of '\c': result = lexbase.handleCR(c, pos) + of '\L': result = lexbase.handleLF(c, pos) else: result = pos proc skip(c: var TSqlLexer) = @@ -163,7 +165,7 @@ proc skip(c: var TSqlLexer) = case buf[pos] of '\0': break of '\c', '\L': - pos = HandleCRLF(c, pos) + pos = handleCRLF(c, pos) buf = c.buf of '*': if buf[pos+1] == '/': @@ -181,13 +183,13 @@ proc skip(c: var TSqlLexer) = else: inc(pos) else: break of '\c', '\L': - pos = HandleCRLF(c, pos) + pos = handleCRLF(c, pos) buf = c.buf else: break # EndOfFile also leaves the loop c.bufpos = pos -proc getString(c: var TSqlLexer, tok: var TToken, kind: TTokKind) = +proc getString(c: var TSqlLexer, tok: var TToken, kind: TokKind) = var pos = c.bufPos + 1 var buf = c.buf tok.kind = kind @@ -465,7 +467,7 @@ proc errorStr(L: TSqlLexer, msg: string): string = # :: left PostgreSQL-style typecast # [ ] left array element selection # - right unary minus -# ^ left exponentiation +# ^ left exponentiation # * / % left multiplication, division, modulo # + - left addition, subtraction # IS IS TRUE, IS FALSE, IS UNKNOWN, IS NULL @@ -483,7 +485,7 @@ proc errorStr(L: TSqlLexer, msg: string): string = # OR left logical disjunction type - TSqlNodeKind* = enum ## kind of SQL abstract syntax tree + SqlNodeKind* = enum ## kind of SQL abstract syntax tree nkNone, nkIdent, nkStringLit, @@ -536,79 +538,82 @@ type nkEnumDef type - EInvalidSql* = object of EInvalidValue ## Invalid SQL encountered - PSqlNode* = ref TSqlNode ## an SQL abstract syntax tree node - TSqlNode* = object ## an SQL abstract syntax tree node - case kind*: TSqlNodeKind ## kind of syntax tree + SqlParseError* = object of ValueError ## Invalid SQL encountered + SqlNode* = ref SqlNodeObj ## an SQL abstract syntax tree node + SqlNodeObj* = object ## an SQL abstract syntax tree node + case kind*: SqlNodeKind ## kind of syntax tree of nkIdent, nkStringLit, nkBitStringLit, nkHexStringLit, nkIntegerLit, nkNumericLit: strVal*: string ## AST leaf: the identifier, numeric literal ## string literal, etc. else: - sons*: seq[PSqlNode] ## the node's children + sons*: seq[SqlNode] ## the node's children + + SqlParser* = object of SqlLexer ## SQL parser object + tok: Token - TSqlParser* = object of TSqlLexer ## SQL parser object - tok: TToken +{.deprecated: [EInvalidSql: SqlParseError, PSqlNode: SqlNode, + TSqlNode: SqlNodeObj, TSqlParser: SqlParser, TSqlNodeKind: SqlNodeKind].} -proc newNode(k: TSqlNodeKind): PSqlNode = +proc newNode(k: SqlNodeKind): SqlNode = new(result) result.kind = k -proc newNode(k: TSqlNodeKind, s: string): PSqlNode = +proc newNode(k: SqlNodeKind, s: string): SqlNode = new(result) result.kind = k result.strVal = s -proc len*(n: PSqlNode): int = +proc len*(n: SqlNode): int = if isNil(n.sons): result = 0 else: result = n.sons.len -proc add*(father, n: PSqlNode) = +proc add*(father, n: SqlNode) = if isNil(father.sons): father.sons = @[] add(father.sons, n) -proc getTok(p: var TSqlParser) = +proc getTok(p: var SqlParser) = getTok(p, p.tok) -proc sqlError(p: TSqlParser, msg: string) = - var e: ref EInvalidSql +proc sqlError(p: SqlParser, msg: string) = + var e: ref SqlParseError new(e) e.msg = errorStr(p, msg) raise e -proc isKeyw(p: TSqlParser, keyw: string): bool = +proc isKeyw(p: SqlParser, keyw: string): bool = result = p.tok.kind == tkIdentifier and cmpIgnoreCase(p.tok.literal, keyw) == 0 -proc isOpr(p: TSqlParser, opr: string): bool = +proc isOpr(p: SqlParser, opr: string): bool = result = p.tok.kind == tkOperator and cmpIgnoreCase(p.tok.literal, opr) == 0 -proc optKeyw(p: var TSqlParser, keyw: string) = +proc optKeyw(p: var SqlParser, keyw: string) = if p.tok.kind == tkIdentifier and cmpIgnoreCase(p.tok.literal, keyw) == 0: getTok(p) -proc expectIdent(p: TSqlParser) = +proc expectIdent(p: SqlParser) = if p.tok.kind != tkIdentifier and p.tok.kind != tkQuotedIdentifier: sqlError(p, "identifier expected") -proc expect(p: TSqlParser, kind: TTokKind) = +proc expect(p: SqlParser, kind: TokKind) = if p.tok.kind != kind: sqlError(p, tokKindToStr[kind] & " expected") -proc eat(p: var TSqlParser, kind: TTokKind) = +proc eat(p: var SqlParser, kind: TokKind) = if p.tok.kind == kind: getTok(p) else: sqlError(p, tokKindToStr[kind] & " expected") -proc eat(p: var TSqlParser, keyw: string) = +proc eat(p: var SqlParser, keyw: string) = if isKeyw(p, keyw): getTok(p) else: sqlError(p, keyw.toUpper() & " expected") -proc parseDataType(p: var TSqlParser): PSqlNode = +proc parseDataType(p: var SqlParser): SqlNode = if isKeyw(p, "enum"): result = newNode(nkEnumDef) getTok(p) @@ -636,7 +641,7 @@ proc parseDataType(p: var TSqlParser): PSqlNode = getTok(p) eat(p, tkParRi) -proc getPrecedence(p: TSqlParser): int = +proc getPrecedence(p: SqlParser): int = if isOpr(p, "*") or isOpr(p, "/") or isOpr(p, "%"): result = 6 elif isOpr(p, "+") or isOpr(p, "-"): @@ -655,9 +660,9 @@ proc getPrecedence(p: TSqlParser): int = else: result = - 1 -proc parseExpr(p: var TSqlParser): PSqlNode +proc parseExpr(p: var SqlParser): SqlNode -proc identOrLiteral(p: var TSqlParser): PSqlNode = +proc identOrLiteral(p: var SqlParser): SqlNode = case p.tok.kind of tkIdentifier, tkQuotedIdentifier: result = newNode(nkIdent, p.tok.literal) @@ -685,7 +690,7 @@ proc identOrLiteral(p: var TSqlParser): PSqlNode = sqlError(p, "expression expected") getTok(p) # we must consume a token here to prevend endless loops! -proc primary(p: var TSqlParser): PSqlNode = +proc primary(p: var SqlParser): SqlNode = if p.tok.kind == tkOperator or isKeyw(p, "not"): result = newNode(nkPrefix) result.add(newNode(nkIdent, p.tok.literal)) @@ -723,9 +728,9 @@ proc primary(p: var TSqlParser): PSqlNode = getTok(p) else: break -proc lowestExprAux(p: var TSqlParser, v: var PSqlNode, limit: int): int = +proc lowestExprAux(p: var SqlParser, v: var SqlNode, limit: int): int = var - v2, node, opNode: PSqlNode + v2, node, opNode: SqlNode v = primary(p) # expand while operators have priorities higher than 'limit' var opPred = getPrecedence(p) result = opPred @@ -740,14 +745,14 @@ proc lowestExprAux(p: var TSqlParser, v: var PSqlNode, limit: int): int = v = node opPred = getPrecedence(p) -proc parseExpr(p: var TSqlParser): PSqlNode = +proc parseExpr(p: var SqlParser): SqlNode = discard lowestExprAux(p, result, - 1) -proc parseTableName(p: var TSqlParser): PSqlNode = +proc parseTableName(p: var SqlParser): SqlNode = expectIdent(p) result = primary(p) -proc parseColumnReference(p: var TSqlParser): PSqlNode = +proc parseColumnReference(p: var SqlParser): SqlNode = result = parseTableName(p) if p.tok.kind == tkParLe: getTok(p) @@ -760,12 +765,12 @@ proc parseColumnReference(p: var TSqlParser): PSqlNode = result.add(parseTableName(p)) eat(p, tkParRi) -proc parseCheck(p: var TSqlParser): PSqlNode = +proc parseCheck(p: var SqlParser): SqlNode = getTok(p) result = newNode(nkCheck) result.add(parseExpr(p)) -proc parseConstraint(p: var TSqlParser): PSqlNode = +proc parseConstraint(p: var SqlParser): SqlNode = getTok(p) result = newNode(nkConstraint) expectIdent(p) @@ -774,7 +779,7 @@ proc parseConstraint(p: var TSqlParser): PSqlNode = eat(p, "check") result.add(parseExpr(p)) -proc parseColumnConstraints(p: var TSqlParser, result: PSqlNode) = +proc parseColumnConstraints(p: var SqlParser, result: SqlNode) = while true: if isKeyw(p, "default"): getTok(p) @@ -806,7 +811,7 @@ proc parseColumnConstraints(p: var TSqlParser, result: PSqlNode) = else: break -proc parseColumnDef(p: var TSqlParser): PSqlNode = +proc parseColumnDef(p: var SqlParser): SqlNode = expectIdent(p) result = newNode(nkColumnDef) result.add(newNode(nkIdent, p.tok.literal)) @@ -814,7 +819,7 @@ proc parseColumnDef(p: var TSqlParser): PSqlNode = result.add(parseDataType(p)) parseColumnConstraints(p, result) -proc parseIfNotExists(p: var TSqlParser, k: TSqlNodeKind): PSqlNode = +proc parseIfNotExists(p: var SqlParser, k: TSqlNodeKind): SqlNode = getTok(p) if isKeyw(p, "if"): getTok(p) @@ -824,7 +829,7 @@ proc parseIfNotExists(p: var TSqlParser, k: TSqlNodeKind): PSqlNode = else: result = newNode(k) -proc parseParIdentList(p: var TSqlParser, father: PSqlNode) = +proc parseParIdentList(p: var SqlParser, father: SqlNode) = eat(p, tkParLe) while true: expectIdent(p) @@ -834,7 +839,7 @@ proc parseParIdentList(p: var TSqlParser, father: PSqlNode) = getTok(p) eat(p, tkParRi) -proc parseTableConstraint(p: var TSqlParser): PSqlNode = +proc parseTableConstraint(p: var SqlParser): SqlNode = if isKeyw(p, "primary"): getTok(p) eat(p, "key") @@ -861,7 +866,7 @@ proc parseTableConstraint(p: var TSqlParser): PSqlNode = else: sqlError(p, "column definition expected") -proc parseTableDef(p: var TSqlParser): PSqlNode = +proc parseTableDef(p: var SqlParser): SqlNode = result = parseIfNotExists(p, nkCreateTable) expectIdent(p) result.add(newNode(nkIdent, p.tok.literal)) @@ -876,7 +881,7 @@ proc parseTableDef(p: var TSqlParser): PSqlNode = if p.tok.kind != tkComma: break eat(p, tkParRi) -proc parseTypeDef(p: var TSqlParser): PSqlNode = +proc parseTypeDef(p: var SqlParser): SqlNode = result = parseIfNotExists(p, nkCreateType) expectIdent(p) result.add(newNode(nkIdent, p.tok.literal)) @@ -884,12 +889,12 @@ proc parseTypeDef(p: var TSqlParser): PSqlNode = eat(p, "as") result.add(parseDataType(p)) -proc parseWhere(p: var TSqlParser): PSqlNode = +proc parseWhere(p: var SqlParser): SqlNode = getTok(p) result = newNode(nkWhere) result.add(parseExpr(p)) -proc parseIndexDef(p: var TSqlParser): PSqlNode = +proc parseIndexDef(p: var SqlParser): SqlNode = result = parseIfNotExists(p, nkCreateIndex) if isKeyw(p, "primary"): getTok(p) @@ -914,7 +919,7 @@ proc parseIndexDef(p: var TSqlParser): PSqlNode = getTok(p) eat(p, tkParRi) -proc parseInsert(p: var TSqlParser): PSqlNode = +proc parseInsert(p: var SqlParser): SqlNode = getTok(p) eat(p, "into") expectIdent(p) @@ -941,7 +946,7 @@ proc parseInsert(p: var TSqlParser): PSqlNode = result.add(n) eat(p, tkParRi) -proc parseUpdate(p: var TSqlParser): PSqlNode = +proc parseUpdate(p: var SqlParser): SqlNode = getTok(p) result = newNode(nkUpdate) result.add(primary(p)) @@ -962,7 +967,7 @@ proc parseUpdate(p: var TSqlParser): PSqlNode = else: result.add(nil) -proc parseDelete(p: var TSqlParser): PSqlNode = +proc parseDelete(p: var SqlParser): SqlNode = getTok(p) result = newNode(nkDelete) eat(p, "from") @@ -972,7 +977,7 @@ proc parseDelete(p: var TSqlParser): PSqlNode = else: result.add(nil) -proc parseSelect(p: var TSqlParser): PSqlNode = +proc parseSelect(p: var SqlParser): SqlNode = getTok(p) if isKeyw(p, "distinct"): getTok(p) @@ -1041,7 +1046,7 @@ proc parseSelect(p: var TSqlParser): PSqlNode = getTok(p) result.add(n) -proc parseStmt(p: var TSqlParser): PSqlNode = +proc parseStmt(p: var SqlParser): SqlNode = if isKeyw(p, "create"): getTok(p) optKeyw(p, "cached") @@ -1071,7 +1076,7 @@ proc parseStmt(p: var TSqlParser): PSqlNode = else: sqlError(p, "CREATE expected") -proc open(p: var TSqlParser, input: PStream, filename: string) = +proc open(p: var SqlParser, input: PStream, filename: string) = ## opens the parser `p` and assigns the input stream `input` to it. ## `filename` is only used for error messages. open(TSqlLexer(p), input, filename) @@ -1079,7 +1084,7 @@ proc open(p: var TSqlParser, input: PStream, filename: string) = p.tok.literal = "" getTok(p) -proc parse(p: var TSqlParser): PSqlNode = +proc parse(p: var SqlParser): SqlNode = ## parses the content of `p`'s input stream and returns the SQL AST. ## Syntax errors raise an `EInvalidSql` exception. result = newNode(nkStmtList) @@ -1090,24 +1095,24 @@ proc parse(p: var TSqlParser): PSqlNode = if result.len == 1: result = result.sons[0] -proc close(p: var TSqlParser) = +proc close(p: var SqlParser) = ## closes the parser `p`. The associated input stream is closed too. close(TSqlLexer(p)) -proc parseSQL*(input: PStream, filename: string): PSqlNode = +proc parseSQL*(input: PStream, filename: string): SqlNode = ## parses the SQL from `input` into an AST and returns the AST. ## `filename` is only used for error messages. ## Syntax errors raise an `EInvalidSql` exception. - var p: TSqlParser + var p: SqlParser open(p, input, filename) try: result = parse(p) finally: close(p) -proc ra(n: PSqlNode, s: var string, indent: int) +proc ra(n: SqlNode, s: var string, indent: int) -proc rs(n: PSqlNode, s: var string, indent: int, +proc rs(n: SqlNode, s: var string, indent: int, prefix = "(", suffix = ")", sep = ", ") = if n.len > 0: @@ -1117,7 +1122,7 @@ proc rs(n: PSqlNode, s: var string, indent: int, ra(n.sons[i], s, indent) s.add(suffix) -proc ra(n: PSqlNode, s: var string, indent: int) = +proc ra(n: SqlNode, s: var string, indent: int) = if n == nil: return case n.kind of nkNone: discard @@ -1320,7 +1325,7 @@ proc ra(n: PSqlNode, s: var string, indent: int) = #for x, y, z in db.select(fromm = a, b where = a.name == b.name): # writeln x, y, z -proc renderSQL*(n: PSqlNode): string = +proc renderSQL*(n: SqlNode): string = ## Converts an SQL abstract syntax tree to its string representation. result = "" ra(n, result, 0) diff --git a/lib/pure/parseurl.nim b/lib/pure/parseurl.nim index 67c6de905..2637a879d 100644 --- a/lib/pure/parseurl.nim +++ b/lib/pure/parseurl.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2014 Dominik Picheta # # See the file "copying.txt", included in this @@ -15,12 +15,14 @@ import strutils type - TUrl* = tuple[ ## represents a *Uniform Resource Locator* (URL) - ## any optional component is "" if it does not exist + Url* = tuple[ ## represents a *Uniform Resource Locator* (URL) + ## any optional component is "" if it does not exist scheme, username, password, hostname, port, path, query, anchor: string] - -proc parseUrl*(url: string): TUrl {.deprecated.} = + +{.deprecated: [TUrl: Url].} + +proc parseUrl*(url: string): Url {.deprecated.} = var i = 0 var scheme, username, password: string = "" @@ -86,7 +88,7 @@ proc parseUrl*(url: string): TUrl {.deprecated.} = return (scheme, username, password, hostname, port, path, query, anchor) -proc `$`*(u: TUrl): string {.deprecated.} = +proc `$`*(u: Url): string {.deprecated.} = ## turns the URL `u` into its string representation. result = "" if u.scheme.len > 0: diff --git a/lib/pure/parseutils.nim b/lib/pure/parseutils.nim index 0c045bc5a..38a3cbc5e 100644 --- a/lib/pure/parseutils.nim +++ b/lib/pure/parseutils.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -35,7 +35,7 @@ proc parseHex*(s: string, number: var int, start = 0): int {. ## can use this feature to *chain* calls, though the result int will quickly ## overflow. Example: ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## var value = 0 ## discard parseHex("0x38", value) ## assert value == 56 @@ -332,7 +332,7 @@ proc parseFloat*(s: string, number: var float, start = 0): int {. number = bf type - TInterpolatedKind* = enum ## describes for `interpolatedFragments` + InterpolatedKind* = enum ## describes for `interpolatedFragments` ## which part of the interpolated string is ## yielded; for example in "str$$$var${expr}" ikStr, ## ``str`` part of the interpolated string @@ -340,7 +340,9 @@ type ikVar, ## ``var`` part of the interpolated string ikExpr ## ``expr`` part of the interpolated string -iterator interpolatedFragments*(s: string): tuple[kind: TInterpolatedKind, +{.deprecated: [TInterpolatedKind: InterpolatedKind].} + +iterator interpolatedFragments*(s: string): tuple[kind: InterpolatedKind, value: string] = ## Tokenizes the string `s` into substrings for interpolation purposes. ## @@ -360,7 +362,7 @@ iterator interpolatedFragments*(s: string): tuple[kind: TInterpolatedKind, ## (ikString, " ") ## (ikDollar, "$") var i = 0 - var kind: TInterpolatedKind + var kind: InterpolatedKind while true: var j = i if s[j] == '$': diff --git a/lib/pure/parsexml.nim b/lib/pure/parsexml.nim index 667b8aed6..2d944917f 100644 --- a/lib/pure/parsexml.nim +++ b/lib/pure/parsexml.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2010 Andreas Rumpf # # See the file "copying.txt", included in this @@ -56,7 +56,7 @@ import # xmlElementCloseEnd, ## ``/>`` type - TXmlEventKind* = enum ## enumation of all events that may occur when parsing + XmlEventKind* = enum ## enumation of all events that may occur when parsing xmlError, ## an error ocurred during parsing xmlEof, ## end of file reached xmlCharData, ## character data @@ -72,7 +72,7 @@ type xmlEntity, ## &entity; xmlSpecial ## ``<! ... data ... >`` - TXmlError* = enum ## enumeration that lists all errors that can occur + XmlErrorKind* = enum ## enumeration that lists all errors that can occur errNone, ## no error errEndOfCDataExpected, ## ``]]>`` expected errNameExpected, ## name expected @@ -83,23 +83,26 @@ type errQuoteExpected, ## ``"`` or ``'`` expected errEndOfCommentExpected ## ``-->`` expected - TParserState = enum + ParserState = enum stateStart, stateNormal, stateAttr, stateEmptyElementTag, stateError - TXmlParseOption* = enum ## options for the XML parser + XmlParseOption* = enum ## options for the XML parser reportWhitespace, ## report whitespace reportComments ## report comments - TXmlParser* = object of TBaseLexer ## the parser object. + XmlParser* = object of TBaseLexer ## the parser object. a, b, c: string - kind: TXmlEventKind - err: TXmlError - state: TParserState + kind: XmlEventKind + err: XmlErrorKind + state: ParserState filename: string - options: set[TXmlParseOption] - + options: set[XmlParseOption] + +{.deprecated: [TXmlParser: XmlParser, TXmlParseOptions: XmlParseOptions, + TXmlError: XmlErrorKind, TXmlEventKind: XmlEventKind].} + const - errorMessages: array [TXmlError, string] = [ + errorMessages: array[XmlError, string] = [ "no error", "']]>' expected", "name expected", @@ -111,8 +114,8 @@ const "'-->' expected" ] -proc open*(my: var TXmlParser, input: PStream, filename: string, - options: set[TXmlParseOption] = {}) = +proc open*(my: var XmlParser, input: Stream, filename: string, + options: set[XmlParseOption] = {}) = ## initializes the parser with an input stream. `Filename` is only used ## for nice error messages. The parser's behaviour can be controlled by ## the `options` parameter: If `options` contains ``reportWhitespace`` @@ -127,7 +130,7 @@ proc open*(my: var TXmlParser, input: PStream, filename: string, my.b = "" my.options = options -proc close*(my: var TXmlParser) {.inline.} = +proc close*(my: var XmlParser) {.inline.} = ## closes the parser `my` and its associated input stream. lexbase.close(my) diff --git a/lib/pure/pegs.nim b/lib/pure/pegs.nim index efe169c1d..8bd307c7d 100644 --- a/lib/pure/pegs.nim +++ b/lib/pure/pegs.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -32,7 +32,7 @@ const ## can be captured. More subpatterns cannot be captured! type - TPegKind = enum + PegKind = enum pkEmpty, pkAny, ## any character (.) pkAnyRune, ## any Unicode character (_) @@ -67,16 +67,16 @@ type pkRule, ## a <- b pkList, ## a, b pkStartAnchor ## ^ --> Internal DSL: startAnchor() - TNonTerminalFlag = enum + NonTerminalFlag = enum ntDeclared, ntUsed - TNonTerminal {.final.} = object ## represents a non terminal symbol + NonTerminalObj = object ## represents a non terminal symbol name: string ## the name of the symbol line: int ## line the symbol has been declared/used in col: int ## column the symbol has been declared/used in - flags: set[TNonTerminalFlag] ## the nonterminal's flags + flags: set[NonTerminalFlag] ## the nonterminal's flags rule: TNode ## the rule that the symbol refers to - TNode {.final, shallow.} = object - case kind: TPegKind + TNode {.shallow.} = object + case kind: PegKind of pkEmpty..pkWhitespace: nil of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle: term: string of pkChar, pkGreedyRepChar: ch: char @@ -84,11 +84,13 @@ type of pkNonTerminal: nt: PNonTerminal of pkBackRef..pkBackRefIgnoreStyle: index: range[0..MaxSubpatterns] else: sons: seq[TNode] - PNonTerminal* = ref TNonTerminal + NonTerminal* = ref NonTerminalObj - TPeg* = TNode ## type that represents a PEG + Peg* = TNode ## type that represents a PEG -proc term*(t: string): TPeg {.nosideEffect, rtl, extern: "npegs$1Str".} = +{.deprecated: [TPeg: Peg].} + +proc term*(t: string): Peg {.nosideEffect, rtl, extern: "npegs$1Str".} = ## constructs a PEG from a terminal string if t.len != 1: result.kind = pkTerminal @@ -97,35 +99,35 @@ proc term*(t: string): TPeg {.nosideEffect, rtl, extern: "npegs$1Str".} = result.kind = pkChar result.ch = t[0] -proc termIgnoreCase*(t: string): TPeg {. +proc termIgnoreCase*(t: string): Peg {. nosideEffect, rtl, extern: "npegs$1".} = ## constructs a PEG from a terminal string; ignore case for matching result.kind = pkTerminalIgnoreCase result.term = t -proc termIgnoreStyle*(t: string): TPeg {. +proc termIgnoreStyle*(t: string): Peg {. nosideEffect, rtl, extern: "npegs$1".} = ## constructs a PEG from a terminal string; ignore style for matching result.kind = pkTerminalIgnoreStyle result.term = t -proc term*(t: char): TPeg {.nosideEffect, rtl, extern: "npegs$1Char".} = +proc term*(t: char): Peg {.nosideEffect, rtl, extern: "npegs$1Char".} = ## constructs a PEG from a terminal char assert t != '\0' result.kind = pkChar result.ch = t -proc charSet*(s: set[char]): TPeg {.nosideEffect, rtl, extern: "npegs$1".} = +proc charSet*(s: set[char]): Peg {.nosideEffect, rtl, extern: "npegs$1".} = ## constructs a PEG from a character set `s` assert '\0' notin s result.kind = pkCharChoice new(result.charChoice) result.charChoice[] = s -proc len(a: TPeg): int {.inline.} = return a.sons.len -proc add(d: var TPeg, s: TPeg) {.inline.} = add(d.sons, s) +proc len(a: Peg): int {.inline.} = return a.sons.len +proc add(d: var Peg, s: Peg) {.inline.} = add(d.sons, s) -proc addChoice(dest: var TPeg, elem: TPeg) = +proc addChoice(dest: var Peg, elem: Peg) = var L = dest.len-1 if L >= 0 and dest.sons[L].kind == pkCharChoice: # caution! Do not introduce false aliasing here! @@ -137,7 +139,7 @@ proc addChoice(dest: var TPeg, elem: TPeg) = else: add(dest, elem) else: add(dest, elem) -template multipleOp(k: TPegKind, localOpt: expr) = +template multipleOp(k: PegKind, localOpt: expr) = result.kind = k result.sons = @[] for x in items(a): @@ -149,12 +151,12 @@ template multipleOp(k: TPegKind, localOpt: expr) = if result.len == 1: result = result.sons[0] -proc `/`*(a: varargs[TPeg]): TPeg {. +proc `/`*(a: varargs[Peg]): Peg {. nosideEffect, rtl, extern: "npegsOrderedChoice".} = ## constructs an ordered choice with the PEGs in `a` multipleOp(pkOrderedChoice, addChoice) -proc addSequence(dest: var TPeg, elem: TPeg) = +proc addSequence(dest: var Peg, elem: Peg) = var L = dest.len-1 if L >= 0 and dest.sons[L].kind == pkTerminal: # caution! Do not introduce false aliasing here! @@ -166,12 +168,12 @@ proc addSequence(dest: var TPeg, elem: TPeg) = else: add(dest, elem) else: add(dest, elem) -proc sequence*(a: varargs[TPeg]): TPeg {. +proc sequence*(a: varargs[Peg]): Peg {. nosideEffect, rtl, extern: "npegs$1".} = ## constructs a sequence with all the PEGs from `a` multipleOp(pkSequence, addSequence) -proc `?`*(a: TPeg): TPeg {.nosideEffect, rtl, extern: "npegsOptional".} = +proc `?`*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsOptional".} = ## constructs an optional for the PEG `a` if a.kind in {pkOption, pkGreedyRep, pkGreedyAny, pkGreedyRepChar, pkGreedyRepSet}: @@ -182,7 +184,7 @@ proc `?`*(a: TPeg): TPeg {.nosideEffect, rtl, extern: "npegsOptional".} = result.kind = pkOption result.sons = @[a] -proc `*`*(a: TPeg): TPeg {.nosideEffect, rtl, extern: "npegsGreedyRep".} = +proc `*`*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsGreedyRep".} = ## constructs a "greedy repetition" for the PEG `a` case a.kind of pkGreedyRep, pkGreedyRepChar, pkGreedyRepSet, pkGreedyAny, pkOption: @@ -200,111 +202,99 @@ proc `*`*(a: TPeg): TPeg {.nosideEffect, rtl, extern: "npegsGreedyRep".} = result.kind = pkGreedyRep result.sons = @[a] -proc `!*`*(a: TPeg): TPeg {.nosideEffect, rtl, extern: "npegsSearch".} = +proc `!*`*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsSearch".} = ## constructs a "search" for the PEG `a` result.kind = pkSearch result.sons = @[a] -proc `!*\`*(a: TPeg): TPeg {.noSideEffect, rtl, +proc `!*\`*(a: Peg): Peg {.noSideEffect, rtl, extern: "npgegsCapturedSearch".} = ## constructs a "captured search" for the PEG `a` result.kind = pkCapturedSearch result.sons = @[a] - -when false: - proc contains(a: TPeg, k: TPegKind): bool = - if a.kind == k: return true - case a.kind - of pkEmpty, pkAny, pkAnyRune, pkGreedyAny, pkNewLine, pkTerminal, - pkTerminalIgnoreCase, pkTerminalIgnoreStyle, pkChar, pkGreedyRepChar, - pkCharChoice, pkGreedyRepSet: nil - of pkNonTerminal: return true - else: - for i in 0..a.sons.len-1: - if contains(a.sons[i], k): return true -proc `+`*(a: TPeg): TPeg {.nosideEffect, rtl, extern: "npegsGreedyPosRep".} = +proc `+`*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsGreedyPosRep".} = ## constructs a "greedy positive repetition" with the PEG `a` return sequence(a, *a) -proc `&`*(a: TPeg): TPeg {.nosideEffect, rtl, extern: "npegsAndPredicate".} = +proc `&`*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsAndPredicate".} = ## constructs an "and predicate" with the PEG `a` result.kind = pkAndPredicate result.sons = @[a] -proc `!`*(a: TPeg): TPeg {.nosideEffect, rtl, extern: "npegsNotPredicate".} = +proc `!`*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsNotPredicate".} = ## constructs a "not predicate" with the PEG `a` result.kind = pkNotPredicate result.sons = @[a] -proc any*: TPeg {.inline.} = +proc any*: Peg {.inline.} = ## constructs the PEG `any character`:idx: (``.``) result.kind = pkAny -proc anyRune*: TPeg {.inline.} = +proc anyRune*: Peg {.inline.} = ## constructs the PEG `any rune`:idx: (``_``) result.kind = pkAnyRune -proc newLine*: TPeg {.inline.} = +proc newLine*: Peg {.inline.} = ## constructs the PEG `newline`:idx: (``\n``) result.kind = pkNewline -proc unicodeLetter*: TPeg {.inline.} = +proc unicodeLetter*: Peg {.inline.} = ## constructs the PEG ``\letter`` which matches any Unicode letter. result.kind = pkLetter -proc unicodeLower*: TPeg {.inline.} = +proc unicodeLower*: Peg {.inline.} = ## constructs the PEG ``\lower`` which matches any Unicode lowercase letter. result.kind = pkLower -proc unicodeUpper*: TPeg {.inline.} = +proc unicodeUpper*: Peg {.inline.} = ## constructs the PEG ``\upper`` which matches any Unicode uppercase letter. result.kind = pkUpper -proc unicodeTitle*: TPeg {.inline.} = +proc unicodeTitle*: Peg {.inline.} = ## constructs the PEG ``\title`` which matches any Unicode title letter. result.kind = pkTitle -proc unicodeWhitespace*: TPeg {.inline.} = +proc unicodeWhitespace*: Peg {.inline.} = ## constructs the PEG ``\white`` which matches any Unicode ## whitespace character. result.kind = pkWhitespace -proc startAnchor*: TPeg {.inline.} = +proc startAnchor*: Peg {.inline.} = ## constructs the PEG ``^`` which matches the start of the input. result.kind = pkStartAnchor -proc endAnchor*: TPeg {.inline.} = +proc endAnchor*: Peg {.inline.} = ## constructs the PEG ``$`` which matches the end of the input. result = !any() -proc capture*(a: TPeg): TPeg {.nosideEffect, rtl, extern: "npegsCapture".} = +proc capture*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsCapture".} = ## constructs a capture with the PEG `a` result.kind = pkCapture result.sons = @[a] -proc backref*(index: range[1..MaxSubPatterns]): TPeg {. +proc backref*(index: range[1..MaxSubPatterns]): Peg {. nosideEffect, rtl, extern: "npegs$1".} = ## constructs a back reference of the given `index`. `index` starts counting ## from 1. result.kind = pkBackRef result.index = index-1 -proc backrefIgnoreCase*(index: range[1..MaxSubPatterns]): TPeg {. +proc backrefIgnoreCase*(index: range[1..MaxSubPatterns]): Peg {. nosideEffect, rtl, extern: "npegs$1".} = ## constructs a back reference of the given `index`. `index` starts counting ## from 1. Ignores case for matching. result.kind = pkBackRefIgnoreCase result.index = index-1 -proc backrefIgnoreStyle*(index: range[1..MaxSubPatterns]): TPeg {. +proc backrefIgnoreStyle*(index: range[1..MaxSubPatterns]): Peg {. nosideEffect, rtl, extern: "npegs$1".}= ## constructs a back reference of the given `index`. `index` starts counting ## from 1. Ignores style for matching. result.kind = pkBackRefIgnoreStyle result.index = index-1 -proc spaceCost(n: TPeg): int = +proc spaceCost(n: Peg): int = case n.kind of pkEmpty: discard of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle, pkChar, @@ -319,7 +309,7 @@ proc spaceCost(n: TPeg): int = inc(result, spaceCost(n.sons[i])) if result >= InlineThreshold: break -proc nonterminal*(n: PNonTerminal): TPeg {. +proc nonterminal*(n: PNonTerminal): Peg {. nosideEffect, rtl, extern: "npegs$1".} = ## constructs a PEG that consists of the nonterminal symbol assert n != nil @@ -415,7 +405,7 @@ proc charSetEsc(cc: set[char]): string = else: result = '[' & charSetEscAux(cc) & ']' -proc toStrAux(r: TPeg, res: var string) = +proc toStrAux(r: Peg, res: var string) = case r.kind of pkEmpty: add(res, "()") of pkAny: add(res, '.') @@ -501,7 +491,7 @@ proc toStrAux(r: TPeg, res: var string) = of pkStartAnchor: add(res, '^') -proc `$` *(r: TPeg): string {.nosideEffect, rtl, extern: "npegsToString".} = +proc `$` *(r: Peg): string {.nosideEffect, rtl, extern: "npegsToString".} = ## converts a PEG to its string representation result = "" toStrAux(r, result) @@ -509,12 +499,14 @@ proc `$` *(r: TPeg): string {.nosideEffect, rtl, extern: "npegsToString".} = # --------------------- core engine ------------------------------------------- type - TCaptures* {.final.} = object ## contains the captured substrings. + Captures* = object ## contains the captured substrings. matches: array[0..maxSubpatterns-1, tuple[first, last: int]] ml: int origStart: int -proc bounds*(c: TCaptures, +{.deprecated: [TCaptures: Captures].} + +proc bounds*(c: Captures, i: range[0..maxSubpatterns-1]): tuple[first, last: int] = ## returns the bounds ``[first..last]`` of the `i`'th capture. result = c.matches[i] @@ -533,7 +525,7 @@ when not useUnicode: proc isTitle(a: char): bool {.inline.} = return false proc isWhiteSpace(a: char): bool {.inline.} = return a in {' ', '\9'..'\13'} -proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {. +proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {. nosideEffect, rtl, extern: "npegs$1".} = ## low-level matching proc that implements the PEG interpreter. Use this ## for maximum efficiency (every other PEG operation ends up calling this @@ -734,7 +726,7 @@ proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {. of pkBackRef..pkBackRefIgnoreStyle: if p.index >= c.ml: return -1 var (a, b) = c.matches[p.index] - var n: TPeg + var n: Peg n.kind = succ(pkTerminal, ord(p.kind)-ord(pkBackRef)) n.term = s.substr(a, b) result = rawMatch(s, n, start, c) @@ -747,51 +739,51 @@ template fillMatches(s, caps, c: expr) = for k in 0..c.ml-1: caps[k] = substr(s, c.matches[k][0], c.matches[k][1]) -proc match*(s: string, pattern: TPeg, matches: var openArray[string], +proc match*(s: string, pattern: Peg, matches: var openArray[string], start = 0): bool {.nosideEffect, rtl, extern: "npegs$1Capture".} = ## returns ``true`` if ``s[start..]`` matches the ``pattern`` and ## the captured substrings in the array ``matches``. If it does not ## match, nothing is written into ``matches`` and ``false`` is ## returned. - var c: TCaptures + var c: Captures c.origStart = start result = rawMatch(s, pattern, start, c) == len(s) - start if result: fillMatches(s, matches, c) -proc match*(s: string, pattern: TPeg, +proc match*(s: string, pattern: Peg, start = 0): bool {.nosideEffect, rtl, extern: "npegs$1".} = ## returns ``true`` if ``s`` matches the ``pattern`` beginning from ``start``. - var c: TCaptures + var c: Captures c.origStart = start result = rawMatch(s, pattern, start, c) == len(s)-start -proc matchLen*(s: string, pattern: TPeg, matches: var openArray[string], +proc matchLen*(s: string, pattern: Peg, matches: var openArray[string], start = 0): int {.nosideEffect, rtl, extern: "npegs$1Capture".} = ## the same as ``match``, but it returns the length of the match, ## if there is no match, -1 is returned. Note that a match length ## of zero can happen. It's possible that a suffix of `s` remains ## that does not belong to the match. - var c: TCaptures + var c: Captures c.origStart = start result = rawMatch(s, pattern, start, c) if result >= 0: fillMatches(s, matches, c) -proc matchLen*(s: string, pattern: TPeg, +proc matchLen*(s: string, pattern: Peg, start = 0): int {.nosideEffect, rtl, extern: "npegs$1".} = ## the same as ``match``, but it returns the length of the match, ## if there is no match, -1 is returned. Note that a match length ## of zero can happen. It's possible that a suffix of `s` remains ## that does not belong to the match. - var c: TCaptures + var c: Captures c.origStart = start result = rawMatch(s, pattern, start, c) -proc find*(s: string, pattern: TPeg, matches: var openArray[string], +proc find*(s: string, pattern: Peg, matches: var openArray[string], start = 0): int {.nosideEffect, rtl, extern: "npegs$1Capture".} = ## returns the starting position of ``pattern`` in ``s`` and the captured ## substrings in the array ``matches``. If it does not match, nothing ## is written into ``matches`` and -1 is returned. - var c: TCaptures + var c: Captures c.origStart = start for i in start .. s.len-1: c.ml = 0 @@ -801,14 +793,14 @@ proc find*(s: string, pattern: TPeg, matches: var openArray[string], return -1 # could also use the pattern here: (!P .)* P -proc findBounds*(s: string, pattern: TPeg, matches: var openArray[string], +proc findBounds*(s: string, pattern: Peg, matches: var openArray[string], start = 0): tuple[first, last: int] {. nosideEffect, rtl, extern: "npegs$1Capture".} = ## returns the starting position and end position of ``pattern`` in ``s`` ## and the captured ## substrings in the array ``matches``. If it does not match, nothing ## is written into ``matches`` and (-1,0) is returned. - var c: TCaptures + var c: Captures c.origStart = start for i in start .. s.len-1: c.ml = 0 @@ -818,19 +810,19 @@ proc findBounds*(s: string, pattern: TPeg, matches: var openArray[string], return (i, i+L-1) return (-1, 0) -proc find*(s: string, pattern: TPeg, +proc find*(s: string, pattern: Peg, start = 0): int {.nosideEffect, rtl, extern: "npegs$1".} = ## returns the starting position of ``pattern`` in ``s``. If it does not ## match, -1 is returned. - var c: TCaptures + var c: Captures c.origStart = start for i in start .. s.len-1: if rawMatch(s, pattern, i, c) >= 0: return i return -1 -iterator findAll*(s: string, pattern: TPeg, start = 0): string = +iterator findAll*(s: string, pattern: Peg, start = 0): string = ## yields all matching *substrings* of `s` that match `pattern`. - var c: TCaptures + var c: Captures c.origStart = start var i = start while i < s.len: @@ -842,7 +834,7 @@ iterator findAll*(s: string, pattern: TPeg, start = 0): string = yield substr(s, i, i+L-1) inc(i, L) -proc findAll*(s: string, pattern: TPeg, start = 0): seq[string] {. +proc findAll*(s: string, pattern: Peg, start = 0): seq[string] {. nosideEffect, rtl, extern: "npegs$1".} = ## returns all matching *substrings* of `s` that match `pattern`. ## If it does not match, @[] is returned. @@ -851,11 +843,11 @@ proc findAll*(s: string, pattern: TPeg, start = 0): seq[string] {. when not defined(nimhygiene): {.pragma: inject.} -template `=~`*(s: string, pattern: TPeg): bool = +template `=~`*(s: string, pattern: Peg): bool = ## This calls ``match`` with an implicit declared ``matches`` array that ## can be used in the scope of the ``=~`` call: ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## ## if line =~ peg"\s* {\w+} \s* '=' \s* {\w+}": ## # matches a key=value pair: @@ -876,46 +868,46 @@ template `=~`*(s: string, pattern: TPeg): bool = # ------------------------- more string handling ------------------------------ -proc contains*(s: string, pattern: TPeg, start = 0): bool {. +proc contains*(s: string, pattern: Peg, start = 0): bool {. nosideEffect, rtl, extern: "npegs$1".} = ## same as ``find(s, pattern, start) >= 0`` return find(s, pattern, start) >= 0 -proc contains*(s: string, pattern: TPeg, matches: var openArray[string], +proc contains*(s: string, pattern: Peg, matches: var openArray[string], start = 0): bool {.nosideEffect, rtl, extern: "npegs$1Capture".} = ## same as ``find(s, pattern, matches, start) >= 0`` return find(s, pattern, matches, start) >= 0 -proc startsWith*(s: string, prefix: TPeg, start = 0): bool {. +proc startsWith*(s: string, prefix: Peg, start = 0): bool {. nosideEffect, rtl, extern: "npegs$1".} = ## returns true if `s` starts with the pattern `prefix` result = matchLen(s, prefix, start) >= 0 -proc endsWith*(s: string, suffix: TPeg, start = 0): bool {. +proc endsWith*(s: string, suffix: Peg, start = 0): bool {. nosideEffect, rtl, extern: "npegs$1".} = ## returns true if `s` ends with the pattern `prefix` - var c: TCaptures + var c: Captures c.origStart = start for i in start .. s.len-1: if rawMatch(s, suffix, i, c) == s.len - i: return true -proc replacef*(s: string, sub: TPeg, by: string): string {. +proc replacef*(s: string, sub: Peg, by: string): string {. nosideEffect, rtl, extern: "npegs$1".} = ## Replaces `sub` in `s` by the string `by`. Captures can be accessed in `by` ## with the notation ``$i`` and ``$#`` (see strutils.`%`). Examples: ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## "var1=key; var2=key2".replace(peg"{\ident}'='{\ident}", "$1<-$2$2") ## ## Results in: ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## ## "var1<-keykey; val2<-key2key2" result = "" var i = 0 var caps: array[0..maxSubpatterns-1, string] - var c: TCaptures + var c: Captures while i < s.len: c.ml = 0 var x = rawMatch(s, sub, i, c) @@ -928,13 +920,13 @@ proc replacef*(s: string, sub: TPeg, by: string): string {. inc(i, x) add(result, substr(s, i)) -proc replace*(s: string, sub: TPeg, by = ""): string {. +proc replace*(s: string, sub: Peg, by = ""): string {. nosideEffect, rtl, extern: "npegs$1".} = ## Replaces `sub` in `s` by the string `by`. Captures cannot be accessed ## in `by`. result = "" var i = 0 - var c: TCaptures + var c: Captures while i < s.len: var x = rawMatch(s, sub, i, c) if x <= 0: @@ -946,13 +938,13 @@ proc replace*(s: string, sub: TPeg, by = ""): string {. add(result, substr(s, i)) proc parallelReplace*(s: string, subs: varargs[ - tuple[pattern: TPeg, repl: string]]): string {. + tuple[pattern: Peg, repl: string]]): string {. nosideEffect, rtl, extern: "npegs$1".} = ## Returns a modified copy of `s` with the substitutions in `subs` ## applied in parallel. result = "" var i = 0 - var c: TCaptures + var c: Captures var caps: array[0..maxSubpatterns-1, string] while i < s.len: block searchSubs: @@ -970,7 +962,7 @@ proc parallelReplace*(s: string, subs: varargs[ add(result, substr(s, i)) proc transformFile*(infile, outfile: string, - subs: varargs[tuple[pattern: TPeg, repl: string]]) {. + subs: varargs[tuple[pattern: Peg, repl: string]]) {. rtl, extern: "npegs$1".} = ## reads in the file `infile`, performs a parallel replacement (calls ## `parallelReplace`) and writes back to `outfile`. Raises ``EIO`` if an @@ -978,25 +970,25 @@ proc transformFile*(infile, outfile: string, var x = readFile(infile).string writeFile(outfile, x.parallelReplace(subs)) -iterator split*(s: string, sep: TPeg): string = +iterator split*(s: string, sep: Peg): string = ## Splits the string `s` into substrings. ## ## Substrings are separated by the PEG `sep`. ## Examples: ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## for word in split("00232this02939is39an22example111", peg"\d+"): ## writeln(stdout, word) ## ## Results in: ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## "this" ## "is" ## "an" ## "example" ## - var c: TCaptures + var c: Captures var first = 0 last = 0 @@ -1013,7 +1005,7 @@ iterator split*(s: string, sep: TPeg): string = if first < last: yield substr(s, first, last-1) -proc split*(s: string, sep: TPeg): seq[string] {. +proc split*(s: string, sep: Peg): seq[string] {. nosideEffect, rtl, extern: "npegs$1".} = ## Splits the string `s` into substrings. accumulateResult(split(s, sep)) @@ -1060,7 +1052,7 @@ type charset: set[char] ## if kind == tkCharSet index: int ## if kind == tkBackref - TPegLexer {.inheritable.} = object ## the lexer object. + PegLexer {.inheritable.} = object ## the lexer object. bufpos: int ## the current position within the buffer buf: cstring ## the buffer itself LineNumber: int ## the current line number @@ -1076,20 +1068,20 @@ const "@", "built-in", "escaped", "$", "$", "^" ] -proc handleCR(L: var TPegLexer, pos: int): int = +proc handleCR(L: var PegLexer, pos: int): int = assert(L.buf[pos] == '\c') inc(L.linenumber) result = pos+1 if L.buf[result] == '\L': inc(result) L.lineStart = result -proc handleLF(L: var TPegLexer, pos: int): int = +proc handleLF(L: var PegLexer, pos: int): int = assert(L.buf[pos] == '\L') inc(L.linenumber) result = pos+1 L.lineStart = result -proc init(L: var TPegLexer, input, filename: string, line = 1, col = 0) = +proc init(L: var PegLexer, input, filename: string, line = 1, col = 0) = L.buf = input L.bufpos = 0 L.lineNumber = line @@ -1097,18 +1089,18 @@ proc init(L: var TPegLexer, input, filename: string, line = 1, col = 0) = L.lineStart = 0 L.filename = filename -proc getColumn(L: TPegLexer): int {.inline.} = +proc getColumn(L: PegLexer): int {.inline.} = result = abs(L.bufpos - L.lineStart) + L.colOffset -proc getLine(L: TPegLexer): int {.inline.} = +proc getLine(L: PegLexer): int {.inline.} = result = L.linenumber -proc errorStr(L: TPegLexer, msg: string, line = -1, col = -1): string = +proc errorStr(L: PegLexer, msg: string, line = -1, col = -1): string = var line = if line < 0: getLine(L) else: line var col = if col < 0: getColumn(L) else: col result = "$1($2, $3) Error: $4" % [L.filename, $line, $col, msg] -proc handleHexChar(c: var TPegLexer, xi: var int) = +proc handleHexChar(c: var PegLexer, xi: var int) = case c.buf[c.bufpos] of '0'..'9': xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('0')) @@ -1121,7 +1113,7 @@ proc handleHexChar(c: var TPegLexer, xi: var int) = inc(c.bufpos) else: discard -proc getEscapedChar(c: var TPegLexer, tok: var TToken) = +proc getEscapedChar(c: var PegLexer, tok: var TToken) = inc(c.bufpos) case c.buf[c.bufpos] of 'r', 'R', 'c', 'C': @@ -1173,7 +1165,7 @@ proc getEscapedChar(c: var TPegLexer, tok: var TToken) = add(tok.literal, c.buf[c.bufpos]) inc(c.bufpos) -proc skip(c: var TPegLexer) = +proc skip(c: var PegLexer) = var pos = c.bufpos var buf = c.buf while true: @@ -1192,7 +1184,7 @@ proc skip(c: var TPegLexer) = break # EndOfFile also leaves the loop c.bufpos = pos -proc getString(c: var TPegLexer, tok: var TToken) = +proc getString(c: var PegLexer, tok: var TToken) = tok.kind = tkStringLit var pos = c.bufPos + 1 var buf = c.buf @@ -1214,7 +1206,7 @@ proc getString(c: var TPegLexer, tok: var TToken) = inc(pos) c.bufpos = pos -proc getDollar(c: var TPegLexer, tok: var TToken) = +proc getDollar(c: var PegLexer, tok: var TToken) = var pos = c.bufPos + 1 var buf = c.buf if buf[pos] in {'0'..'9'}: @@ -1227,7 +1219,7 @@ proc getDollar(c: var TPegLexer, tok: var TToken) = tok.kind = tkDollar c.bufpos = pos -proc getCharSet(c: var TPegLexer, tok: var TToken) = +proc getCharSet(c: var PegLexer, tok: var TToken) = tok.kind = tkCharSet tok.charset = {} var pos = c.bufPos + 1 @@ -1278,7 +1270,7 @@ proc getCharSet(c: var TPegLexer, tok: var TToken) = c.bufpos = pos if caret: tok.charset = {'\1'..'\xFF'} - tok.charset -proc getSymbol(c: var TPegLexer, tok: var TToken) = +proc getSymbol(c: var PegLexer, tok: var TToken) = var pos = c.bufpos var buf = c.buf while true: @@ -1288,7 +1280,7 @@ proc getSymbol(c: var TPegLexer, tok: var TToken) = c.bufpos = pos tok.kind = tkIdentifier -proc getBuiltin(c: var TPegLexer, tok: var TToken) = +proc getBuiltin(c: var PegLexer, tok: var TToken) = if c.buf[c.bufpos+1] in strutils.Letters: inc(c.bufpos) getSymbol(c, tok) @@ -1297,7 +1289,7 @@ proc getBuiltin(c: var TPegLexer, tok: var TToken) = tok.kind = tkEscaped getEscapedChar(c, tok) # may set tok.kind to tkInvalid -proc getTok(c: var TPegLexer, tok: var TToken) = +proc getTok(c: var PegLexer, tok: var TToken) = tok.kind = tkInvalid tok.modifier = modNone setLen(tok.literal, 0) @@ -1403,7 +1395,7 @@ proc getTok(c: var TPegLexer, tok: var TToken) = add(tok.literal, c.buf[c.bufpos]) inc(c.bufpos) -proc arrowIsNextTok(c: TPegLexer): bool = +proc arrowIsNextTok(c: PegLexer): bool = # the only look ahead we need var pos = c.bufpos while c.buf[pos] in {'\t', ' '}: inc(pos) @@ -1414,31 +1406,31 @@ proc arrowIsNextTok(c: TPegLexer): bool = type EInvalidPeg* = object of EInvalidValue ## raised if an invalid ## PEG has been detected - TPegParser = object of TPegLexer ## the PEG parser object + PegParser = object of PegLexer ## the PEG parser object tok: TToken nonterms: seq[PNonTerminal] modifier: TModifier captures: int identIsVerbatim: bool - skip: TPeg + skip: Peg -proc pegError(p: TPegParser, msg: string, line = -1, col = -1) = +proc pegError(p: PegParser, msg: string, line = -1, col = -1) = var e: ref EInvalidPeg new(e) e.msg = errorStr(p, msg, line, col) raise e -proc getTok(p: var TPegParser) = +proc getTok(p: var PegParser) = getTok(p, p.tok) if p.tok.kind == tkInvalid: pegError(p, "invalid token") -proc eat(p: var TPegParser, kind: TTokKind) = +proc eat(p: var PegParser, kind: TTokKind) = if p.tok.kind == kind: getTok(p) else: pegError(p, tokKindToStr[kind] & " expected") -proc parseExpr(p: var TPegParser): TPeg +proc parseExpr(p: var PegParser): Peg -proc getNonTerminal(p: var TPegParser, name: string): PNonTerminal = +proc getNonTerminal(p: var PegParser, name: string): PNonTerminal = for i in 0..high(p.nonterms): result = p.nonterms[i] if cmpIgnoreStyle(result.name, name) == 0: return @@ -1446,19 +1438,19 @@ proc getNonTerminal(p: var TPegParser, name: string): PNonTerminal = result = newNonTerminal(name, getLine(p), getColumn(p)) add(p.nonterms, result) -proc modifiedTerm(s: string, m: TModifier): TPeg = +proc modifiedTerm(s: string, m: TModifier): Peg = case m of modNone, modVerbatim: result = term(s) of modIgnoreCase: result = termIgnoreCase(s) of modIgnoreStyle: result = termIgnoreStyle(s) -proc modifiedBackref(s: int, m: TModifier): TPeg = +proc modifiedBackref(s: int, m: TModifier): Peg = case m of modNone, modVerbatim: result = backref(s) of modIgnoreCase: result = backrefIgnoreCase(s) of modIgnoreStyle: result = backrefIgnoreStyle(s) -proc builtin(p: var TPegParser): TPeg = +proc builtin(p: var PegParser): Peg = # do not use "y", "skip" or "i" as these would be ambiguous case p.tok.literal of "n": result = newLine() @@ -1478,11 +1470,11 @@ proc builtin(p: var TPegParser): TPeg = of "white": result = unicodeWhitespace() else: pegError(p, "unknown built-in: " & p.tok.literal) -proc token(terminal: TPeg, p: TPegParser): TPeg = +proc token(terminal: Peg, p: PegParser): Peg = if p.skip.kind == pkEmpty: result = terminal else: result = sequence(p.skip, terminal) -proc primary(p: var TPegParser): TPeg = +proc primary(p: var PegParser): Peg = case p.tok.kind of tkAmp: getTok(p) @@ -1571,7 +1563,7 @@ proc primary(p: var TPegParser): TPeg = getTok(p) else: break -proc seqExpr(p: var TPegParser): TPeg = +proc seqExpr(p: var PegParser): Peg = result = primary(p) while true: case p.tok.kind @@ -1585,13 +1577,13 @@ proc seqExpr(p: var TPegParser): TPeg = else: break else: break -proc parseExpr(p: var TPegParser): TPeg = +proc parseExpr(p: var PegParser): Peg = result = seqExpr(p) while p.tok.kind == tkBar: getTok(p) result = result / seqExpr(p) -proc parseRule(p: var TPegParser): PNonTerminal = +proc parseRule(p: var PegParser): PNonTerminal = if p.tok.kind == tkIdentifier and arrowIsNextTok(p): result = getNonTerminal(p, p.tok.literal) if ntDeclared in result.flags: @@ -1605,7 +1597,7 @@ proc parseRule(p: var TPegParser): PNonTerminal = else: pegError(p, "rule expected, but found: " & p.tok.literal) -proc rawParse(p: var TPegParser): TPeg = +proc rawParse(p: var PegParser): Peg = ## parses a rule or a PEG expression while p.tok.kind == tkBuiltin: case p.tok.literal @@ -1635,12 +1627,12 @@ proc rawParse(p: var TPegParser): TPeg = elif ntUsed notin nt.flags and i > 0: pegError(p, "unused rule: " & nt.name, nt.line, nt.col) -proc parsePeg*(pattern: string, filename = "pattern", line = 1, col = 0): TPeg = - ## constructs a TPeg object from `pattern`. `filename`, `line`, `col` are +proc parsePeg*(pattern: string, filename = "pattern", line = 1, col = 0): Peg = + ## constructs a Peg object from `pattern`. `filename`, `line`, `col` are ## used for error messages, but they only provide start offsets. `parsePeg` ## keeps track of line and column numbers within `pattern`. - var p: TPegParser - init(TPegLexer(p), pattern, filename, line, col) + var p: PegParser + init(PegLexer(p), pattern, filename, line, col) p.tok.kind = tkInvalid p.tok.modifier = modNone p.tok.literal = "" @@ -1650,8 +1642,8 @@ proc parsePeg*(pattern: string, filename = "pattern", line = 1, col = 0): TPeg = getTok(p) result = rawParse(p) -proc peg*(pattern: string): TPeg = - ## constructs a TPeg object from the `pattern`. The short name has been +proc peg*(pattern: string): Peg = + ## constructs a Peg object from the `pattern`. The short name has been ## chosen to encourage its use as a raw string modifier:: ## ## peg"{\ident} \s* '=' \s* {.*}" @@ -1704,7 +1696,7 @@ when isMainModule: expr.rule = sequence(capture(ident), *sequence( nonterminal(ws), term('+'), nonterminal(ws), nonterminal(expr))) - var c: TCaptures + var c: Captures var s = "a+b + c +d+e+f" assert rawMatch(s, expr.rule, 0, c) == len(s) var a = "" diff --git a/lib/pure/poly.nim b/lib/pure/poly.nim index 45e528604..19bed2aca 100644 --- a/lib/pure/poly.nim +++ b/lib/pure/poly.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2013 Robert Persson # # See the file "copying.txt", included in this @@ -12,10 +12,11 @@ import strutils import numeric type - TPoly* = object - cofs:seq[float] + Poly* = object + cofs:seq[float] + +{.deprecated: [TPoly: Poly].} - proc degree*(p:TPoly):int= ## Returns the degree of the polynomial, ## that is the number of coefficients-1 @@ -104,7 +105,7 @@ proc `$` *(p:TPoly):string = result="0" -proc derivative*(p:TPoly):TPoly= +proc derivative*(p: TPoly): TPoly= ## Returns a new polynomial, which is the derivative of `p` newSeq[float](result.cofs,p.degree) for idx in 0..high(result.cofs): @@ -310,10 +311,10 @@ proc getRangeForRoots(p:TPoly):tuple[xmin,xmax:float]= var bound1,bound2:float for i in countup(0,deg): - var c=abs(p.cofs[i]/d) - bound1=max(bound1,c+1.0) - bound2=bound2+c - + var c=abs(p.cofs[i]/d) + bound1=max(bound1,c+1.0) + bound2=bound2+c + bound2=max(1.0,bound2) result.xmax=min(bound1,bound2) result.xmin= -result.xmax diff --git a/lib/pure/rawsockets.nim b/lib/pure/rawsockets.nim index fea09dfa2..14a494ecf 100644 --- a/lib/pure/rawsockets.nim +++ b/lib/pure/rawsockets.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2014 Dominik Picheta # # See the file "copying.txt", included in this @@ -28,7 +28,7 @@ else: export fcntl, F_GETFL, O_NONBLOCK, F_SETFL, EAGAIN, EWOULDBLOCK, MSG_NOSIGNAL, EINTR, EINPROGRESS, ECONNRESET, EPIPE, ENETRESET -export TSocketHandle, TSockaddr_in, TAddrinfo, INADDR_ANY, TSockAddr, TSockLen, +export SocketHandle, Sockaddr_in, Addrinfo, INADDR_ANY, SockAddr, SockLen, inet_ntoa, recv, `==`, connect, send, accept, recvfrom, sendto export @@ -40,22 +40,22 @@ export MSG_PEEK type - TPort* = distinct uint16 ## port type + Port* = distinct uint16 ## port type - TDomain* = enum ## domain, which specifies the protocol family of the + Domain* = enum ## domain, which specifies the protocol family of the ## created socket. Other domains than those that are listed ## here are unsupported. AF_UNIX, ## for local socket (using a file). Unsupported on Windows. AF_INET = 2, ## for network protocol IPv4 or AF_INET6 = 23 ## for network protocol IPv6. - TType* = enum ## second argument to `socket` proc + SockType* = enum ## second argument to `socket` proc SOCK_STREAM = 1, ## reliable stream-oriented service or Stream Sockets SOCK_DGRAM = 2, ## datagram service or Datagram Sockets SOCK_RAW = 3, ## raw protocols atop the network layer. SOCK_SEQPACKET = 5 ## reliable sequenced packet service - TProtocol* = enum ## third argument to `socket` proc + Protocol* = enum ## third argument to `socket` proc IPPROTO_TCP = 6, ## Transmission control protocol. IPPROTO_UDP = 17, ## User datagram protocol. IPPROTO_IP, ## Internet protocol. Unsupported on Windows. @@ -63,19 +63,22 @@ type IPPROTO_RAW, ## Raw IP Packets Protocol. Unsupported on Windows. IPPROTO_ICMP ## Control message protocol. Unsupported on Windows. - TServent* {.pure, final.} = object ## information about a service + Servent* = object ## information about a service name*: string aliases*: seq[string] - port*: TPort + port*: Port proto*: string - Thostent* {.pure, final.} = object ## information about a given host + Hostent* = object ## information about a given host name*: string aliases*: seq[string] - addrtype*: TDomain + addrtype*: Domain length*: int addrList*: seq[string] +{.deprecated: [TPort: Port, TDomain: Domain, TType: SockType, + TProtocol: Protocol, TServent: Servent, THostent: Hostent].} + when useWinVersion: let osInvalidSocket* = winlean.INVALID_SOCKET @@ -86,37 +89,37 @@ when useWinVersion: FIONBIO* = IOC_IN.int32 or ((sizeof(int32) and IOCPARM_MASK) shl 16) or (102 shl 8) or 126 - proc ioctlsocket*(s: TSocketHandle, cmd: clong, + proc ioctlsocket*(s: SocketHandle, cmd: clong, argptr: ptr clong): cint {. stdcall, importc: "ioctlsocket", dynlib: "ws2_32.dll".} else: let osInvalidSocket* = posix.INVALID_SOCKET -proc `==`*(a, b: TPort): bool {.borrow.} +proc `==`*(a, b: Port): bool {.borrow.} ## ``==`` for ports. -proc `$`*(p: TPort): string {.borrow.} +proc `$`*(p: Port): string {.borrow.} ## returns the port number as a string -proc toInt*(domain: TDomain): cint +proc toInt*(domain: Domain): cint ## Converts the TDomain enum to a platform-dependent ``cint``. -proc toInt*(typ: TType): cint +proc toInt*(typ: SockType): cint ## Converts the TType enum to a platform-dependent ``cint``. -proc toInt*(p: TProtocol): cint +proc toInt*(p: Protocol): cint ## Converts the TProtocol enum to a platform-dependent ``cint``. when not useWinVersion: - proc toInt(domain: TDomain): cint = + proc toInt(domain: Domain): cint = case domain of AF_UNIX: result = posix.AF_UNIX of AF_INET: result = posix.AF_INET of AF_INET6: result = posix.AF_INET6 else: discard - proc toInt(typ: TType): cint = + proc toInt(typ: SockType): cint = case typ of SOCK_STREAM: result = posix.SOCK_STREAM of SOCK_DGRAM: result = posix.SOCK_DGRAM @@ -124,7 +127,7 @@ when not useWinVersion: of SOCK_RAW: result = posix.SOCK_RAW else: discard - proc toInt(p: TProtocol): cint = + proc toInt(p: Protocol): cint = case p of IPPROTO_TCP: result = posix.IPPROTO_TCP of IPPROTO_UDP: result = posix.IPPROTO_UDP @@ -135,22 +138,22 @@ when not useWinVersion: else: discard else: - proc toInt(domain: TDomain): cint = + proc toInt(domain: Domain): cint = result = toU16(ord(domain)) - proc toInt(typ: TType): cint = + proc toInt(typ: SockType): cint = result = cint(ord(typ)) - proc toInt(p: TProtocol): cint = + proc toInt(p: Protocol): cint = result = cint(ord(p)) -proc newRawSocket*(domain: TDomain = AF_INET, typ: TType = SOCK_STREAM, - protocol: TProtocol = IPPROTO_TCP): TSocketHandle = +proc newRawSocket*(domain: Domain = AF_INET, typ: SockType = SOCK_STREAM, + protocol: Protocol = IPPROTO_TCP): SocketHandle = ## Creates a new socket; returns `InvalidSocket` if an error occurs. socket(toInt(domain), toInt(typ), toInt(protocol)) -proc close*(socket: TSocketHandle) = +proc close*(socket: SocketHandle) = ## closes a socket. when useWinVersion: discard winlean.closeSocket(socket) @@ -159,10 +162,10 @@ proc close*(socket: TSocketHandle) = # TODO: These values should not be discarded. An EOS should be raised. # http://stackoverflow.com/questions/12463473/what-happens-if-you-call-close-on-a-bsd-socket-multiple-times -proc bindAddr*(socket: TSocketHandle, name: ptr TSockAddr, namelen: TSockLen): cint = +proc bindAddr*(socket: SocketHandle, name: ptr SockAddr, namelen: SockLen): cint = result = bindSocket(socket, name, namelen) -proc listen*(socket: TSocketHandle, backlog = SOMAXCONN): cint {.tags: [FReadIO].} = +proc listen*(socket: SocketHandle, backlog = SOMAXCONN): cint {.tags: [FReadIO].} = ## Marks ``socket`` as accepting connections. ## ``Backlog`` specifies the maximum length of the ## queue of pending connections. @@ -171,12 +174,12 @@ proc listen*(socket: TSocketHandle, backlog = SOMAXCONN): cint {.tags: [FReadIO] else: result = posix.listen(socket, cint(backlog)) -proc getAddrInfo*(address: string, port: TPort, af: TDomain = AF_INET, typ: TType = SOCK_STREAM, - prot: TProtocol = IPPROTO_TCP): ptr TAddrInfo = +proc getAddrInfo*(address: string, port: Port, af: Domain = AF_INET, typ: SockType = SOCK_STREAM, + prot: Protocol = IPPROTO_TCP): ptr AddrInfo = ## ## ## **Warning**: The resulting ``ptr TAddrInfo`` must be freed using ``dealloc``! - var hints: TAddrInfo + var hints: AddrInfo result = nil hints.ai_family = toInt(af) hints.ai_socktype = toInt(typ) @@ -184,11 +187,11 @@ proc getAddrInfo*(address: string, port: TPort, af: TDomain = AF_INET, typ: TTyp var gaiResult = getAddrInfo(address, $port, addr(hints), result) if gaiResult != 0'i32: when useWinVersion: - osError(osLastError()) + raiseOSError(osLastError()) else: raise newException(EOS, $gai_strerror(gaiResult)) -proc dealloc*(ai: ptr TAddrInfo) = +proc dealloc*(ai: ptr AddrInfo) = freeaddrinfo(ai) proc ntohl*(x: int32): int32 = @@ -220,7 +223,7 @@ proc htons*(x: int16): int16 = ## order, this is a no-op; otherwise, it performs a 2-byte swap operation. result = rawsockets.ntohs(x) -proc getServByName*(name, proto: string): TServent {.tags: [FReadIO].} = +proc getServByName*(name, proto: string): Servent {.tags: [FReadIO].} = ## Searches the database from the beginning and finds the first entry for ## which the service name specified by ``name`` matches the s_name member ## and the protocol name specified by ``proto`` matches the s_proto member. @@ -233,10 +236,10 @@ proc getServByName*(name, proto: string): TServent {.tags: [FReadIO].} = if s == nil: raise newException(EOS, "Service not found.") result.name = $s.s_name result.aliases = cstringArrayToSeq(s.s_aliases) - result.port = TPort(s.s_port) + result.port = Port(s.s_port) result.proto = $s.s_proto -proc getServByPort*(port: TPort, proto: string): TServent {.tags: [FReadIO].} = +proc getServByPort*(port: Port, proto: string): Servent {.tags: [FReadIO].} = ## Searches the database from the beginning and finds the first entry for ## which the port specified by ``port`` matches the s_port member and the ## protocol name specified by ``proto`` matches the s_proto member. @@ -249,28 +252,28 @@ proc getServByPort*(port: TPort, proto: string): TServent {.tags: [FReadIO].} = if s == nil: raise newException(EOS, "Service not found.") result.name = $s.s_name result.aliases = cstringArrayToSeq(s.s_aliases) - result.port = TPort(s.s_port) + result.port = Port(s.s_port) result.proto = $s.s_proto -proc getHostByAddr*(ip: string): Thostent {.tags: [FReadIO].} = +proc getHostByAddr*(ip: string): Hostent {.tags: [FReadIO].} = ## This function will lookup the hostname of an IP Address. - var myaddr: TInAddr + var myaddr: InAddr myaddr.s_addr = inet_addr(ip) when useWinVersion: var s = winlean.gethostbyaddr(addr(myaddr), sizeof(myaddr).cuint, cint(rawsockets.AF_INET)) - if s == nil: osError(osLastError()) + if s == nil: raiseOSError(osLastError()) else: - var s = posix.gethostbyaddr(addr(myaddr), sizeof(myaddr).TSocklen, + var s = posix.gethostbyaddr(addr(myaddr), sizeof(myaddr).Socklen, cint(posix.AF_INET)) if s == nil: raise newException(EOS, $hstrerror(h_errno)) result.name = $s.h_name result.aliases = cstringArrayToSeq(s.h_aliases) - when useWinVersion: - result.addrtype = TDomain(s.h_addrtype) + when useWinVersion: + result.addrtype = Domain(s.h_addrtype) else: if s.h_addrtype == posix.AF_INET: result.addrtype = AF_INET @@ -281,17 +284,17 @@ proc getHostByAddr*(ip: string): Thostent {.tags: [FReadIO].} = result.addrList = cstringArrayToSeq(s.h_addr_list) result.length = int(s.h_length) -proc getHostByName*(name: string): Thostent {.tags: [FReadIO].} = +proc getHostByName*(name: string): Hostent {.tags: [FReadIO].} = ## This function will lookup the IP address of a hostname. when useWinVersion: var s = winlean.gethostbyname(name) else: var s = posix.gethostbyname(name) - if s == nil: osError(osLastError()) + if s == nil: raiseOSError(osLastError()) result.name = $s.h_name result.aliases = cstringArrayToSeq(s.h_aliases) - when useWinVersion: - result.addrtype = TDomain(s.h_addrtype) + when useWinVersion: + result.addrtype = Domain(s.h_addrtype) else: if s.h_addrtype == posix.AF_INET: result.addrtype = AF_INET @@ -302,69 +305,69 @@ proc getHostByName*(name: string): Thostent {.tags: [FReadIO].} = result.addrList = cstringArrayToSeq(s.h_addr_list) result.length = int(s.h_length) -proc getSockName*(socket: TSocketHandle): TPort = +proc getSockName*(socket: SocketHandle): Port = ## returns the socket's associated port number. - var name: Tsockaddr_in + var name: Sockaddr_in when useWinVersion: name.sin_family = int16(ord(AF_INET)) else: name.sin_family = posix.AF_INET #name.sin_port = htons(cint16(port)) #name.sin_addr.s_addr = htonl(INADDR_ANY) - var namelen = sizeof(name).TSocklen - if getsockname(socket, cast[ptr TSockAddr](addr(name)), + var namelen = sizeof(name).Socklen + if getsockname(socket, cast[ptr SockAddr](addr(name)), addr(namelen)) == -1'i32: - osError(osLastError()) - result = TPort(rawsockets.ntohs(name.sin_port)) + raiseOSError(osLastError()) + result = Port(rawsockets.ntohs(name.sin_port)) -proc getSockOptInt*(socket: TSocketHandle, level, optname: int): int {. +proc getSockOptInt*(socket: SocketHandle, level, optname: int): int {. tags: [FReadIO].} = ## getsockopt for integer options. var res: cint - var size = sizeof(res).TSocklen + var size = sizeof(res).Socklen if getsockopt(socket, cint(level), cint(optname), addr(res), addr(size)) < 0'i32: - osError(osLastError()) + raiseOSError(osLastError()) result = int(res) -proc setSockOptInt*(socket: TSocketHandle, level, optname, optval: int) {. +proc setSockOptInt*(socket: SocketHandle, level, optname, optval: int) {. tags: [FWriteIO].} = ## setsockopt for integer options. var value = cint(optval) if setsockopt(socket, cint(level), cint(optname), addr(value), - sizeof(value).TSocklen) < 0'i32: - osError(osLastError()) + sizeof(value).Socklen) < 0'i32: + raiseOSError(osLastError()) -proc setBlocking*(s: TSocketHandle, blocking: bool) = +proc setBlocking*(s: SocketHandle, blocking: bool) = ## Sets blocking mode on socket. ## ## Raises EOS on error. when useWinVersion: var mode = clong(ord(not blocking)) # 1 for non-blocking, 0 for blocking if ioctlsocket(s, FIONBIO, addr(mode)) == -1: - osError(osLastError()) + raiseOSError(osLastError()) else: # BSD sockets var x: int = fcntl(s, F_GETFL, 0) if x == -1: - osError(osLastError()) + raiseOSError(osLastError()) else: var mode = if blocking: x and not O_NONBLOCK else: x or O_NONBLOCK if fcntl(s, F_SETFL, mode) == -1: - osError(osLastError()) + raiseOSError(osLastError()) -proc timeValFromMilliseconds(timeout = 500): Ttimeval = +proc timeValFromMilliseconds(timeout = 500): Timeval = if timeout != -1: var seconds = timeout div 1000 result.tv_sec = seconds.int32 result.tv_usec = ((timeout - seconds * 1000) * 1000).int32 -proc createFdSet(fd: var TFdSet, s: seq[TSocketHandle], m: var int) = +proc createFdSet(fd: var FdSet, s: seq[SocketHandle], m: var int) = FD_ZERO(fd) for i in items(s): m = max(m, int(i)) FD_SET(i, fd) -proc pruneSocketSet(s: var seq[TSocketHandle], fd: var TFdSet) = +proc pruneSocketSet(s: var seq[SocketHandle], fd: var FdSet) = var i = 0 var L = s.len while i < L: @@ -375,7 +378,7 @@ proc pruneSocketSet(s: var seq[TSocketHandle], fd: var TFdSet) = inc(i) setLen(s, L) -proc select*(readfds: var seq[TSocketHandle], timeout = 500): int = +proc select*(readfds: var seq[SocketHandle], timeout = 500): int = ## Traditional select function. This function will return the number of ## sockets that are ready to be read from, written to, or which have errors. ## If there are none; 0 is returned. @@ -396,7 +399,7 @@ proc select*(readfds: var seq[TSocketHandle], timeout = 500): int = pruneSocketSet(readfds, (rd)) -proc selectWrite*(writefds: var seq[TSocketHandle], +proc selectWrite*(writefds: var seq[SocketHandle], timeout = 500): int {.tags: [FReadIO].} = ## When a socket in ``writefds`` is ready to be written to then a non-zero ## value will be returned specifying the count of the sockets which can be @@ -405,7 +408,7 @@ proc selectWrite*(writefds: var seq[TSocketHandle], ## ## ``timeout`` is specified in miliseconds and ``-1`` can be specified for ## an unlimited time. - var tv {.noInit.}: Ttimeval = timeValFromMilliseconds(timeout) + var tv {.noInit.}: Timeval = timeValFromMilliseconds(timeout) var wr: TFdSet var m = 0 @@ -419,5 +422,5 @@ proc selectWrite*(writefds: var seq[TSocketHandle], pruneSocketSet(writefds, (wr)) when defined(Windows): - var wsa: TWSADATA - if WSAStartup(0x0101'i16, addr wsa) != 0: osError(osLastError()) + var wsa: WSADATA + if WSAStartup(0x0101'i16, addr wsa) != 0: raiseOSError(osLastError()) diff --git a/lib/pure/redis.nim b/lib/pure/redis.nim index 959f5c6ef..ab3b81f37 100644 --- a/lib/pure/redis.nim +++ b/lib/pure/redis.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Dominik Picheta # # See the file "copying.txt", included in this @@ -20,36 +20,40 @@ const redisNil* = "\0\0" type - PPipeline = ref object + Pipeline = ref object enabled: bool buffer: string expected: int ## number of replies expected if pipelined type - TSendMode = enum + SendMode = enum normal, pipelined, multiple type - TRedis* {.pure, final.} = object + Redis* = object socket: TSocket connected: bool - pipeline: PPipeline + pipeline: Pipeline - TRedisStatus* = string - TRedisInteger* = biggestInt - TRedisString* = string ## Bulk reply - TRedisList* = seq[TRedisString] ## Multi-bulk reply + RedisStatus* = string + RedisInteger* = BiggestInt + RedisString* = string ## Bulk reply + RedisList* = seq[RedisString] ## Multi-bulk reply - EInvalidReply* = object of ESynch ## Invalid reply from redis - ERedis* = object of ESynch ## Error in redis + ReplyError* = object of IOError ## Invalid reply from redis + RedisError* = object of IOError ## Error in redis -proc newPipeline(): PPipeline = +{.deprecated: [TSendMode: SendMode, TRedis: Redis, TRedisStatus: RedisStatus, + TRedisInteger: RedisInteger, TRedisString: RedisString, + TRedisList: RedistList, EInvalidReply: ReplyError, ERedis: RedisError].} + +proc newPipeline(): Pipeline = new(result) result.buffer = "" result.enabled = false result.expected = 0 -proc open*(host = "localhost", port = 6379.TPort): TRedis = +proc open*(host = "localhost", port = 6379.Port): Redis = ## Opens a connection to the redis server. result.socket = socket(buffered = false) if result.socket == InvalidSocket: @@ -58,24 +62,24 @@ proc open*(host = "localhost", port = 6379.TPort): TRedis = result.pipeline = newPipeline() proc raiseInvalidReply(expected, got: char) = - raise newException(EInvalidReply, + raise newException(ReplyError, "Expected '$1' at the beginning of a status reply got '$2'" % [$expected, $got]) -proc raiseNoOK(status: string, pipelineEnabled:bool) = +proc raiseNoOK(status: string, pipelineEnabled: bool) = if pipelineEnabled and not (status == "QUEUED" or status == "PIPELINED"): raise newException(EInvalidReply, "Expected \"QUEUED\" or \"PIPELINED\" got \"$1\"" % status) elif not pipelineEnabled and status != "OK": raise newException(EInvalidReply, "Expected \"OK\" got \"$1\"" % status) -template readSocket(r: TRedis, dummyVal:expr): stmt = - var line {.inject.} :TaintedString = "" +template readSocket(r: Redis, dummyVal:expr): stmt = + var line {.inject.}: TaintedString = "" if r.pipeline.enabled: return dummyVal else: readLine(r.socket, line) -proc parseStatus(r: TRedis, line: string = ""): TRedisStatus = +proc parseStatus(r: Redis, line: string = ""): RedisStatus = if r.pipeline.enabled: return "PIPELINED" diff --git a/lib/pure/romans.nim b/lib/pure/romans.nim index dee3226d8..79fb75526 100644 --- a/lib/pure/romans.nim +++ b/lib/pure/romans.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2011 Philippe Lhoste # # See the file "copying.txt", included in this diff --git a/lib/pure/ropes.nim b/lib/pure/ropes.nim index eb3792bce..8205203ba 100644 --- a/lib/pure/ropes.nim +++ b/lib/pure/ropes.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2010 Andreas Rumpf # # See the file "copying.txt", included in this @@ -30,13 +30,15 @@ var cacheEnabled = false type - PRope* = ref TRope ## empty rope is represented by nil - TRope {.acyclic, final, pure.} = object - left, right: PRope + Rope* = ref RopeObj ## empty rope is represented by nil + RopeObj {.acyclic.} = object + left, right: Rope length: int data: string # != nil if a leaf -proc isConc(r: PRope): bool {.inline.} = return isNil(r.data) +{.deprecated: [PRope: Rope].} + +proc isConc(r: Rope): bool {.inline.} = return isNil(r.data) # Note that the left and right pointers are not needed for leafs. # Leaves have relatively high memory overhead (~30 bytes on a 32 @@ -46,25 +48,25 @@ proc isConc(r: PRope): bool {.inline.} = return isNil(r.data) # performance. But for the caching tree we use the leaf's left and right # pointers. -proc len*(a: PRope): int {.rtl, extern: "nro$1".} = +proc len*(a: Rope): int {.rtl, extern: "nro$1".} = ## the rope's length if a == nil: result = 0 else: result = a.length -proc newRope(): PRope = new(result) -proc newRope(data: string): PRope = +proc newRope(): Rope = new(result) +proc newRope(data: string): Rope = new(result) result.length = len(data) result.data = data var - cache {.threadvar.}: PRope # the root of the cache tree - N {.threadvar.}: PRope # dummy rope needed for splay algorithm + cache {.threadvar.}: Rope # the root of the cache tree + N {.threadvar.}: Rope # dummy rope needed for splay algorithm when countCacheMisses: var misses, hits: int -proc splay(s: string, tree: PRope, cmpres: var int): PRope = +proc splay(s: string, tree: Rope, cmpres: var int): Rope = var c: int var t = tree N.left = nil @@ -102,7 +104,7 @@ proc splay(s: string, tree: PRope, cmpres: var int): PRope = t.right = N.left result = t -proc insertInCache(s: string, tree: PRope): PRope = +proc insertInCache(s: string, tree: Rope): Rope = var t = tree if t == nil: result = newRope(s) @@ -128,7 +130,7 @@ proc insertInCache(s: string, tree: PRope): PRope = result.left = t t.right = nil -proc rope*(s: string): PRope {.rtl, extern: "nro$1Str".} = +proc rope*(s: string): Rope {.rtl, extern: "nro$1Str".} = ## Converts a string to a rope. if s.len == 0: result = nil @@ -138,11 +140,11 @@ proc rope*(s: string): PRope {.rtl, extern: "nro$1Str".} = else: result = newRope(s) -proc rope*(i: BiggestInt): PRope {.rtl, extern: "nro$1BiggestInt".} = +proc rope*(i: BiggestInt): Rope {.rtl, extern: "nro$1BiggestInt".} = ## Converts an int to a rope. result = rope($i) -proc rope*(f: BiggestFloat): PRope {.rtl, extern: "nro$1BiggestFloat".} = +proc rope*(f: BiggestFloat): Rope {.rtl, extern: "nro$1BiggestFloat".} = ## Converts a float to a rope. result = rope($f) @@ -156,7 +158,7 @@ proc disableCache*() {.rtl, extern: "nro$1".} = cache = nil cacheEnabled = false -proc `&`*(a, b: PRope): PRope {.rtl, extern: "nroConcRopeRope".} = +proc `&`*(a, b: Rope): Rope {.rtl, extern: "nroConcRopeRope".} = ## the concatenation operator for ropes. if a == nil: result = b @@ -176,27 +178,27 @@ proc `&`*(a, b: PRope): PRope {.rtl, extern: "nroConcRopeRope".} = result.left = a result.right = b -proc `&`*(a: PRope, b: string): PRope {.rtl, extern: "nroConcRopeStr".} = +proc `&`*(a: Rope, b: string): Rope {.rtl, extern: "nroConcRopeStr".} = ## the concatenation operator for ropes. result = a & rope(b) -proc `&`*(a: string, b: PRope): PRope {.rtl, extern: "nroConcStrRope".} = +proc `&`*(a: string, b: Rope): Rope {.rtl, extern: "nroConcStrRope".} = ## the concatenation operator for ropes. result = rope(a) & b -proc `&`*(a: openarray[PRope]): PRope {.rtl, extern: "nroConcOpenArray".} = +proc `&`*(a: openarray[Rope]): Rope {.rtl, extern: "nroConcOpenArray".} = ## the concatenation operator for an openarray of ropes. for i in countup(0, high(a)): result = result & a[i] -proc add*(a: var PRope, b: PRope) {.rtl, extern: "nro$1Rope".} = +proc add*(a: var Rope, b: Rope) {.rtl, extern: "nro$1Rope".} = ## adds `b` to the rope `a`. a = a & b -proc add*(a: var PRope, b: string) {.rtl, extern: "nro$1Str".} = +proc add*(a: var Rope, b: string) {.rtl, extern: "nro$1Str".} = ## adds `b` to the rope `a`. a = a & b -proc `[]`*(r: PRope, i: int): char {.rtl, extern: "nroCharAt".} = +proc `[]`*(r: Rope, i: int): char {.rtl, extern: "nroCharAt".} = ## returns the character at position `i` in the rope `r`. This is quite ## expensive! Worst-case: O(n). If ``i >= r.len``, ``\0`` is returned. var x = r @@ -213,7 +215,7 @@ proc `[]`*(r: PRope, i: int): char {.rtl, extern: "nroCharAt".} = x = x.right dec(j, x.len) -iterator leaves*(r: PRope): string = +iterator leaves*(r: Rope): string = ## iterates over any leaf string in the rope `r`. if r != nil: var stack = @[r] @@ -226,16 +228,16 @@ iterator leaves*(r: PRope): string = assert(it.data != nil) yield it.data -iterator items*(r: PRope): char = +iterator items*(r: Rope): char = ## iterates over any character in the rope `r`. for s in leaves(r): for c in items(s): yield c -proc write*(f: TFile, r: PRope) {.rtl, extern: "nro$1".} = +proc write*(f: TFile, r: Rope) {.rtl, extern: "nro$1".} = ## writes a rope to a file. for s in leaves(r): write(f, s) -proc `$`*(r: PRope): string {.rtl, extern: "nroToString".}= +proc `$`*(r: Rope): string {.rtl, extern: "nroToString".}= ## converts a rope back to a string. result = newString(r.len) setLen(result, 0) @@ -245,11 +247,11 @@ when false: # Format string caching seems reasonable: All leaves can be shared and format # string parsing has to be done only once. A compiled format string is stored # as a rope. A negative length is used for the index into the args array. - proc compiledArg(idx: int): PRope = + proc compiledArg(idx: int): Rope = new(result) result.length = -idx - proc compileFrmt(frmt: string): PRope = + proc compileFrmt(frmt: string): Rope = var i = 0 var length = len(frmt) result = nil @@ -289,7 +291,7 @@ when false: if i - 1 >= start: add(result, substr(frmt, start, i-1)) -proc `%`*(frmt: string, args: openarray[PRope]): PRope {. +proc `%`*(frmt: string, args: openarray[Rope]): Rope {. rtl, extern: "nroFormat".} = ## `%` substitution operator for ropes. Does not support the ``$identifier`` ## nor ``${identifier}`` notations. @@ -332,12 +334,12 @@ proc `%`*(frmt: string, args: openarray[PRope]): PRope {. if i - 1 >= start: add(result, substr(frmt, start, i - 1)) -proc addf*(c: var PRope, frmt: string, args: openarray[PRope]) {. +proc addf*(c: var Rope, frmt: string, args: openarray[Rope]) {. rtl, extern: "nro$1".} = ## shortcut for ``add(c, frmt % args)``. add(c, frmt % args) -proc equalsFile*(r: PRope, f: TFile): bool {.rtl, extern: "nro$1File".} = +proc equalsFile*(r: Rope, f: TFile): bool {.rtl, extern: "nro$1File".} = ## returns true if the contents of the file `f` equal `r`. var bufSize = 1024 # reasonable start value var buf = alloc(BufSize) @@ -352,7 +354,7 @@ proc equalsFile*(r: PRope, f: TFile): bool {.rtl, extern: "nro$1File".} = result = readBuffer(f, buf, 1) == 0 # really at the end of file? dealloc(buf) -proc equalsFile*(r: PRope, f: string): bool {.rtl, extern: "nro$1Str".} = +proc equalsFile*(r: Rope, f: string): bool {.rtl, extern: "nro$1Str".} = ## returns true if the contents of the file `f` equal `r`. If `f` does not ## exist, false is returned. var bin: TFile diff --git a/lib/pure/scgi.nim b/lib/pure/scgi.nim index 45f837833..fa8605a69 100644 --- a/lib/pure/scgi.nim +++ b/lib/pure/scgi.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2013 Andreas Rumpf, Dominik Picheta # # See the file "copying.txt", included in this @@ -9,13 +9,13 @@ ## This module implements helper procs for SCGI applications. Example: ## -## .. code-block:: Nimrod +## .. code-block:: Nim ## ## import strtabs, sockets, scgi ## ## var counter = 0 -## proc handleRequest(client: TSocket, input: string, -## headers: PStringTable): bool {.procvar.} = +## proc handleRequest(client: Socket, input: string, +## headers: StringTableRef): bool {.procvar.} = ## inc(counter) ## client.writeStatusOkTextContent() ## client.send("Hello for the $#th time." % $counter & "\c\L") @@ -31,11 +31,11 @@ include "system/inclrtl" import sockets, strutils, os, strtabs, asyncio type - EScgi* = object of EIO ## the exception that is raised, if a SCGI error occurs + ScgiError* = object of IOError ## the exception that is raised, if a SCGI error occurs -proc scgiError*(msg: string) {.noreturn.} = - ## raises an EScgi exception with message `msg`. - var e: ref EScgi +proc raiseScgiError*(msg: string) {.noreturn.} = + ## raises an ScgiError exception with message `msg`. + var e: ref ScgiError new(e) e.msg = msg raise e @@ -45,7 +45,7 @@ proc parseWord(inp: string, outp: var string, start: int): int = while inp[result] != '\0': inc(result) outp = substr(inp, start, result-1) -proc parseHeaders(s: string, L: int): PStringTable = +proc parseHeaders(s: string, L: int): StringTableRef = result = newStringTable() var i = 0 while i < L: @@ -54,73 +54,77 @@ proc parseHeaders(s: string, L: int): PStringTable = i = parseWord(s, val, i)+1 result[key] = val if s[i] == ',': inc(i) - else: scgiError("',' after netstring expected") + else: raiseScgiError("',' after netstring expected") -proc recvChar(s: TSocket): char = +proc recvChar(s: Socket): char = var c: char if recv(s, addr(c), sizeof(c)) == sizeof(c): result = c type - TScgiState* = object of TObject ## SCGI state object - server: TSocket + ScgiState* = object of RootObj ## SCGI state object + server: Socket bufLen: int - client*: TSocket ## the client socket to send data to - headers*: PStringTable ## the parsed headers + client*: Socket ## the client socket to send data to + headers*: StringTableRef ## the parsed headers input*: string ## the input buffer # Async - TClientMode = enum + ClientMode = enum ClientReadChar, ClientReadHeaders, ClientReadContent - PAsyncClient = ref object - c: PAsyncSocket - mode: TClientMode + AsyncClient = ref object + c: AsyncSocket + mode: ClientMode dataLen: int headers: PStringTable ## the parsed headers input: string ## the input buffer - TAsyncScgiState = object - handleRequest: proc (client: PAsyncSocket, - input: string, headers: PStringTable) {.closure,gcsafe.} - asyncServer: PAsyncSocket - disp: PDispatcher - PAsyncScgiState* = ref TAsyncScgiState - -proc recvBuffer(s: var TScgiState, L: int) = + AsyncScgiStateObj = object + handleRequest: proc (client: AsyncSocket, + input: string, + headers: StringTableRef) {.closure, gcsafe.} + asyncServer: AsyncSocket + disp: Dispatcher + AsyncScgiState* = ref AsyncScgiStateObj + +{.deprected: [EScgi: ScgiError, TScgiState: ScgiState, + PAsyncScgiState: AsyncScgiState, scgiError: raiseScgiError].} + +proc recvBuffer(s: var ScgiState, L: int) = if L > s.bufLen: s.bufLen = L s.input = newString(L) if L > 0 and recv(s.client, cstring(s.input), L) != L: - scgiError("could not read all data") + raiseScgiError("could not read all data") setLen(s.input, L) -proc open*(s: var TScgiState, port = TPort(4000), address = "127.0.0.1", - reuseAddr = False) = +proc open*(s: var ScgiState, port = Port(4000), address = "127.0.0.1", + reuseAddr = false) = ## opens a connection. s.bufLen = 4000 s.input = newString(s.buflen) # will be reused s.server = socket() - if s.server == InvalidSocket: osError(osLastError()) + if s.server == InvalidSocket: raiseOSError(osLastError()) new(s.client) # Initialise s.client for `next` - if s.server == InvalidSocket: scgiError("could not open socket") + if s.server == InvalidSocket: raiseScgiError("could not open socket") #s.server.connect(connectionName, port) if reuseAddr: s.server.setSockOpt(OptReuseAddr, True) bindAddr(s.server, port, address) listen(s.server) -proc close*(s: var TScgiState) = +proc close*(s: var ScgiState) = ## closes the connection. s.server.close() -proc next*(s: var TScgistate, timeout: int = -1): bool = +proc next*(s: var ScgiState, timeout: int = -1): bool = ## proceed to the first/next request. Waits ``timeout`` miliseconds for a ## request, if ``timeout`` is `-1` then this function will never time out. - ## Returns `True` if a new request has been processed. + ## Returns `true` if a new request has been processed. var rsocks = @[s.server] if select(rsocks, timeout) == 1 and rsocks.len == 1: new(s.client) @@ -132,17 +136,17 @@ proc next*(s: var TScgistate, timeout: int = -1): bool = s.client.close() return false if d notin strutils.digits: - if d != ':': scgiError("':' after length expected") + if d != ':': raiseScgiError("':' after length expected") break L = L * 10 + ord(d) - ord('0') recvBuffer(s, L+1) s.headers = parseHeaders(s.input, L) - if s.headers["SCGI"] != "1": scgiError("SCGI Version 1 expected") + if s.headers["SCGI"] != "1": raiseScgiError("SCGI Version 1 expected") L = parseInt(s.headers["CONTENT_LENGTH"]) recvBuffer(s, L) return True -proc writeStatusOkTextContent*(c: TSocket, contentType = "text/html") = +proc writeStatusOkTextContent*(c: Socket, contentType = "text/html") = ## sends the following string to the socket `c`:: ## ## Status: 200 OK\r\LContent-Type: text/html\r\L\r\L @@ -151,11 +155,11 @@ proc writeStatusOkTextContent*(c: TSocket, contentType = "text/html") = c.send("Status: 200 OK\r\L" & "Content-Type: $1\r\L\r\L" % contentType) -proc run*(handleRequest: proc (client: TSocket, input: string, - headers: PStringTable): bool {.nimcall,gcsafe.}, - port = TPort(4000)) = +proc run*(handleRequest: proc (client: Socket, input: string, + headers: StringTableRef): bool {.nimcall,gcsafe.}, + port = Port(4000)) = ## encapsulates the SCGI object and main loop. - var s: TScgiState + var s: ScgiState s.open(port) var stop = false while not stop: @@ -166,11 +170,11 @@ proc run*(handleRequest: proc (client: TSocket, input: string, # -- AsyncIO start -proc recvBufferAsync(client: PAsyncClient, L: int): TReadLineResult = +proc recvBufferAsync(client: AsyncClient, L: int): ReadLineResult = result = ReadPartialLine var data = "" if L < 1: - scgiError("Cannot read negative or zero length: " & $L) + raiseScgiError("Cannot read negative or zero length: " & $L) let ret = recvAsync(client.c, data, L) if ret == 0 and data == "": client.c.close() @@ -181,16 +185,16 @@ proc recvBufferAsync(client: PAsyncClient, L: int): TReadLineResult = if ret == L: return ReadFullLine -proc checkCloseSocket(client: PAsyncClient) = +proc checkCloseSocket(client: AsyncClient) = if not client.c.isClosed: if client.c.isSendDataBuffered: - client.c.setHandleWrite do (s: PAsyncSocket): + client.c.setHandleWrite do (s: AsyncSocket): if not s.isClosed and not s.isSendDataBuffered: s.close() s.delHandleWrite() else: client.c.close() -proc handleClientRead(client: PAsyncClient, s: PAsyncScgiState) = +proc handleClientRead(client: AsyncClient, s: AsyncScgiState) = case client.mode of ClientReadChar: while true: @@ -203,7 +207,7 @@ proc handleClientRead(client: PAsyncClient, s: PAsyncScgiState) = if ret == -1: return # No more data available if d[0] notin strutils.digits: - if d[0] != ':': scgiError("':' after length expected") + if d[0] != ':': raiseScgiError("':' after length expected") break client.dataLen = client.dataLen * 10 + ord(d[0]) - ord('0') client.mode = ClientReadHeaders @@ -213,7 +217,7 @@ proc handleClientRead(client: PAsyncClient, s: PAsyncScgiState) = case ret of ReadFullLine: client.headers = parseHeaders(client.input, client.input.len-1) - if client.headers["SCGI"] != "1": scgiError("SCGI Version 1 expected") + if client.headers["SCGI"] != "1": raiseScgiError("SCGI Version 1 expected") client.input = "" # For next part let contentLen = parseInt(client.headers["CONTENT_LENGTH"]) @@ -236,50 +240,50 @@ proc handleClientRead(client: PAsyncClient, s: PAsyncScgiState) = s.handleRequest(client.c, client.input, client.headers) checkCloseSocket(client) -proc handleAccept(sock: PAsyncSocket, s: PAsyncScgiState) = - var client: PAsyncSocket +proc handleAccept(sock: AsyncSocket, s: AsyncScgiState) = + var client: AsyncSocket new(client) accept(s.asyncServer, client) - var asyncClient = PAsyncClient(c: client, mode: ClientReadChar, dataLen: 0, + var asyncClient = AsyncClient(c: client, mode: ClientReadChar, dataLen: 0, headers: newStringTable(), input: "") client.handleRead = - proc (sock: PAsyncSocket) = + proc (sock: AsyncSocket) = handleClientRead(asyncClient, s) s.disp.register(client) -proc open*(handleRequest: proc (client: PAsyncSocket, - input: string, headers: PStringTable) {. +proc open*(handleRequest: proc (client: AsyncSocket, + input: string, headers: StringTableRef) {. closure, gcsafe.}, - port = TPort(4000), address = "127.0.0.1", - reuseAddr = false): PAsyncScgiState = - ## Creates an ``PAsyncScgiState`` object which serves as a SCGI server. + port = Port(4000), address = "127.0.0.1", + reuseAddr = false): AsyncScgiState = + ## Creates an ``AsyncScgiState`` object which serves as a SCGI server. ## ## After the execution of ``handleRequest`` the client socket will be closed ## automatically unless it has already been closed. - var cres: PAsyncScgiState + var cres: AsyncScgiState new(cres) cres.asyncServer = AsyncSocket() - cres.asyncServer.handleAccept = proc (s: PAsyncSocket) = handleAccept(s, cres) + cres.asyncServer.handleAccept = proc (s: AsyncSocket) = handleAccept(s, cres) if reuseAddr: - cres.asyncServer.setSockOpt(OptReuseAddr, True) + cres.asyncServer.setSockOpt(OptReuseAddr, true) bindAddr(cres.asyncServer, port, address) listen(cres.asyncServer) cres.handleRequest = handleRequest result = cres -proc register*(d: PDispatcher, s: PAsyncScgiState): PDelegate {.discardable.} = +proc register*(d: Dispatcher, s: AsyncScgiState): Delegate {.discardable.} = ## Registers ``s`` with dispatcher ``d``. result = d.register(s.asyncServer) s.disp = d -proc close*(s: PAsyncScgiState) = - ## Closes the ``PAsyncScgiState``. +proc close*(s: AsyncScgiState) = + ## Closes the ``AsyncScgiState``. s.asyncServer.close() when false: var counter = 0 - proc handleRequest(client: TSocket, input: string, - headers: PStringTable): bool {.procvar.} = + proc handleRequest(client: Socket, input: string, + headers: StringTableRef): bool {.procvar.} = inc(counter) client.writeStatusOkTextContent() client.send("Hello for the $#th time." % $counter & "\c\L") diff --git a/lib/pure/selectors.nim b/lib/pure/selectors.nim index bd53c2dbf..33939537a 100644 --- a/lib/pure/selectors.nim +++ b/lib/pure/selectors.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2014 Dominik Picheta # # See the file "copying.txt", included in this @@ -18,57 +18,57 @@ elif defined(windows): else: import posix -proc hash*(x: TSocketHandle): THash {.borrow.} -proc `$`*(x: TSocketHandle): string {.borrow.} +proc hash*(x: SocketHandle): THash {.borrow.} +proc `$`*(x: SocketHandle): string {.borrow.} type - TEvent* = enum + Event* = enum EvRead, EvWrite - PSelectorKey* = ref object - fd*: TSocketHandle - events*: set[TEvent] ## The events which ``fd`` listens for. - data*: PObject ## User object. + SelectorKey* = ref object + fd*: SocketHandle + events*: set[Event] ## The events which ``fd`` listens for. + data*: RootRef ## User object. - TReadyInfo* = tuple[key: PSelectorKey, events: set[TEvent]] + ReadyInfo* = tuple[key: SelectorKey, events: set[Event]] when defined(nimdoc): type - PSelector* = ref object + Selector* = ref object ## An object which holds file descripters to be checked for read/write ## status. - fds: TTable[TSocketHandle, PSelectorKey] + fds: Table[SocketHandle, SelectorKey] - proc register*(s: PSelector, fd: TSocketHandle, events: set[TEvent], - data: PObject): PSelectorKey {.discardable.} = + proc register*(s: Selector, fd: SocketHandle, events: set[Event], + data: RootRef): SelectorKey {.discardable.} = ## Registers file descriptor ``fd`` to selector ``s`` with a set of TEvent ## ``events``. - proc update*(s: PSelector, fd: TSocketHandle, - events: set[TEvent]): PSelectorKey {.discardable.} = + proc update*(s: Selector, fd: SocketHandle, + events: set[Event]): SelectorKey {.discardable.} = ## Updates the events which ``fd`` wants notifications for. - proc select*(s: PSelector, timeout: int): seq[TReadyInfo] = + proc select*(s: Selector, timeout: int): seq[ReadyInfo] = ## The ``events`` field of the returned ``key`` contains the original events ## for which the ``fd`` was bound. This is contrary to the ``events`` field ## of the ``TReadyInfo`` tuple which determines which events are ready ## on the ``fd``. - proc contains*(s: PSelector, fd: TSocketHandle): bool = + proc contains*(s: Selector, fd: SocketHandle): bool = ## Determines whether selector contains a file descriptor. - proc `[]`*(s: PSelector, fd: TSocketHandle): PSelectorKey = + proc `[]`*(s: Selector, fd: SocketHandle): SelectorKey = ## Retrieves the selector key for ``fd``. elif defined(linux): type - PSelector* = ref object + Selector* = ref object epollFD: cint events: array[64, epoll_event] - fds: TTable[TSocketHandle, PSelectorKey] + fds: Table[SocketHandle, SelectorKey] - proc createEventStruct(events: set[TEvent], fd: TSocketHandle): epoll_event = + proc createEventStruct(events: set[Event], fd: SocketHandle): epoll_event = if EvRead in events: result.events = EPOLLIN if EvWrite in events: @@ -76,22 +76,22 @@ elif defined(linux): result.events = result.events or EPOLLRDHUP result.data.fd = fd.cint - proc register*(s: PSelector, fd: TSocketHandle, events: set[TEvent], - data: PObject): PSelectorKey {.discardable.} = + proc register*(s: Selector, fd: SocketHandle, events: set[Event], + data: RootRef): SelectorKey {.discardable.} = ## Registers file descriptor ``fd`` to selector ``s`` with a set of TEvent ## ``events``. var event = createEventStruct(events, fd) if events != {}: if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fd, addr(event)) != 0: - OSError(OSLastError()) + raiseOSError(osLastError()) - var key = PSelectorKey(fd: fd, events: events, data: data) + var key = SelectorKey(fd: fd, events: events, data: data) s.fds[fd] = key result = key - proc update*(s: PSelector, fd: TSocketHandle, - events: set[TEvent]): PSelectorKey {.discardable.} = + proc update*(s: Selector, fd: SocketHandle, + events: set[Event]): SelectorKey {.discardable.} = ## Updates the events which ``fd`` wants notifications for. if s.fds[fd].events != events: if events == {}: @@ -101,7 +101,7 @@ elif defined(linux): # because its got fds which are waiting for no events and # are therefore constantly ready. (leading to 100% CPU usage). if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fd, nil) != 0: - OSError(OSLastError()) + raiseOSError(osLastError()) s.fds[fd].events = events else: var event = createEventStruct(events, fd) @@ -109,36 +109,36 @@ elif defined(linux): # This fd is idle. It's not a member of this epoll instance and must # be re-registered. if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fd, addr(event)) != 0: - OSError(OSLastError()) + raiseOSError(osLastError()) else: if epoll_ctl(s.epollFD, EPOLL_CTL_MOD, fd, addr(event)) != 0: - OSError(OSLastError()) + raiseOSError(osLastError()) s.fds[fd].events = events result = s.fds[fd] - proc unregister*(s: PSelector, fd: TSocketHandle): PSelectorKey {.discardable.} = + proc unregister*(s: Selector, fd: SocketHandle): SelectorKey {.discardable.} = if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fd, nil) != 0: - let err = OSLastError() + let err = osLastError() if err.cint notin {ENOENT, EBADF}: # TODO: Why do we sometimes get an EBADF? Is this normal? - OSError(err) + raiseOSError(err) result = s.fds[fd] s.fds.del(fd) - proc close*(s: PSelector) = - if s.epollFD.close() != 0: OSError(OSLastError()) + proc close*(s: Selector) = + if s.epollFD.close() != 0: raiseOSError(osLastError()) dealloc(addr s.events) # TODO: Test this - proc epollHasFd(s: PSelector, fd: TSocketHandle): bool = + proc epollHasFd(s: Selector, fd: SocketHandle): bool = result = true var event = createEventStruct(s.fds[fd].events, fd) if epoll_ctl(s.epollFD, EPOLL_CTL_MOD, fd, addr(event)) != 0: let err = osLastError() if err.cint in {ENOENT, EBADF}: return false - OSError(OSLastError()) + raiseOSError(osLastError()) - proc select*(s: PSelector, timeout: int): seq[TReadyInfo] = + proc select*(s: Selector, timeout: int): seq[ReadyInfo] = ## ## The ``events`` field of the returned ``key`` contains the original events ## for which the ``fd`` was bound. This is contrary to the ``events`` field @@ -146,12 +146,12 @@ elif defined(linux): ## on the ``fd``. result = @[] let evNum = epoll_wait(s.epollFD, addr s.events[0], 64.cint, timeout.cint) - if evNum < 0: OSError(OSLastError()) + if evNum < 0: raiseOSError(osLastError()) if evNum == 0: return @[] for i in 0 .. <evNum: - let fd = s.events[i].data.fd.TSocketHandle + let fd = s.events[i].data.fd.SocketHandle - var evSet: set[TEvent] = {} + var evSet: set[Event] = {} if (s.events[i].events and EPOLLIN) != 0: evSet = evSet + {EvRead} if (s.events[i].events and EPOLLOUT) != 0: evSet = evSet + {EvWrite} let selectorKey = s.fds[fd] @@ -160,15 +160,15 @@ elif defined(linux): #echo("Epoll: ", result[i].key.fd, " ", result[i].events, " ", result[i].key.events) - proc newSelector*(): PSelector = + proc newSelector*(): Selector = new result result.epollFD = epoll_create(64) #result.events = cast[array[64, epoll_event]](alloc0(sizeof(epoll_event)*64)) - result.fds = initTable[TSocketHandle, PSelectorKey]() + result.fds = initTable[SocketHandle, SelectorKey]() if result.epollFD < 0: - OSError(OSLastError()) + raiseOSError(osLastError()) - proc contains*(s: PSelector, fd: TSocketHandle): bool = + proc contains*(s: Selector, fd: SocketHandle): bool = ## Determines whether selector contains a file descriptor. if s.fds.hasKey(fd): # Ensure the underlying epoll instance still contains this fd. @@ -179,46 +179,46 @@ elif defined(linux): else: return false - proc `[]`*(s: PSelector, fd: TSocketHandle): PSelectorKey = + proc `[]`*(s: Selector, fd: SocketHandle): SelectorKey = ## Retrieves the selector key for ``fd``. return s.fds[fd] elif not defined(nimdoc): # TODO: kqueue for bsd/mac os x. type - PSelector* = ref object - fds: TTable[TSocketHandle, PSelectorKey] + Selector* = ref object + fds: Table[SocketHandle, SelectorKey] - proc register*(s: PSelector, fd: TSocketHandle, events: set[TEvent], - data: PObject): PSelectorKey {.discardable.} = + proc register*(s: Selector, fd: SocketHandle, events: set[Event], + data: RootRef): SelectorKey {.discardable.} = if s.fds.hasKey(fd): - raise newException(EInvalidValue, "File descriptor already exists.") - var sk = PSelectorKey(fd: fd, events: events, data: data) + raise newException(ValueError, "File descriptor already exists.") + var sk = SelectorKey(fd: fd, events: events, data: data) s.fds[fd] = sk result = sk - proc update*(s: PSelector, fd: TSocketHandle, - events: set[TEvent]): PSelectorKey {.discardable.} = + proc update*(s: Selector, fd: SocketHandle, + events: set[Event]): SelectorKey {.discardable.} = ## Updates the events which ``fd`` wants notifications for. if not s.fds.hasKey(fd): - raise newException(EInvalidValue, "File descriptor not found.") + raise newException(ValueError, "File descriptor not found.") s.fds[fd].events = events result = s.fds[fd] - proc unregister*(s: PSelector, fd: TSocketHandle): PSelectorKey {.discardable.} = + proc unregister*(s: Selector, fd: SocketHandle): SelectorKey {.discardable.} = result = s.fds[fd] s.fds.del(fd) - proc close*(s: PSelector) = nil + proc close*(s: Selector) = discard - proc timeValFromMilliseconds(timeout: int): TTimeVal = + proc timeValFromMilliseconds(timeout: int): TimeVal = if timeout != -1: var seconds = timeout div 1000 result.tv_sec = seconds.int32 result.tv_usec = ((timeout - seconds * 1000) * 1000).int32 - proc createFdSet(rd, wr: var TFdSet, fds: TTable[TSocketHandle, PSelectorKey], + proc createFdSet(rd, wr: var FdSet, fds: Table[SocketHandle, SelectorKey], m: var int) = FD_ZERO(rd); FD_ZERO(wr) for k, v in pairs(fds): @@ -229,22 +229,22 @@ elif not defined(nimdoc): m = max(m, int(k)) FD_SET(k, wr) - proc getReadyFDs(rd, wr: var TFdSet, fds: TTable[TSocketHandle, PSelectorKey]): - seq[TReadyInfo] = + proc getReadyFDs(rd, wr: var FdSet, fds: Table[SocketHandle, SelectorKey]): + seq[ReadyInfo] = result = @[] for k, v in pairs(fds): - var events: set[TEvent] = {} + var events: set[Event] = {} if FD_ISSET(k, rd) != 0'i32: events = events + {EvRead} if FD_ISSET(k, wr) != 0'i32: events = events + {EvWrite} result.add((v, events)) - proc select(fds: TTable[TSocketHandle, PSelectorKey], timeout = 500): - seq[TReadyInfo] = - var tv {.noInit.}: TTimeVal = timeValFromMilliseconds(timeout) + proc select(fds: Table[SocketHandle, SelectorKey], timeout = 500): + seq[ReadyInfo] = + var tv {.noInit.}: TimeVal = timeValFromMilliseconds(timeout) - var rd, wr: TFdSet + var rd, wr: FdSet var m = 0 createFdSet(rd, wr, fds, m) @@ -255,26 +255,26 @@ elif not defined(nimdoc): retCode = int(select(cint(m+1), addr(rd), addr(wr), nil, nil)) if retCode < 0: - OSError(OSLastError()) + raiseOSError(osLastError()) elif retCode == 0: return @[] else: return getReadyFDs(rd, wr, fds) - proc select*(s: PSelector, timeout: int): seq[TReadyInfo] = + proc select*(s: Selector, timeout: int): seq[ReadyInfo] = result = select(s.fds, timeout) - proc newSelector*(): PSelector = + proc newSelector*(): Selector = new result - result.fds = initTable[TSocketHandle, PSelectorKey]() + result.fds = initTable[SocketHandle, SelectorKey]() - proc contains*(s: PSelector, fd: TSocketHandle): bool = + proc contains*(s: Selector, fd: SocketHandle): bool = return s.fds.hasKey(fd) - proc `[]`*(s: PSelector, fd: TSocketHandle): PSelectorKey = + proc `[]`*(s: Selector, fd: SocketHandle): SelectorKey = return s.fds[fd] -proc contains*(s: PSelector, key: PSelectorKey): bool = +proc contains*(s: Selector, key: SelectorKey): bool = ## Determines whether selector contains this selector key. More accurate ## than checking if the file descriptor is in the selector because it ## ensures that the keys are equal. File descriptors may not always be @@ -282,20 +282,24 @@ proc contains*(s: PSelector, key: PSelectorKey): bool = ## the new one may have the same value. return key.fd in s and s.fds[key.fd] == key +{.deprecated: [TEvent: Event, PSelectorKey: SelectorKey, + TReadyInfo: ReadyInfo, PSelector: Selector].} + + when isMainModule and not defined(nimdoc): # Select() import sockets type - PSockWrapper = ref object of PObject - sock: TSocket + SockWrapper = ref object of RootObj + sock: Socket var sock = socket() - if sock == sockets.InvalidSocket: osError(osLastError()) + if sock == sockets.InvalidSocket: raiseOSError(osLastError()) #sock.setBlocking(false) - sock.connect("irc.freenode.net", TPort(6667)) + sock.connect("irc.freenode.net", Port(6667)) var selector = newSelector() - var data = PSockWrapper(sock: sock) + var data = SockWrapper(sock: sock) let key = selector.register(sock.getFD, {EvWrite}, data) var i = 0 while true: diff --git a/lib/pure/smtp.nim b/lib/pure/smtp.nim index 88afeb589..83eb60807 100644 --- a/lib/pure/smtp.nim +++ b/lib/pure/smtp.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Dominik Picheta # # See the file "copying.txt", included in this @@ -16,11 +16,11 @@ ## Example gmail use: ## ## -## .. code-block:: Nimrod -## var msg = createMessage("Hello from Nimrod's SMTP", +## .. code-block:: Nim +## var msg = createMessage("Hello from Nim's SMTP", ## "Hello!.\n Is this awesome or what?", ## @["foo@gmail.com"]) -## var smtp = connect("smtp.gmail.com", 465, True, True) +## var smtp = connect("smtp.gmail.com", 465, true, true) ## smtp.auth("username", "password") ## smtp.sendmail("username@gmail.com", @["foo@gmail.com"], $msg) ## @@ -31,18 +31,20 @@ import sockets, strutils, strtabs, base64, os type - TSMTP* {.final.} = object - sock: TSocket - debug: Bool + Smtp* = object + sock: Socket + debug: bool - TMessage* {.final.} = object + Message* = object msgTo: seq[string] msgCc: seq[string] msgSubject: string - msgOtherHeaders: PStringTable + msgOtherHeaders: StringTableRef msgBody: string - EInvalidReply* = object of EIO + ReplyError* = object of IOError + +{.deprecated: [EInvalidReply: ReplyError, TMessage: Message, TSMTP: Smtp].} proc debugSend(smtp: TSMTP, cmd: string) = if smtp.debug: @@ -170,7 +172,7 @@ when isMainModule: #smtp.sendmail("root@localhost", @["dominik@localhost"], $msg) #echo(decode("a17sm3701420wbe.12")) - var msg = createMessage("Hello from Nimrod's SMTP!", + var msg = createMessage("Hello from Nim's SMTP!", "Hello!!!!.\n Is this awesome or what?", @["someone@yahoo.com", "someone@gmail.com"]) echo(msg) diff --git a/lib/pure/sockets.nim b/lib/pure/sockets.nim index b0cc67c70..6c2ec72f1 100644 --- a/lib/pure/sockets.nim +++ b/lib/pure/sockets.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2013 Andreas Rumpf, Dominik Picheta # # See the file "copying.txt", included in this @@ -14,8 +14,8 @@ ## the ``socket`` function to `false`. Be aware that some functions may not yet ## support buffered sockets (mainly the recvFrom function). ## -## Most procedures raise EOS on error, but some may return ``-1`` or a boolean -## ``false``. +## Most procedures raise OSError on error, but some may return ``-1`` or a +## boolean ``false``. ## ## SSL is supported through the OpenSSL library. This support can be activated ## by compiling with the ``-d:ssl`` switch. When an SSL socket is used it will @@ -47,25 +47,29 @@ else: when defined(ssl): type - ESSL* = object of ESynch + SSLError* = object of Exception - TSSLCVerifyMode* = enum + SSLCVerifyMode* = enum CVerifyNone, CVerifyPeer - TSSLProtVersion* = enum + SSLProtVersion* = enum protSSLv2, protSSLv3, protTLSv1, protSSLv23 - PSSLContext* = distinct PSSLCTX + SSLContext* = distinct PSSLCTX - TSSLAcceptResult* = enum + SSLAcceptResult* = enum AcceptNoClient = 0, AcceptNoHandshake, AcceptSuccess + {.deprecated: [ESSL: SSLError, TSSLCVerifyMode: SSLCVerifyMode, + TSSLProtVersion: SSLProtVersion, PSSLContext: SSLContext, + TSSLAcceptResult: SSLAcceptResult].} + const BufferSize*: int = 4000 ## size of a buffered socket's buffer type TSocketImpl = object ## socket type - fd: TSocketHandle + fd: SocketHandle case isBuffered: bool # determines whether this socket is buffered. of true: buffer: array[0..BufferSize, char] @@ -76,31 +80,31 @@ type case isSsl: bool of true: sslHandle: PSSL - sslContext: PSSLContext + sslContext: SSLContext sslNoHandshake: bool # True if needs handshake. sslHasPeekChar: bool sslPeekChar: char of false: nil nonblocking: bool - TSocket* = ref TSocketImpl + Socket* = ref TSocketImpl - TPort* = distinct uint16 ## port type + Port* = distinct uint16 ## port type - TDomain* = enum ## domain, which specifies the protocol family of the + Domain* = enum ## domain, which specifies the protocol family of the ## created socket. Other domains than those that are listed ## here are unsupported. AF_UNIX, ## for local socket (using a file). Unsupported on Windows. AF_INET = 2, ## for network protocol IPv4 or AF_INET6 = 23 ## for network protocol IPv6. - TType* = enum ## second argument to `socket` proc + SockType* = enum ## second argument to `socket` proc SOCK_STREAM = 1, ## reliable stream-oriented service or Stream Sockets SOCK_DGRAM = 2, ## datagram service or Datagram Sockets SOCK_RAW = 3, ## raw protocols atop the network layer. SOCK_SEQPACKET = 5 ## reliable sequenced packet service - TProtocol* = enum ## third argument to `socket` proc + Protocol* = enum ## third argument to `socket` proc IPPROTO_TCP = 6, ## Transmission control protocol. IPPROTO_UDP = 17, ## User datagram protocol. IPPROTO_IP, ## Internet protocol. Unsupported on Windows. @@ -108,33 +112,39 @@ type IPPROTO_RAW, ## Raw IP Packets Protocol. Unsupported on Windows. IPPROTO_ICMP ## Control message protocol. Unsupported on Windows. - TServent* {.pure, final.} = object ## information about a service + Servent* = object ## information about a service name*: string aliases*: seq[string] - port*: TPort + port*: Port proto*: string - Thostent* {.pure, final.} = object ## information about a given host + Hostent* = object ## information about a given host name*: string aliases*: seq[string] - addrtype*: TDomain + addrtype*: Domain length*: int addrList*: seq[string] - TSOBool* = enum ## Boolean socket options. + SOBool* = enum ## Boolean socket options. OptAcceptConn, OptBroadcast, OptDebug, OptDontRoute, OptKeepAlive, OptOOBInline, OptReuseAddr - TRecvLineResult* = enum ## result for recvLineAsync + RecvLineResult* = enum ## result for recvLineAsync RecvFullLine, RecvPartialLine, RecvDisconnected, RecvFail - TReadLineResult* = enum ## result for readLineAsync + ReadLineResult* = enum ## result for readLineAsync ReadFullLine, ReadPartialLine, ReadDisconnected, ReadNone - ETimeout* = object of Exception + TimeoutError* = object of Exception + +{.deprecated: [TSocket: Socket, TType: SockType, TPort: Port, TDomain: Domain, + TProtocol: Protocol, TServent: Servent, THostent: Hostent, + TSOBool: SOBool, TRecvLineResult: RecvLineResult, + TReadLineResult: ReadLineResult, ETimeout: TimeoutError].} + let - invalidSocket*: TSocket = nil ## invalid socket + invalidSocket*: Socket = nil ## invalid socket when defined(windows): let @@ -143,7 +153,7 @@ else: let osInvalidSocket = posix.INVALID_SOCKET -proc newTSocket(fd: TSocketHandle, isBuff: bool): TSocket = +proc newTSocket(fd: SocketHandle, isBuff: bool): Socket = if fd == osInvalidSocket: return nil new(result) @@ -153,10 +163,10 @@ proc newTSocket(fd: TSocketHandle, isBuff: bool): TSocket = result.currPos = 0 result.nonblocking = false -proc `==`*(a, b: TPort): bool {.borrow.} +proc `==`*(a, b: Port): bool {.borrow.} ## ``==`` for ports. -proc `$`*(p: TPort): string {.borrow.} +proc `$`*(p: Port): string {.borrow.} ## returns the port number as a string proc ntohl*(x: int32): int32 = @@ -189,14 +199,14 @@ proc htons*(x: int16): int16 = result = sockets.ntohs(x) when defined(Posix): - proc toInt(domain: TDomain): cint = + proc toInt(domain: Domain): cint = case domain of AF_UNIX: result = posix.AF_UNIX of AF_INET: result = posix.AF_INET of AF_INET6: result = posix.AF_INET6 else: discard - proc toInt(typ: TType): cint = + proc toInt(typ: SockType): cint = case typ of SOCK_STREAM: result = posix.SOCK_STREAM of SOCK_DGRAM: result = posix.SOCK_DGRAM @@ -204,7 +214,7 @@ when defined(Posix): of SOCK_RAW: result = posix.SOCK_RAW else: discard - proc toInt(p: TProtocol): cint = + proc toInt(p: Protocol): cint = case p of IPPROTO_TCP: result = posix.IPPROTO_TCP of IPPROTO_UDP: result = posix.IPPROTO_UDP @@ -215,13 +225,13 @@ when defined(Posix): else: discard else: - proc toInt(domain: TDomain): cint = + proc toInt(domain: Domain): cint = result = toU16(ord(domain)) - proc toInt(typ: TType): cint = + proc toInt(typ: SockType): cint = result = cint(ord(typ)) - proc toInt(p: TProtocol): cint = + proc toInt(p: Protocol): cint = result = cint(ord(p)) proc socket*(domain: TDomain = AF_INET, typ: TType = SOCK_STREAM, @@ -336,7 +346,7 @@ when defined(ssl): if SSLSetFd(socket.sslHandle, socket.fd) != 1: SSLError() -proc socketError*(socket: TSocket, err: int = -1, async = false) = +proc raiseSocketError*(socket: TSocket, err: int = -1, async = false) = ## Raises proper errors based on return values of ``recv`` functions. ## ## If ``async`` is ``True`` no error will be thrown in the case when the @@ -370,18 +380,18 @@ proc socketError*(socket: TSocket, err: int = -1, async = false) = when defined(windows): if lastError.int32 == WSAEWOULDBLOCK: return - else: osError(lastError) + else: raiseOSError(lastError) else: if lastError.int32 == EAGAIN or lastError.int32 == EWOULDBLOCK: return - else: osError(lastError) - else: osError(lastError) + else: raiseOSError(lastError) + else: raiseOSError(lastError) proc listen*(socket: TSocket, backlog = SOMAXCONN) {.tags: [ReadIOEffect].} = ## Marks ``socket`` as accepting connections. ## ``Backlog`` specifies the maximum length of the ## queue of pending connections. - if listen(socket.fd, cint(backlog)) < 0'i32: osError(osLastError()) + if listen(socket.fd, cint(backlog)) < 0'i32: raiseOSError(osLastError()) proc invalidIp4(s: string) {.noreturn, noinline.} = raise newException(ValueError, "invalid ip4 address: " & s) @@ -420,7 +430,7 @@ template gaiNim(a, p, h, list: expr): stmt = var gaiResult = getaddrinfo(a, $p, addr(h), list) if gaiResult != 0'i32: when defined(windows): - osError(osLastError()) + raiseOSError(osLastError()) else: raise newException(OSError, $gai_strerror(gaiResult)) @@ -440,7 +450,7 @@ proc bindAddr*(socket: TSocket, port = TPort(0), address = "") {. name.sin_addr.s_addr = sockets.htonl(INADDR_ANY) if bindSocket(socket.fd, cast[ptr TSockAddr](addr(name)), sizeof(name).TSocklen) < 0'i32: - osError(osLastError()) + raiseOSError(osLastError()) else: var hints: Taddrinfo var aiList: ptr Taddrinfo = nil @@ -449,7 +459,7 @@ proc bindAddr*(socket: TSocket, port = TPort(0), address = "") {. hints.ai_protocol = toInt(IPPROTO_TCP) gaiNim(address, port, hints, aiList) if bindSocket(socket.fd, aiList.ai_addr, aiList.ai_addrlen.TSocklen) < 0'i32: - osError(osLastError()) + raiseOSError(osLastError()) proc getSockName*(socket: TSocket): TPort = ## returns the socket's associated port number. @@ -463,7 +473,7 @@ proc getSockName*(socket: TSocket): TPort = var namelen = sizeof(name).TSocklen if getsockname(socket.fd, cast[ptr TSockAddr](addr(name)), addr(namelen)) == -1'i32: - osError(osLastError()) + raiseOSError(osLastError()) result = TPort(sockets.ntohs(name.sin_port)) template acceptAddrPlain(noClientRet, successRet: expr, @@ -484,7 +494,7 @@ template acceptAddrPlain(noClientRet, successRet: expr, return else: return noClientRet - else: osError(err) + else: raiseOSError(err) else: if err.int32 == EAGAIN or err.int32 == EWOULDBLOCK: client = invalidSocket @@ -493,7 +503,7 @@ template acceptAddrPlain(noClientRet, successRet: expr, return else: return noClientRet - else: osError(err) + else: raiseOSError(err) else: client.fd = sock client.isBuffered = server.isBuffered @@ -680,7 +690,7 @@ proc getHostByAddr*(ip: string): Thostent {.tags: [ReadIOEffect].} = when defined(windows): var s = winlean.gethostbyaddr(addr(myaddr), sizeof(myaddr).cuint, cint(sockets.AF_INET)) - if s == nil: osError(osLastError()) + if s == nil: raiseOSError(osLastError()) else: var s = posix.gethostbyaddr(addr(myaddr), sizeof(myaddr).TSocklen, cint(posix.AF_INET)) @@ -707,7 +717,7 @@ proc getHostByName*(name: string): Thostent {.tags: [ReadIOEffect].} = var s = winlean.gethostbyname(name) else: var s = posix.gethostbyname(name) - if s == nil: osError(osLastError()) + if s == nil: raiseOSError(osLastError()) result.name = $s.h_name result.aliases = cstringArrayToSeq(s.h_aliases) when defined(windows): @@ -729,7 +739,7 @@ proc getSockOptInt*(socket: TSocket, level, optname: int): int {. var size = sizeof(res).TSocklen if getsockopt(socket.fd, cint(level), cint(optname), addr(res), addr(size)) < 0'i32: - osError(osLastError()) + raiseOSError(osLastError()) result = int(res) proc setSockOptInt*(socket: TSocket, level, optname, optval: int) {. @@ -738,7 +748,7 @@ proc setSockOptInt*(socket: TSocket, level, optname, optval: int) {. var value = cint(optval) if setsockopt(socket.fd, cint(level), cint(optname), addr(value), sizeof(value).TSocklen) < 0'i32: - osError(osLastError()) + raiseOSError(osLastError()) proc toCInt(opt: TSOBool): cint = case opt @@ -757,7 +767,7 @@ proc getSockOpt*(socket: TSocket, opt: TSOBool, level = SOL_SOCKET): bool {. var size = sizeof(res).TSocklen if getsockopt(socket.fd, cint(level), toCInt(opt), addr(res), addr(size)) < 0'i32: - osError(osLastError()) + raiseOSError(osLastError()) result = res != 0 proc setSockOpt*(socket: TSocket, opt: TSOBool, value: bool, level = SOL_SOCKET) {. @@ -766,7 +776,7 @@ proc setSockOpt*(socket: TSocket, opt: TSOBool, value: bool, level = SOL_SOCKET) var valuei = cint(if value: 1 else: 0) if setsockopt(socket.fd, cint(level), toCInt(opt), addr(valuei), sizeof(valuei).TSocklen) < 0'i32: - osError(osLastError()) + raiseOSError(osLastError()) proc connect*(socket: TSocket, address: string, port = TPort(0), af: TDomain = AF_INET) {.tags: [ReadIOEffect].} = @@ -784,7 +794,7 @@ proc connect*(socket: TSocket, address: string, port = TPort(0), gaiNim(address, port, hints, aiList) # try all possibilities: var success = false - var lastError: TOSErrorCode + var lastError: OSErrorCode var it = aiList while it != nil: if connect(socket.fd, it.ai_addr, it.ai_addrlen.TSocklen) == 0'i32: @@ -794,7 +804,7 @@ proc connect*(socket: TSocket, address: string, port = TPort(0), it = it.ai_next freeaddrinfo(aiList) - if not success: osError(lastError) + if not success: raiseOSError(lastError) when defined(ssl): if socket.isSSL: @@ -847,7 +857,7 @@ proc connectAsync*(socket: TSocket, name: string, port = TPort(0), gaiNim(name, port, hints, aiList) # try all possibilities: var success = false - var lastError: TOSErrorCode + var lastError: OSErrorCode var it = aiList while it != nil: var ret = connect(socket.fd, it.ai_addr, it.ai_addrlen.TSocklen) @@ -869,7 +879,7 @@ proc connectAsync*(socket: TSocket, name: string, port = TPort(0), it = it.ai_next freeaddrinfo(aiList) - if not success: osError(lastError) + if not success: raiseOSError(lastError) when defined(ssl): if socket.isSSL: socket.sslNoHandshake = true @@ -1133,7 +1143,7 @@ proc waitFor(socket: TSocket, waited: var float, timeout, size: int, result = min(result, size) else: if timeout - int(waited * 1000.0) < 1: - raise newException(ETimeout, "Call to '" & funcName & "' timed out.") + raise newException(TimeoutError, "Call to '" & funcName & "' timed out.") when defined(ssl): if socket.isSSL: @@ -1147,9 +1157,9 @@ proc waitFor(socket: TSocket, waited: var float, timeout, size: int, var s = @[socket] var startTime = epochTime() let selRet = select(s, timeout - int(waited * 1000.0)) - if selRet < 0: osError(osLastError()) + if selRet < 0: raiseOSError(osLastError()) if selRet != 1: - raise newException(ETimeout, "Call to '" & funcName & "' timed out.") + raise newException(TimeoutError, "Call to '" & funcName & "' timed out.") waited += (epochTime() - startTime) proc recv*(socket: TSocket, data: pointer, size: int, timeout: int): int {. @@ -1185,7 +1195,7 @@ proc recv*(socket: TSocket, data: var string, size: int, timeout = -1): int = result = recv(socket, cstring(data), size, timeout) if result < 0: data.setLen(0) - socket.socketError(result) + socket.raiseSocketError(result) data.setLen(result) proc recvAsync*(socket: TSocket, data: var string, size: int): int = @@ -1199,7 +1209,7 @@ proc recvAsync*(socket: TSocket, data: var string, size: int): int = result = recv(socket, cstring(data), size) if result < 0: data.setLen(0) - socket.socketError(async = true) + socket.raiseSocketError(async = true) result = -1 data.setLen(result) @@ -1296,14 +1306,14 @@ proc readLine*(socket: TSocket, line: var TaintedString, timeout = -1) {. var c: char discard waitFor(socket, waited, timeout, 1, "readLine") var n = recv(socket, addr(c), 1) - if n < 0: socket.socketError() + if n < 0: socket.raiseSocketError() elif n == 0: return if c == '\r': discard waitFor(socket, waited, timeout, 1, "readLine") n = peekChar(socket, c) if n > 0 and c == '\L': discard recv(socket, addr(c), 1) - elif n <= 0: socket.socketError() + elif n <= 0: socket.raiseSocketError() addNLIfEmpty() return elif c == '\L': @@ -1357,7 +1367,7 @@ proc readLineAsync*(socket: TSocket, setLen(line.string, 0) template errorOrNone = - socket.socketError(async = true) + socket.raiseSocketError(async = true) return ReadNone while true: @@ -1390,7 +1400,7 @@ proc recv*(socket: TSocket): TaintedString {.tags: [ReadIOEffect], deprecated.} var pos = 0 while true: var bytesRead = recv(socket, addr(string(result)[pos]), bufSize-1) - if bytesRead == -1: osError(osLastError()) + if bytesRead == -1: raiseOSError(osLastError()) setLen(result.string, pos + bytesRead) if bytesRead != bufSize-1: break # increase capacity: @@ -1463,11 +1473,11 @@ proc recvAsync*(socket: TSocket, s: var TaintedString): bool {. when defined(windows): if err.int32 == WSAEWOULDBLOCK: return false - else: osError(err) + else: raiseOSError(err) else: if err.int32 == EAGAIN or err.int32 == EWOULDBLOCK: return false - else: osError(err) + else: raiseOSError(err) setLen(s.string, pos + bytesRead) if bytesRead != bufSize-1: break @@ -1516,11 +1526,11 @@ proc recvFromAsync*(socket: TSocket, data: var string, length: int, when defined(windows): if err.int32 == WSAEWOULDBLOCK: return false - else: osError(err) + else: raiseOSError(err) else: if err.int32 == EAGAIN or err.int32 == EWOULDBLOCK: return false - else: osError(err) + else: raiseOSError(err) proc skip*(socket: TSocket) {.tags: [ReadIOEffect], deprecated.} = ## skips all the data that is pending for the socket @@ -1570,7 +1580,7 @@ proc send*(socket: TSocket, data: string) {.tags: [WriteIOEffect].} = if socket.isSSL: SSLError() - osError(osLastError()) + raiseOSError(osLastError()) if sent != data.len: raise newException(OSError, "Could not send all data.") @@ -1607,11 +1617,11 @@ proc sendAsync*(socket: TSocket, data: string): int {.tags: [WriteIOEffect].} = when defined(windows): if err.int32 == WSAEINPROGRESS: return 0 - else: osError(err) + else: raiseOSError(err) else: if err.int32 == EAGAIN or err.int32 == EWOULDBLOCK: return 0 - else: osError(err) + else: raiseOSError(err) proc trySend*(socket: TSocket, data: string): bool {.tags: [WriteIOEffect].} = @@ -1667,15 +1677,15 @@ proc setBlocking(s: TSocket, blocking: bool) = when defined(Windows): var mode = clong(ord(not blocking)) # 1 for non-blocking, 0 for blocking if ioctlsocket(s.fd, FIONBIO, addr(mode)) == -1: - osError(osLastError()) + raiseOSError(osLastError()) else: # BSD sockets var x: int = fcntl(s.fd, F_GETFL, 0) if x == -1: - osError(osLastError()) + raiseOSError(osLastError()) else: var mode = if blocking: x and not O_NONBLOCK else: x or O_NONBLOCK if fcntl(s.fd, F_SETFL, mode) == -1: - osError(osLastError()) + raiseOSError(osLastError()) s.nonblocking = not blocking discard """ proc setReuseAddr*(s: TSocket) = @@ -1715,6 +1725,6 @@ proc isBlocking*(socket: TSocket): bool = not socket.nonblocking when defined(Windows): var wsa: TWSAData - if wsaStartup(0x0101'i16, addr wsa) != 0: osError(osLastError()) + if wsaStartup(0x0101'i16, addr wsa) != 0: raiseOSError(osLastError()) diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim index c4e969f21..bc0f1c540 100644 --- a/lib/pure/streams.nim +++ b/lib/pure/streams.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -8,8 +8,8 @@ # ## This module provides a stream interface and two implementations thereof: -## the `PFileStream` and the `PStringStream` which implement the stream -## interface for Nimrod file objects (`TFile`) and strings. Other modules +## the `FileStream` and the `StringStream` which implement the stream +## interface for Nimrod file objects (`File`) and strings. Other modules ## may provide other implementations for this standard stream interface. include "system/inclrtl" @@ -19,81 +19,83 @@ proc newEIO(msg: string): ref IOError = result.msg = msg type - PStream* = ref TStream - TStream* = object of RootObj ## Stream interface that supports - ## writing or reading. Note that these fields - ## here shouldn't be used directly. They are - ## accessible so that a stream implementation - ## can override them. - closeImpl*: proc (s: PStream) {.nimcall, tags: [], gcsafe.} - atEndImpl*: proc (s: PStream): bool {.nimcall, tags: [], gcsafe.} - setPositionImpl*: proc (s: PStream, pos: int) {.nimcall, tags: [], gcsafe.} - getPositionImpl*: proc (s: PStream): int {.nimcall, tags: [], gcsafe.} - readDataImpl*: proc (s: PStream, buffer: pointer, + Stream* = ref StreamObj + StreamObj* = object of RootObj ## Stream interface that supports + ## writing or reading. Note that these fields + ## here shouldn't be used directly. They are + ## accessible so that a stream implementation + ## can override them. + closeImpl*: proc (s: Stream) {.nimcall, tags: [], gcsafe.} + atEndImpl*: proc (s: Stream): bool {.nimcall, tags: [], gcsafe.} + setPositionImpl*: proc (s: Stream, pos: int) {.nimcall, tags: [], gcsafe.} + getPositionImpl*: proc (s: Stream): int {.nimcall, tags: [], gcsafe.} + readDataImpl*: proc (s: Stream, buffer: pointer, bufLen: int): int {.nimcall, tags: [ReadIOEffect], gcsafe.} - writeDataImpl*: proc (s: PStream, buffer: pointer, bufLen: int) {.nimcall, + writeDataImpl*: proc (s: Stream, buffer: pointer, bufLen: int) {.nimcall, tags: [WriteIOEffect], gcsafe.} - flushImpl*: proc (s: PStream) {.nimcall, tags: [WriteIOEffect], gcsafe.} + flushImpl*: proc (s: Stream) {.nimcall, tags: [WriteIOEffect], gcsafe.} -proc flush*(s: PStream) = +{.deprecated: [PStream: Stream, TStream: StreamObj].} + +proc flush*(s: Stream) = ## flushes the buffers that the stream `s` might use. if not isNil(s.flushImpl): s.flushImpl(s) -proc close*(s: PStream) = +proc close*(s: Stream) = ## closes the stream `s`. if not isNil(s.closeImpl): s.closeImpl(s) -proc close*(s, unused: PStream) {.deprecated.} = +proc close*(s, unused: Stream) {.deprecated.} = ## closes the stream `s`. s.closeImpl(s) -proc atEnd*(s: PStream): bool = +proc atEnd*(s: Stream): bool = ## checks if more data can be read from `f`. Returns true if all data has ## been read. result = s.atEndImpl(s) -proc atEnd*(s, unused: PStream): bool {.deprecated.} = +proc atEnd*(s, unused: Stream): bool {.deprecated.} = ## checks if more data can be read from `f`. Returns true if all data has ## been read. result = s.atEndImpl(s) -proc setPosition*(s: PStream, pos: int) = +proc setPosition*(s: Stream, pos: int) = ## sets the position `pos` of the stream `s`. s.setPositionImpl(s, pos) -proc setPosition*(s, unused: PStream, pos: int) {.deprecated.} = +proc setPosition*(s, unused: Stream, pos: int) {.deprecated.} = ## sets the position `pos` of the stream `s`. s.setPositionImpl(s, pos) -proc getPosition*(s: PStream): int = +proc getPosition*(s: Stream): int = ## retrieves the current position in the stream `s`. result = s.getPositionImpl(s) -proc getPosition*(s, unused: PStream): int {.deprecated.} = +proc getPosition*(s, unused: Stream): int {.deprecated.} = ## retrieves the current position in the stream `s`. result = s.getPositionImpl(s) -proc readData*(s: PStream, buffer: pointer, bufLen: int): int = +proc readData*(s: Stream, buffer: pointer, bufLen: int): int = ## low level proc that reads data into an untyped `buffer` of `bufLen` size. result = s.readDataImpl(s, buffer, bufLen) -proc readData*(s, unused: PStream, buffer: pointer, +proc readData*(s, unused: Stream, buffer: pointer, bufLen: int): int {.deprecated.} = ## low level proc that reads data into an untyped `buffer` of `bufLen` size. result = s.readDataImpl(s, buffer, bufLen) -proc writeData*(s: PStream, buffer: pointer, bufLen: int) = +proc writeData*(s: Stream, buffer: pointer, bufLen: int) = ## low level proc that writes an untyped `buffer` of `bufLen` size ## to the stream `s`. s.writeDataImpl(s, buffer, bufLen) -proc writeData*(s, unused: PStream, buffer: pointer, +proc writeData*(s, unused: Stream, buffer: pointer, bufLen: int) {.deprecated.} = ## low level proc that writes an untyped `buffer` of `bufLen` size ## to the stream `s`. s.writeDataImpl(s, buffer, bufLen) -proc write*[T](s: PStream, x: T) = +proc write*[T](s: Stream, x: T) = ## generic write procedure. Writes `x` to the stream `s`. Implementation: ## ## .. code-block:: Nimrod @@ -103,63 +105,63 @@ proc write*[T](s: PStream, x: T) = shallowCopy(y, x) writeData(s, addr(y), sizeof(y)) -proc write*(s: PStream, x: string) = +proc write*(s: Stream, x: string) = ## writes the string `x` to the the stream `s`. No length field or ## terminating zero is written. writeData(s, cstring(x), x.len) -proc writeln*(s: PStream, args: varargs[string, `$`]) = +proc writeln*(s: Stream, args: varargs[string, `$`]) = ## writes one or more strings to the the stream `s` followed ## by a new line. No length field or terminating zero is written. for str in args: write(s, str) write(s, "\n") -proc read[T](s: PStream, result: var T) = +proc read[T](s: Stream, result: var T) = ## generic read procedure. Reads `result` from the stream `s`. if readData(s, addr(result), sizeof(T)) != sizeof(T): raise newEIO("cannot read from stream") -proc readChar*(s: PStream): char = +proc readChar*(s: Stream): char = ## reads a char from the stream `s`. Raises `EIO` if an error occured. ## Returns '\0' as an EOF marker. if readData(s, addr(result), sizeof(result)) != 1: result = '\0' -proc readBool*(s: PStream): bool = +proc readBool*(s: Stream): bool = ## reads a bool from the stream `s`. Raises `EIO` if an error occured. read(s, result) -proc readInt8*(s: PStream): int8 = +proc readInt8*(s: Stream): int8 = ## reads an int8 from the stream `s`. Raises `EIO` if an error occured. read(s, result) -proc readInt16*(s: PStream): int16 = +proc readInt16*(s: Stream): int16 = ## reads an int16 from the stream `s`. Raises `EIO` if an error occured. read(s, result) -proc readInt32*(s: PStream): int32 = +proc readInt32*(s: Stream): int32 = ## reads an int32 from the stream `s`. Raises `EIO` if an error occured. read(s, result) -proc readInt64*(s: PStream): int64 = +proc readInt64*(s: Stream): int64 = ## reads an int64 from the stream `s`. Raises `EIO` if an error occured. read(s, result) -proc readFloat32*(s: PStream): float32 = +proc readFloat32*(s: Stream): float32 = ## reads a float32 from the stream `s`. Raises `EIO` if an error occured. read(s, result) -proc readFloat64*(s: PStream): float64 = +proc readFloat64*(s: Stream): float64 = ## reads a float64 from the stream `s`. Raises `EIO` if an error occured. read(s, result) -proc readStr*(s: PStream, length: int): TaintedString = +proc readStr*(s: Stream, length: int): TaintedString = ## reads a string of length `length` from the stream `s`. Raises `EIO` if ## an error occured. result = newString(length).TaintedString var L = readData(s, addr(string(result)[0]), length) if L != length: setLen(result.string, L) -proc readLine*(s: PStream, line: var TaintedString): bool = +proc readLine*(s: Stream, line: var TaintedString): bool = ## reads a line of text from the stream `s` into `line`. `line` must not be ## ``nil``! May throw an IO exception. ## A line of text may be delimited by ``CR``, ``LF`` or @@ -179,7 +181,7 @@ proc readLine*(s: PStream, line: var TaintedString): bool = line.string.add(c) result = true -proc readLine*(s: PStream): TaintedString = +proc readLine*(s: Stream): TaintedString = ## Reads a line from a stream `s`. Note: This is not very efficient. Raises ## `EIO` if an error occured. result = TaintedString"" @@ -194,42 +196,44 @@ proc readLine*(s: PStream): TaintedString = result.string.add(c) type - PStringStream* = ref TStringStream ## a stream that encapsulates a string - TStringStream* = object of TStream + StringStream* = ref StringStreamObj ## a stream that encapsulates a string + StringStreamObj* = object of StreamObj data*: string pos: int - -proc ssAtEnd(s: PStream): bool = - var s = PStringStream(s) + +{.deprecated: [PStringStream: StringStream, TStringStream: StringStreamObj].} + +proc ssAtEnd(s: Stream): bool = + var s = StringStream(s) return s.pos >= s.data.len -proc ssSetPosition(s: PStream, pos: int) = - var s = PStringStream(s) +proc ssSetPosition(s: Stream, pos: int) = + var s = StringStream(s) s.pos = clamp(pos, 0, s.data.high) -proc ssGetPosition(s: PStream): int = - var s = PStringStream(s) +proc ssGetPosition(s: Stream): int = + var s = StringStream(s) return s.pos -proc ssReadData(s: PStream, buffer: pointer, bufLen: int): int = - var s = PStringStream(s) +proc ssReadData(s: Stream, buffer: pointer, bufLen: int): int = + var s = StringStream(s) result = min(bufLen, s.data.len - s.pos) if result > 0: copyMem(buffer, addr(s.data[s.pos]), result) inc(s.pos, result) -proc ssWriteData(s: PStream, buffer: pointer, bufLen: int) = - var s = PStringStream(s) +proc ssWriteData(s: Stream, buffer: pointer, bufLen: int) = + var s = StringStream(s) if bufLen > 0: setLen(s.data, s.data.len + bufLen) copyMem(addr(s.data[s.pos]), buffer, bufLen) inc(s.pos, bufLen) -proc ssClose(s: PStream) = - var s = PStringStream(s) +proc ssClose(s: Stream) = + var s = StringStream(s) s.data = nil -proc newStringStream*(s: string = ""): PStringStream = +proc newStringStream*(s: string = ""): StringStream = ## creates a new stream from the string `s`. new(result) result.data = s @@ -244,27 +248,28 @@ proc newStringStream*(s: string = ""): PStringStream = when not defined(js): type - PFileStream* = ref TFileStream ## a stream that encapsulates a `TFile` - TFileStream* = object of TStream + FileStream* = ref FileStreamObj ## a stream that encapsulates a `TFile` + FileStreamObj* = object of Stream f: File - - proc fsClose(s: PStream) = - if PFileStream(s).f != nil: - close(PFileStream(s).f) - PFileStream(s).f = nil - proc fsFlush(s: PStream) = flushFile(PFileStream(s).f) - proc fsAtEnd(s: PStream): bool = return endOfFile(PFileStream(s).f) - proc fsSetPosition(s: PStream, pos: int) = setFilePos(PFileStream(s).f, pos) - proc fsGetPosition(s: PStream): int = return int(getFilePos(PFileStream(s).f)) - - proc fsReadData(s: PStream, buffer: pointer, bufLen: int): int = - result = readBuffer(PFileStream(s).f, buffer, bufLen) - - proc fsWriteData(s: PStream, buffer: pointer, bufLen: int) = - if writeBuffer(PFileStream(s).f, buffer, bufLen) != bufLen: + {.deprecated: [PFileStream: FileStream, TFileStream: FileStreamObj].} + + proc fsClose(s: Stream) = + if FileStream(s).f != nil: + close(FileStream(s).f) + FileStream(s).f = nil + proc fsFlush(s: Stream) = flushFile(FileStream(s).f) + proc fsAtEnd(s: Stream): bool = return endOfFile(FileStream(s).f) + proc fsSetPosition(s: Stream, pos: int) = setFilePos(FileStream(s).f, pos) + proc fsGetPosition(s: Stream): int = return int(getFilePos(FileStream(s).f)) + + proc fsReadData(s: Stream, buffer: pointer, bufLen: int): int = + result = readBuffer(FileStream(s).f, buffer, bufLen) + + proc fsWriteData(s: Stream, buffer: pointer, bufLen: int) = + if writeBuffer(FileStream(s).f, buffer, bufLen) != bufLen: raise newEIO("cannot write to stream") - proc newFileStream*(f: File): PFileStream = + proc newFileStream*(f: File): FileStream = ## creates a new stream from the file `f`. new(result) result.f = f @@ -276,7 +281,7 @@ when not defined(js): result.writeDataImpl = fsWriteData result.flushImpl = fsFlush - proc newFileStream*(filename: string, mode: FileMode): PFileStream = + proc newFileStream*(filename: string, mode: FileMode): FileStream = ## creates a new stream from the file named `filename` with the mode `mode`. ## If the file cannot be opened, nil is returned. See the `system ## <system.html>`_ module for a list of available TFileMode enums. @@ -288,45 +293,47 @@ when true: discard else: type - TFileHandle* = cint ## Operating system file handle - PFileHandleStream* = ref TFileHandleStream - TFileHandleStream* = object of TStream - handle*: TFileHandle + FileHandleStream* = ref FileHandleStreamObj + FileHandleStreamObj* = object of Stream + handle*: FileHandle pos: int - proc newEOS(msg: string): ref EOS = + {.deprecated: [PFileHandleStream: FileHandleStream, + TFileHandleStream: FileHandleStreamObj].} + + proc newEOS(msg: string): ref OSError = new(result) result.msg = msg - proc hsGetPosition(s: PFileHandleStream): int = + proc hsGetPosition(s: FileHandleStream): int = return s.pos when defined(windows): # do not import windows as this increases compile times: - nil + discard else: import posix - proc hsSetPosition(s: PFileHandleStream, pos: int) = + proc hsSetPosition(s: FileHandleStream, pos: int) = discard lseek(s.handle, pos, SEEK_SET) - proc hsClose(s: PFileHandleStream) = discard close(s.handle) - proc hsAtEnd(s: PFileHandleStream): bool = + proc hsClose(s: FileHandleStream) = discard close(s.handle) + proc hsAtEnd(s: FileHandleStream): bool = var pos = hsGetPosition(s) var theEnd = lseek(s.handle, 0, SEEK_END) result = pos >= theEnd hsSetPosition(s, pos) # set position back - proc hsReadData(s: PFileHandleStream, buffer: pointer, bufLen: int): int = + proc hsReadData(s: FileHandleStream, buffer: pointer, bufLen: int): int = result = posix.read(s.handle, buffer, bufLen) inc(s.pos, result) - proc hsWriteData(s: PFileHandleStream, buffer: pointer, bufLen: int) = + proc hsWriteData(s: FileHandleStream, buffer: pointer, bufLen: int) = if posix.write(s.handle, buffer, bufLen) != bufLen: raise newEIO("cannot write to stream") inc(s.pos, bufLen) - proc newFileHandleStream*(handle: TFileHandle): PFileHandleStream = + proc newFileHandleStream*(handle: FileHandle): FileHandleStream = new(result) result.handle = handle result.pos = 0 @@ -338,9 +345,9 @@ else: result.writeData = hsWriteData proc newFileHandleStream*(filename: string, - mode: TFileMode): PFileHandleStream = - when defined(windows): - nil + mode: FileMode): FileHandleStream = + when defined(windows): + discard else: var flags: cint case mode diff --git a/lib/pure/strtabs.nim b/lib/pure/strtabs.nim index 12621a0fc..71d16192f 100644 --- a/lib/pure/strtabs.nim +++ b/lib/pure/strtabs.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -18,20 +18,23 @@ import include "system/inclrtl" type - TStringTableMode* = enum ## describes the tables operation mode + StringTableMode* = enum ## describes the tables operation mode modeCaseSensitive, ## the table is case sensitive modeCaseInsensitive, ## the table is case insensitive modeStyleInsensitive ## the table is style insensitive - TKeyValuePair = tuple[key, val: string] - TKeyValuePairSeq = seq[TKeyValuePair] - TStringTable* = object of RootObj + KeyValuePair = tuple[key, val: string] + KeyValuePairSeq = seq[KeyValuePair] + StringTableObj* = object of RootObj counter: int - data: TKeyValuePairSeq - mode: TStringTableMode + data: KeyValuePairSeq + mode: StringTableMode - PStringTable* = ref TStringTable ## use this type to declare string tables + StringTableRef* = ref StringTableObj ## use this type to declare string tables -proc len*(t: PStringTable): int {.rtl, extern: "nst$1".} = +{.deprecated: [TStringTableMode: StringTableMode, + TStringTable: StringTableObj, PStringTable: StringTableRef].} + +proc len*(t: StringTableRef): int {.rtl, extern: "nst$1".} = ## returns the number of keys in `t`. result = t.counter @@ -54,7 +57,7 @@ iterator values*(t: PStringTable): string = yield t.data[h].val type - TFormatFlag* = enum ## flags for the `%` operator + FormatFlag* = enum ## flags for the `%` operator useEnvironment, ## use environment variable if the ``$key`` ## is not found in the table useEmpty, ## use the empty string as a default, thus it @@ -63,6 +66,8 @@ type useKey ## do not replace ``$key`` if it is not found ## in the table (or in the environment) +{.deprecated: [TFormatFlag: FormatFlag].} + # implementation const diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index cc62ad1ee..82516653c 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -23,7 +23,7 @@ import parseutils include "system/inclrtl" type - TCharSet* = set[char] # for compatibility with Nim + TCharSet* {.deprecated.} = set[char] # for compatibility with Nim const Whitespace* = {' ', '\t', '\v', '\r', '\l', '\f'} @@ -54,7 +54,7 @@ const ## make the `find() proc <#find,string,set[char],int>`_ find **invalid** ## characters in strings. Example: ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## let invalid = AllChars - Digits ## doAssert "01234".find(invalid) == -1 ## doAssert "01A34".find(invalid) == 2 @@ -205,7 +205,7 @@ iterator split*(s: string, seps: set[char] = Whitespace): string = ## a single split point and leading/trailing separators will be ignored. ## The following example: ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## for word in split(" this is an example "): ## writeln(stdout, word) ## @@ -219,13 +219,13 @@ iterator split*(s: string, seps: set[char] = Whitespace): string = ## ## And the following code: ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## for word in split(";;this;is;an;;example;;;", {';'}): ## writeln(stdout, word) ## ## ...produces the same output as the first example. The code: ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## let date = "2012-11-20T22:08:08.398990" ## let separators = {' ', '-', ':', 'T'} ## for number in split(date, separators): @@ -258,7 +258,7 @@ iterator split*(s: string, sep: char): string = ## characters, this proc will not coalesce groups of the ## separator, returning a string for each found character. The code: ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## for word in split(";;this;is;an;;example;;;", ';'): ## writeln(stdout, word) ## @@ -308,13 +308,13 @@ iterator splitLines*(s: string): string = ## ## Example: ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## for line in splitLines("\nthis\nis\nan\n\nexample\n"): ## writeln(stdout, line) ## ## Results in: ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## "" ## "this" ## "is" @@ -417,7 +417,7 @@ proc parseInt*(s: string): int {.noSideEffect, procvar, rtl, extern: "nsuParseInt".} = ## Parses a decimal integer value contained in `s`. ## - ## If `s` is not a valid integer, `EInvalidValue` is raised. + ## If `s` is not a valid integer, `ValueError` is raised. var L = parseutils.parseInt(s, result, 0) if L != s.len or L == 0: raise newException(ValueError, "invalid integer: " & s) @@ -426,7 +426,7 @@ proc parseBiggestInt*(s: string): BiggestInt {.noSideEffect, procvar, rtl, extern: "nsuParseBiggestInt".} = ## Parses a decimal integer value contained in `s`. ## - ## If `s` is not a valid integer, `EInvalidValue` is raised. + ## If `s` is not a valid integer, `ValueError` is raised. var L = parseutils.parseBiggestInt(s, result, 0) if L != s.len or L == 0: raise newException(ValueError, "invalid integer: " & s) @@ -434,7 +434,7 @@ proc parseBiggestInt*(s: string): BiggestInt {.noSideEffect, procvar, proc parseFloat*(s: string): float {.noSideEffect, procvar, rtl, extern: "nsuParseFloat".} = ## Parses a decimal floating point value contained in `s`. If `s` is not - ## a valid floating point number, `EInvalidValue` is raised. ``NAN``, + ## a valid floating point number, `ValueError` is raised. ``NAN``, ## ``INF``, ``-INF`` are also supported (case insensitive comparison). var L = parseutils.parseFloat(s, result, 0) if L != s.len or L == 0: @@ -444,7 +444,7 @@ proc parseHexInt*(s: string): int {.noSideEffect, procvar, rtl, extern: "nsuParseHexInt".} = ## Parses a hexadecimal integer value contained in `s`. ## - ## If `s` is not a valid integer, `EInvalidValue` is raised. `s` can have one + ## If `s` is not a valid integer, `ValueError` is raised. `s` can have one ## of the following optional prefixes: ``0x``, ``0X``, ``#``. Underscores ## within `s` are ignored. var i = 0 @@ -471,7 +471,7 @@ proc parseBool*(s: string): bool = ## If ``s`` is one of the following values: ``y, yes, true, 1, on``, then ## returns `true`. If ``s`` is one of the following values: ``n, no, false, ## 0, off``, then returns `false`. If ``s`` is something else a - ## ``EInvalidValue`` exception is raised. + ## ``ValueError`` exception is raised. case normalize(s) of "y", "yes", "true", "1", "on": result = true of "n", "no", "false", "0", "off": result = false @@ -480,7 +480,7 @@ proc parseBool*(s: string): bool = proc parseEnum*[T: enum](s: string): T = ## Parses an enum ``T``. ## - ## Raises ``EInvalidValue`` for an invalid value in `s`. The comparison is + ## Raises ``ValueError`` for an invalid value in `s`. The comparison is ## done in a style insensitive way. for e in low(T)..high(T): if cmpIgnoreStyle(s, $e) == 0: @@ -502,7 +502,7 @@ proc repeatChar*(count: int, c: char = ' '): string {.noSideEffect, ## Returns a string of length `count` consisting only of ## the character `c`. You can use this proc to left align strings. Example: ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## let ## width = 15 ## text1 = "Hello user!" @@ -527,7 +527,7 @@ proc align*(s: string, count: int, padding = ' '): string {. ## returned unchanged. If you need to left align a string use the `repeatChar ## proc <#repeatChar>`_. Example: ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## assert align("abc", 4) == " abc" ## assert align("a", 0) == "a" ## assert align("1232", 6) == " 1232" @@ -547,13 +547,13 @@ iterator tokenize*(s: string, seps: set[char] = Whitespace): tuple[ ## Substrings are separated by a substring containing only `seps`. ## Examples: ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## for word in tokenize(" this is an example "): ## writeln(stdout, word) ## ## Results in: ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## (" ", true) ## ("this", false) ## (" ", true) @@ -676,7 +676,7 @@ proc addSep*(dest: var string, sep = ", ", startLen = 0) {.noSideEffect, ## ## A shorthand for: ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## if dest.len > startLen: add(dest, sep) ## ## This is often useful for generating some code where the items need to @@ -684,7 +684,7 @@ proc addSep*(dest: var string, sep = ", ", startLen = 0) {.noSideEffect, ## `startLen`. The following example creates a string describing ## an array of integers: ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## var arr = "[" ## for x in items([2, 3, 5, 7, 11]): ## addSep(arr, startLen=len("[")) @@ -692,7 +692,7 @@ proc addSep*(dest: var string, sep = ", ", startLen = 0) {.noSideEffect, ## add(arr, "]") if dest.len > startLen: add(dest, sep) -proc allCharsInSet*(s: string, theSet: TCharSet): bool = +proc allCharsInSet*(s: string, theSet: set[char]): bool = ## Returns true iff each character of `s` is in the set `theSet`. for c in items(s): if c notin theSet: return false @@ -739,14 +739,14 @@ proc join*(a: openArray[string]): string {. result = "" type - TSkipTable = array[char, int] + SkipTable = array[char, int] -proc preprocessSub(sub: string, a: var TSkipTable) = +proc preprocessSub(sub: string, a: var SkipTable) = var m = len(sub) for i in 0..0xff: a[chr(i)] = m+1 for i in 0..m-1: a[sub[i]] = m-i -proc findAux(s, sub: string, start: int, a: TSkipTable): int = +proc findAux(s, sub: string, start: int, a: SkipTable): int = # Fast "quick search" algorithm: var m = len(sub) @@ -762,7 +762,7 @@ proc findAux(s, sub: string, start: int, a: TSkipTable): int = return -1 proc find*(s, sub: string, start: int = 0): int {.noSideEffect, - rtl, extern: "nsuFindStr", operator: 6.} = + rtl, extern: "nsuFindStr".} = ## Searches for `sub` in `s` starting at position `start`. ## ## Searching is case-sensitive. If `sub` is not in `s`, -1 is returned. @@ -827,9 +827,9 @@ proc contains*(s: string, chars: set[char]): bool {.noSideEffect.} = return find(s, chars) >= 0 proc replace*(s, sub: string, by = ""): string {.noSideEffect, - rtl, extern: "nsuReplaceStr", operator: 1.} = + rtl, extern: "nsuReplaceStr".} = ## Replaces `sub` in `s` by the string `by`. - var a {.noinit.}: TSkipTable + var a {.noinit.}: SkipTable result = "" preprocessSub(sub, a) var i = 0 @@ -862,7 +862,7 @@ proc replaceWord*(s, sub: string, by = ""): string {.noSideEffect, ## (comparable to ``\\w`` in regular expressions), otherwise it is not ## replaced. const wordChars = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\128'..'\255'} - var a {.noinit.}: TSkipTable + var a {.noinit.}: SkipTable result = "" preprocessSub(sub, a) var i = 0 @@ -899,7 +899,7 @@ proc parseOctInt*(s: string): int {.noSideEffect, rtl, extern: "nsuParseOctInt".} = ## Parses an octal integer value contained in `s`. ## - ## If `s` is not a valid integer, `EInvalidValue` is raised. `s` can have one + ## If `s` is not a valid integer, `ValueError` is raised. `s` can have one ## of the following optional prefixes: ``0o``, ``0O``. Underscores within ## `s` are ignored. var i = 0 @@ -999,7 +999,7 @@ proc unescape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect, ## operations. ## ## If `s` does not begin with ``prefix`` and end with ``suffix`` a - ## EInvalidValue exception will be raised. + ## ValueError exception will be raised. result = newStringOfCap(s.len) var i = 0 if s[0 .. prefix.len-1] != prefix: @@ -1138,12 +1138,14 @@ proc c_sprintf(buf, frmt: cstring) {.header: "<stdio.h>", importc: "sprintf", varargs, noSideEffect.} type - TFloatFormat* = enum ## the different modes of floating point formating + FloatFormatMode* = enum ## the different modes of floating point formating ffDefault, ## use the shorter floating point notation ffDecimal, ## use decimal floating point notation ffScientific ## use scientific notation (using ``e`` character) -proc formatBiggestFloat*(f: BiggestFloat, format: TFloatFormat = ffDefault, +{.deprecated: [TFloatFormat: FloatFormatMode].} + +proc formatBiggestFloat*(f: BiggestFloat, format: FloatFormatMode = ffDefault, precision: range[0..32] = 16): string {. noSideEffect, operator: 2, rtl, extern: "nsu$1".} = ## Converts a floating point value `f` to a string. @@ -1174,7 +1176,7 @@ proc formatBiggestFloat*(f: BiggestFloat, format: TFloatFormat = ffDefault, c_sprintf(buf, frmtstr, f) result = $buf -proc formatFloat*(f: float, format: TFloatFormat = ffDefault, +proc formatFloat*(f: float, format: FloatFormatMode = ffDefault, precision: range[0..32] = 16): string {. noSideEffect, operator: 2, rtl, extern: "nsu$1".} = ## Converts a floating point value `f` to a string. @@ -1190,7 +1192,7 @@ proc formatFloat*(f: float, format: TFloatFormat = ffDefault, proc formatSize*(bytes: BiggestInt, decimalSep = '.'): string = ## Rounds and formats `bytes`. Examples: ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## ## formatSize(1'i64 shl 31 + 300'i64) == "2.204GB" ## formatSize(4096) == "4KB" @@ -1280,12 +1282,12 @@ proc `%` *(formatstr: string, a: openArray[string]): string {.noSideEffect, ## ## This is best explained by an example: ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## "$1 eats $2." % ["The cat", "fish"] ## ## Results in: ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## "The cat eats fish." ## ## The substitution variables (the thing after the ``$``) are enumerated @@ -1294,7 +1296,7 @@ proc `%` *(formatstr: string, a: openArray[string]): string {.noSideEffect, ## The notation ``$#`` can be used to refer to the next substitution ## variable: ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## "$# eats $#." % ["The cat", "fish"] ## ## Substitution variables can also be words (that is @@ -1302,15 +1304,15 @@ proc `%` *(formatstr: string, a: openArray[string]): string {.noSideEffect, ## indices are keys and with odd indices are the corresponding values. ## An example: ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## "$animal eats $food." % ["animal", "The cat", "food", "fish"] ## ## Results in: ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## "The cat eats fish." ## - ## The variables are compared with `cmpIgnoreStyle`. `EInvalidValue` is + ## The variables are compared with `cmpIgnoreStyle`. `ValueError` is ## raised if an ill-formed format string has been passed to the `%` operator. result = newStringOfCap(formatstr.len + a.len shl 4) addf(result, formatstr, a) @@ -1350,7 +1352,7 @@ when isMainModule: doAssert "-ld a-ldz -ld".replaceWord("-ld") == " a-ldz " doAssert "-lda-ldz -ld abc".replaceWord("-ld") == "-lda-ldz abc" - type TMyEnum = enum enA, enB, enC, enuD, enE - doAssert parseEnum[TMyEnum]("enu_D") == enuD + type MyEnum = enum enA, enB, enC, enuD, enE + doAssert parseEnum[MyEnum]("enu_D") == enuD doAssert parseEnum("invalid enum value", enC) == enC diff --git a/lib/pure/subexes.nim b/lib/pure/subexes.nim index ed87610d6..452978c09 100644 --- a/lib/pure/subexes.nim +++ b/lib/pure/subexes.nim @@ -1,13 +1,13 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # -## Nimrod support for `substitution expressions`:idx: (`subex`:idx:). +## Nim support for `substitution expressions`:idx: (`subex`:idx:). ## ## .. include:: ../doc/subexes.txt ## @@ -28,11 +28,13 @@ proc findNormalized(x: string, inArray: openarray[string]): int = return -1 type - EInvalidSubex* = object of EInvalidValue ## exception that is raised for - ## an invalid subex + SubexError* = object of ValueError ## exception that is raised for + ## an invalid subex + +{.deprecated: [EInvalidSubex: SubexError].} proc raiseInvalidFormat(msg: string) {.noinline.} = - raise newException(EInvalidSubex, "invalid format string: " & msg) + raise newException(SubexError, "invalid format string: " & msg) type TFormatParser = object {.pure, final.} @@ -291,14 +293,16 @@ proc scanDollar(p: var TFormatParser, a: openarray[string], s: var string) = type - TSubex* = distinct string ## string that contains a substitution expression + Subex* = distinct string ## string that contains a substitution expression + +{.deprecated: [TSubex: Subex].} -proc subex*(s: string): TSubex = +proc subex*(s: string): Subex = ## constructs a *substitution expression* from `s`. Currently this performs ## no syntax checking but this may change in later versions. - result = TSubex(s) + result = Subex(s) -proc addf*(s: var string, formatstr: TSubex, a: varargs[string, `$`]) {. +proc addf*(s: var string, formatstr: Subex, a: varargs[string, `$`]) {. noSideEffect, rtl, extern: "nfrmtAddf".} = ## The same as ``add(s, formatstr % a)``, but more efficient. var p: TFormatParser @@ -312,7 +316,7 @@ proc addf*(s: var string, formatstr: TSubex, a: varargs[string, `$`]) {. emitChar(p, s, p.f[i]) inc(i) -proc `%` *(formatstr: TSubex, a: openarray[string]): string {.noSideEffect, +proc `%` *(formatstr: Subex, a: openarray[string]): string {.noSideEffect, rtl, extern: "nfrmtFormatOpenArray".} = ## The `substitution`:idx: operator performs string substitutions in ## `formatstr` and returns a modified `formatstr`. This is often called @@ -321,13 +325,13 @@ proc `%` *(formatstr: TSubex, a: openarray[string]): string {.noSideEffect, result = newStringOfCap(formatstr.string.len + a.len shl 4) addf(result, formatstr, a) -proc `%` *(formatstr: TSubex, a: string): string {.noSideEffect, +proc `%` *(formatstr: Subex, a: string): string {.noSideEffect, rtl, extern: "nfrmtFormatSingleElem".} = ## This is the same as ``formatstr % [a]``. result = newStringOfCap(formatstr.string.len + a.len) addf(result, formatstr, [a]) -proc format*(formatstr: TSubex, a: varargs[string, `$`]): string {.noSideEffect, +proc format*(formatstr: Subex, a: varargs[string, `$`]): string {.noSideEffect, rtl, extern: "nfrmtFormatVarargs".} = ## The `substitution`:idx: operator performs string substitutions in ## `formatstr` and returns a modified `formatstr`. This is often called diff --git a/lib/pure/terminal.nim b/lib/pure/terminal.nim index 20f1d0695..0ebe8a39e 100644 --- a/lib/pure/terminal.nim +++ b/lib/pure/terminal.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -27,11 +27,11 @@ when defined(windows): var hTemp = GetStdHandle(STD_OUTPUT_HANDLE) if DuplicateHandle(GetCurrentProcess(), hTemp, GetCurrentProcess(), addr(conHandle), 0, 1, DUPLICATE_SAME_ACCESS) == 0: - osError(osLastError()) + raiseOSError(osLastError()) proc getCursorPos(): tuple [x,y: int] = var c: TCONSOLESCREENBUFFERINFO - if GetConsoleScreenBufferInfo(conHandle, addr(c)) == 0: osError(osLastError()) + if GetConsoleScreenBufferInfo(conHandle, addr(c)) == 0: raiseOSError(osLastError()) return (int(c.dwCursorPosition.x), int(c.dwCursorPosition.y)) proc getAttributes(): int16 = @@ -51,7 +51,7 @@ proc setCursorPos*(x, y: int) = var c: TCOORD c.x = int16(x) c.y = int16(y) - if SetConsoleCursorPosition(conHandle, c) == 0: osError(osLastError()) + if SetConsoleCursorPosition(conHandle, c) == 0: raiseOSError(osLastError()) else: stdout.write("\e[" & $y & ';' & $x & 'f') @@ -61,10 +61,10 @@ proc setCursorXPos*(x: int) = when defined(windows): var scrbuf: TCONSOLESCREENBUFFERINFO var hStdout = conHandle - if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: osError(osLastError()) + if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: raiseOSError(osLastError()) var origin = scrbuf.dwCursorPosition origin.x = int16(x) - if SetConsoleCursorPosition(conHandle, origin) == 0: osError(osLastError()) + if SetConsoleCursorPosition(conHandle, origin) == 0: raiseOSError(osLastError()) else: stdout.write("\e[" & $x & 'G') @@ -75,10 +75,10 @@ when defined(windows): when defined(windows): var scrbuf: TCONSOLESCREENBUFFERINFO var hStdout = conHandle - if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: osError(osLastError()) + if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: raiseOSError(osLastError()) var origin = scrbuf.dwCursorPosition origin.y = int16(y) - if SetConsoleCursorPosition(conHandle, origin) == 0: osError(osLastError()) + if SetConsoleCursorPosition(conHandle, origin) == 0: raiseOSError(osLastError()) else: discard @@ -155,18 +155,18 @@ proc eraseLine* = var scrbuf: TCONSOLESCREENBUFFERINFO var numwrote: DWORD var hStdout = conHandle - if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: osError(osLastError()) + if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: raiseOSError(osLastError()) var origin = scrbuf.dwCursorPosition origin.x = 0'i16 - if SetConsoleCursorPosition(conHandle, origin) == 0: osError(osLastError()) + if SetConsoleCursorPosition(conHandle, origin) == 0: raiseOSError(osLastError()) var ht = scrbuf.dwSize.Y - origin.Y var wt = scrbuf.dwSize.X - origin.X if FillConsoleOutputCharacter(hStdout,' ', ht*wt, origin, addr(numwrote)) == 0: - osError(osLastError()) + raiseOSError(osLastError()) if FillConsoleOutputAttribute(hStdout, scrbuf.wAttributes, ht * wt, scrbuf.dwCursorPosition, addr(numwrote)) == 0: - osError(osLastError()) + raiseOSError(osLastError()) else: stdout.write("\e[2K") setCursorXPos(0) @@ -178,14 +178,14 @@ proc eraseScreen* = var numwrote: DWORD var origin: TCOORD # is inititalized to 0, 0 var hStdout = conHandle - if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: osError(osLastError()) + if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: raiseOSError(osLastError()) if FillConsoleOutputCharacter(hStdout, ' ', scrbuf.dwSize.X*scrbuf.dwSize.Y, origin, addr(numwrote)) == 0: - osError(osLastError()) + raiseOSError(osLastError()) if FillConsoleOutputAttribute(hStdout, scrbuf.wAttributes, scrbuf.dwSize.X * scrbuf.dwSize.Y, origin, addr(numwrote)) == 0: - osError(osLastError()) + raiseOSError(osLastError()) setCursorXPos(0) else: stdout.write("\e[2J") @@ -199,7 +199,7 @@ proc resetAttributes* {.noconv.} = stdout.write("\e[0m") type - TStyle* = enum ## different styles for text output + Style* = enum ## different styles for text output styleBright = 1, ## bright text styleDim, ## dim text styleUnknown, ## unknown @@ -208,6 +208,8 @@ type styleReverse = 7, ## unknown styleHidden ## hidden text +{.deprecated: [TStyle: Style].} + when not defined(windows): var # XXX: These better be thread-local @@ -244,7 +246,7 @@ proc writeStyled*(txt: string, style: set[TStyle] = {styleBright}) = stdout.write("\e[" & $ord(gBG) & 'm') type - TForegroundColor* = enum ## terminal's foreground colors + ForegroundColor* = enum ## terminal's foreground colors fgBlack = 30, ## black fgRed, ## red fgGreen, ## green @@ -254,7 +256,7 @@ type fgCyan, ## cyan fgWhite ## white - TBackgroundColor* = enum ## terminal's background colors + BackgroundColor* = enum ## terminal's background colors bgBlack = 40, ## black bgRed, ## red bgGreen, ## green @@ -264,13 +266,16 @@ type bgCyan, ## cyan bgWhite ## white -proc setForegroundColor*(fg: TForegroundColor, bright=false) = +{.deprecated: [TForegroundColor: ForegroundColor, + TBackgroundColor: BackgroundColor].} + +proc setForegroundColor*(fg: ForegroundColor, bright=false) = ## sets the terminal's foreground color when defined(windows): var old = getAttributes() and not 0x0007 if bright: old = old or FOREGROUND_INTENSITY - const lookup: array [TForegroundColor, int] = [ + const lookup: array [ForegroundColor, int] = [ 0, (FOREGROUND_RED), (FOREGROUND_GREEN), @@ -285,13 +290,13 @@ proc setForegroundColor*(fg: TForegroundColor, bright=false) = if bright: inc(gFG, 60) stdout.write("\e[" & $gFG & 'm') -proc setBackgroundColor*(bg: TBackgroundColor, bright=false) = +proc setBackgroundColor*(bg: BackgroundColor, bright=false) = ## sets the terminal's background color when defined(windows): var old = getAttributes() and not 0x0070 if bright: old = old or BACKGROUND_INTENSITY - const lookup: array [TBackgroundColor, int] = [ + const lookup: array [BackgroundColor, int] = [ 0, (BACKGROUND_RED), (BACKGROUND_GREEN), @@ -306,22 +311,22 @@ proc setBackgroundColor*(bg: TBackgroundColor, bright=false) = if bright: inc(gBG, 60) stdout.write("\e[" & $gBG & 'm') -proc isatty*(f: TFile): bool = +proc isatty*(f: File): bool = ## returns true if `f` is associated with a terminal device. when defined(posix): - proc isatty(fildes: TFileHandle): cint {. + proc isatty(fildes: FileHandle): cint {. importc: "isatty", header: "<unistd.h>".} else: - proc isatty(fildes: TFileHandle): cint {. + proc isatty(fildes: FileHandle): cint {. importc: "_isatty", header: "<io.h>".} - result = isatty(fileHandle(f)) != 0'i32 + result = isatty(getFileHandle(f)) != 0'i32 -proc styledEchoProcessArg(s: string) = write stdout, s -proc styledEchoProcessArg(style: TStyle) = setStyle({style}) -proc styledEchoProcessArg(style: set[TStyle]) = setStyle style -proc styledEchoProcessArg(color: TForegroundColor) = setForegroundColor color -proc styledEchoProcessArg(color: TBackgroundColor) = setBackgroundColor color +proc styledEchoProcessArg(s: string) = write stdout, s +proc styledEchoProcessArg(style: Style) = setStyle({style}) +proc styledEchoProcessArg(style: set[Style]) = setStyle style +proc styledEchoProcessArg(color: ForegroundColor) = setForegroundColor color +proc styledEchoProcessArg(color: BackgroundColor) = setBackgroundColor color macro styledEcho*(m: varargs[expr]): stmt = ## to be documented. diff --git a/lib/pure/times.nim b/lib/pure/times.nim index c156a4479..2c09fcc4c 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2013 Andreas Rumpf # # See the file "copying.txt", included in this @@ -21,9 +21,9 @@ import include "system/inclrtl" type - TMonth* = enum ## represents a month + Month* = enum ## represents a month mJan, mFeb, mMar, mApr, mMay, mJun, mJul, mAug, mSep, mOct, mNov, mDec - TWeekDay* = enum ## represents a weekday + WeekDay* = enum ## represents a weekday dMon, dTue, dWed, dThu, dFri, dSat, dSun var @@ -32,12 +32,12 @@ var when defined(posix) and not defined(JS): type - TTimeImpl {.importc: "time_t", header: "<sys/time.h>".} = int - TTime* = distinct TTimeImpl ## distinct type that represents a time - ## measured as number of seconds since the epoch + TimeImpl {.importc: "time_t", header: "<sys/time.h>".} = int + Time* = distinct TimeImpl ## distinct type that represents a time + ## measured as number of seconds since the epoch - Ttimeval {.importc: "struct timeval", header: "<sys/select.h>", - final, pure.} = object ## struct timeval + Timeval {.importc: "struct timeval", + header: "<sys/select.h>".} = object ## struct timeval tv_sec: int ## Seconds. tv_usec: int ## Microseconds. @@ -45,7 +45,7 @@ when defined(posix) and not defined(JS): # Ok, we could, but I don't want circular dependencies. # And gettimeofday() is not defined in the posix module anyway. Sigh. - proc posix_gettimeofday(tp: var Ttimeval, unused: pointer = nil) {. + proc posix_gettimeofday(tp: var Timeval, unused: pointer = nil) {. importc: "gettimeofday", header: "<sys/time.h>".} elif defined(windows): @@ -53,16 +53,16 @@ elif defined(windows): when defined(vcc): # newest version of Visual C++ defines time_t to be of 64 bits - type TTimeImpl {.importc: "time_t", header: "<time.h>".} = int64 + type TimeImpl {.importc: "time_t", header: "<time.h>".} = int64 else: - type TTimeImpl {.importc: "time_t", header: "<time.h>".} = int32 + type TimeImpl {.importc: "time_t", header: "<time.h>".} = int32 type - TTime* = distinct TTimeImpl + Time* = distinct TimeImpl elif defined(JS): type - TTime* {.final, importc.} = object + Time* {.importc.} = object getDay: proc (): int {.tags: [], raises: [], gcsafe.} getFullYear: proc (): int {.tags: [], raises: [], gcsafe.} getHours: proc (): int {.tags: [], raises: [], gcsafe.} @@ -82,7 +82,7 @@ elif defined(JS): getUTCSeconds: proc (): int {.tags: [], raises: [], gcsafe.} getUTCDay: proc (): int {.tags: [], raises: [], gcsafe.} getYear: proc (): int {.tags: [], raises: [], gcsafe.} - parse: proc (s: cstring): TTime {.tags: [], raises: [], gcsafe.} + parse: proc (s: cstring): Time {.tags: [], raises: [], gcsafe.} setDate: proc (x: int) {.tags: [], raises: [], gcsafe.} setFullYear: proc (x: int) {.tags: [], raises: [], gcsafe.} setHours: proc (x: int) {.tags: [], raises: [], gcsafe.} @@ -103,7 +103,7 @@ elif defined(JS): toLocaleString: proc (): cstring {.tags: [], raises: [], gcsafe.} type - TTimeInfo* = object of RootObj ## represents a time in different parts + TimeInfo* = object of RootObj ## represents a time in different parts second*: range[0..61] ## The number of seconds after the minute, ## normally in the range 0 to 59, but can ## be up to 61 to allow for leap seconds. @@ -112,9 +112,9 @@ type hour*: range[0..23] ## The number of hours past midnight, ## in the range 0 to 23. monthday*: range[1..31] ## The day of the month, in the range 1 to 31. - month*: TMonth ## The current month. + month*: Month ## The current month. year*: range[-10_000..10_000] ## The current year. - weekday*: TWeekDay ## The current day of the week. + weekday*: WeekDay ## The current day of the week. yearday*: range[0..365] ## The number of days since January 1, ## in the range 0 to 365. ## Always 0 if the target is JS. @@ -127,7 +127,7 @@ type ## I make some assumptions about the data in here. Either ## everything should be positive or everything negative. Zero is ## fine too. Mixed signs will lead to unexpected results. - TTimeInterval* {.pure.} = object ## a time interval + TimeInterval* = object ## a time interval miliseconds*: int ## The number of miliseconds seconds*: int ## The number of seconds minutes*: int ## The number of minutes @@ -136,55 +136,58 @@ type months*: int ## The number of months years*: int ## The number of years -proc getTime*(): TTime {.tags: [TimeEffect], gcsafe.} +{.deprecated: [TMonth: Month, TWeekDay: WeekDay, TTime: Time, TTimeval: Timeval, + TTimeInterval: TimeInterval, TTimeInfo: TimeInfo].} + +proc getTime*(): Time {.tags: [TimeEffect], gcsafe.} ## gets the current calendar time as a UNIX epoch value (number of seconds ## elapsed since 1970) with integer precission. Use epochTime for higher ## resolution. -proc getLocalTime*(t: TTime): TTimeInfo {.tags: [TimeEffect], raises: [], gcsafe.} +proc getLocalTime*(t: Time): TimeInfo {.tags: [TimeEffect], raises: [], gcsafe.} ## converts the calendar time `t` to broken-time representation, ## expressed relative to the user's specified time zone. -proc getGMTime*(t: TTime): TTimeInfo {.tags: [TimeEffect], raises: [], gcsafe.} +proc getGMTime*(t: Time): TimeInfo {.tags: [TimeEffect], raises: [], gcsafe.} ## converts the calendar time `t` to broken-down time representation, ## expressed in Coordinated Universal Time (UTC). -proc timeInfoToTime*(timeInfo: TTimeInfo): TTime {.tags: [], gcsafe.} +proc timeInfoToTime*(timeInfo: TimeInfo): Time {.tags: [], gcsafe.} ## converts a broken-down time structure to ## calendar time representation. The function ignores the specified ## contents of the structure members `weekday` and `yearday` and recomputes ## them from the other information in the broken-down time structure. -proc fromSeconds*(since1970: float): TTime {.tags: [], raises: [], gcsafe.} +proc fromSeconds*(since1970: float): Time {.tags: [], raises: [], gcsafe.} ## Takes a float which contains the number of seconds since the unix epoch and ## returns a time object. -proc fromSeconds*(since1970: int64): TTime {.tags: [], raises: [], gcsafe.} = +proc fromSeconds*(since1970: int64): Time {.tags: [], raises: [], gcsafe.} = ## Takes an int which contains the number of seconds since the unix epoch and ## returns a time object. fromSeconds(float(since1970)) -proc toSeconds*(time: TTime): float {.tags: [], raises: [], gcsafe.} +proc toSeconds*(time: Time): float {.tags: [], raises: [], gcsafe.} ## Returns the time in seconds since the unix epoch. -proc `$` *(timeInfo: TTimeInfo): string {.tags: [], raises: [], gcsafe.} - ## converts a `TTimeInfo` object to a string representation. -proc `$` *(time: TTime): string {.tags: [], raises: [], gcsafe.} +proc `$` *(timeInfo: TimeInfo): string {.tags: [], raises: [], gcsafe.} + ## converts a `TimeInfo` object to a string representation. +proc `$` *(time: Time): string {.tags: [], raises: [], gcsafe.} ## converts a calendar time to a string representation. -proc `-`*(a, b: TTime): int64 {. +proc `-`*(a, b: Time): int64 {. rtl, extern: "ntDiffTime", tags: [], raises: [].} ## computes the difference of two calendar times. Result is in seconds. -proc `<`*(a, b: TTime): bool {. +proc `<`*(a, b: Time): bool {. rtl, extern: "ntLtTime", tags: [], raises: [].} = ## returns true iff ``a < b``, that is iff a happened before b. result = a - b < 0 -proc `<=` * (a, b: TTime): bool {. +proc `<=` * (a, b: Time): bool {. rtl, extern: "ntLeTime", tags: [], raises: [].}= ## returns true iff ``a <= b``. result = a - b <= 0 -proc `==`*(a, b: TTime): bool {. +proc `==`*(a, b: Time): bool {. rtl, extern: "ntEqTime", tags: [], raises: [].} = ## returns true if ``a == b``, that is if both times represent the same value result = a - b == 0 @@ -203,8 +206,8 @@ proc getStartMilsecs*(): int {.deprecated, tags: [TimeEffect], gcsafe.} ## version 0.8.10.** Use ``epochTime`` or ``cpuTime`` instead. proc initInterval*(miliseconds, seconds, minutes, hours, days, months, - years: int = 0): TTimeInterval = - ## creates a new ``TTimeInterval``. + years: int = 0): TimeInterval = + ## creates a new ``TimeInterval``. result.miliseconds = miliseconds result.seconds = seconds result.minutes = minutes @@ -234,7 +237,7 @@ proc getDaysInMonth*(month: TMonth, year: int): int = of mApr, mJun, mSep, mNov: result = 30 else: result = 31 -proc toSeconds(a: TTimeInfo, interval: TTimeInterval): float = +proc toSeconds(a: TimeInfo, interval: TimeInterval): float = ## Calculates how many seconds the interval is worth by adding up ## all the fields @@ -257,7 +260,7 @@ proc toSeconds(a: TTimeInfo, interval: TTimeInterval): float = result += float(newinterv.seconds) result += newinterv.miliseconds / 1000 -proc `+`*(a: TTimeInfo, interval: TTimeInterval): TTimeInfo = +proc `+`*(a: TimeInfo, interval: TimeInterval): TimeInfo = ## adds ``interval`` time. ## ## **Note:** This has been only briefly tested and it may not be @@ -269,7 +272,7 @@ proc `+`*(a: TTimeInfo, interval: TTimeInterval): TTimeInfo = else: result = getLocalTime(fromSeconds(t + secs)) -proc `-`*(a: TTimeInfo, interval: TTimeInterval): TTimeInfo = +proc `-`*(a: TimeInfo, interval: TimeInterval): TimeInfo = ## subtracts ``interval`` time. ## ## **Note:** This has been only briefly tested, it is inaccurate especially @@ -314,38 +317,36 @@ when not defined(JS): yearday {.importc: "tm_yday".}, isdst {.importc: "tm_isdst".}: cint - PTimeInfo = ptr StructTM - PTime = ptr TTime - - TClock {.importc: "clock_t".} = distinct int + TimeInfoPtr = ptr StructTM + Clock {.importc: "clock_t".} = distinct int - proc localtime(timer: PTime): PTimeInfo {. + proc localtime(timer: ptr Time): TimeInfoPtr {. importc: "localtime", header: "<time.h>", tags: [].} - proc gmtime(timer: PTime): PTimeInfo {. + proc gmtime(timer: ptr Time): TimeInfoPtr {. importc: "gmtime", header: "<time.h>", tags: [].} - proc timec(timer: PTime): TTime {. + proc timec(timer: ptr Time): Time {. importc: "time", header: "<time.h>", tags: [].} - proc mktime(t: StructTM): TTime {. + proc mktime(t: StructTM): Time {. importc: "mktime", header: "<time.h>", tags: [].} proc asctime(tblock: StructTM): cstring {. importc: "asctime", header: "<time.h>", tags: [].} - proc ctime(time: PTime): cstring {. + proc ctime(time: ptr Time): cstring {. importc: "ctime", header: "<time.h>", tags: [].} # strftime(s: CString, maxsize: int, fmt: CString, t: tm): int {. # importc: "strftime", header: "<time.h>".} - proc clock(): TClock {.importc: "clock", header: "<time.h>", tags: [TimeEffect].} - proc difftime(a, b: TTime): float {.importc: "difftime", header: "<time.h>", + proc getClock(): Clock {.importc: "clock", header: "<time.h>", tags: [TimeEffect].} + proc difftime(a, b: Time): float {.importc: "difftime", header: "<time.h>", tags: [].} var clocksPerSec {.importc: "CLOCKS_PER_SEC", nodecl.}: int # our own procs on top of that: - proc tmToTimeInfo(tm: StructTM, local: bool): TTimeInfo = + proc tmToTimeInfo(tm: StructTM, local: bool): TimeInfo = const - weekDays: array [0..6, TWeekDay] = [ + weekDays: array [0..6, WeekDay] = [ dSun, dMon, dTue, dWed, dThu, dFri, dSat] - TTimeInfo(second: int(tm.second), + TimeInfo(second: int(tm.second), minute: int(tm.minute), hour: int(tm.hour), monthday: int(tm.monthday), @@ -364,9 +365,9 @@ when not defined(JS): timezone: if local: getTimezone() else: 0 ) - proc timeInfoToTM(t: TTimeInfo): StructTM = + proc timeInfoToTM(t: TimeInfo): StructTM = const - weekDays: array [TWeekDay, int8] = [1'i8,2'i8,3'i8,4'i8,5'i8,6'i8,0'i8] + weekDays: array [WeekDay, int8] = [1'i8,2'i8,3'i8,4'i8,5'i8,6'i8,0'i8] result.second = t.second result.minute = t.minute result.hour = t.hour @@ -378,36 +379,36 @@ when not defined(JS): result.isdst = if t.isDST: 1 else: 0 when not defined(useNimRtl): - proc `-` (a, b: TTime): int64 = + proc `-` (a, b: Time): int64 = return toBiggestInt(difftime(a, b)) proc getStartMilsecs(): int = - #echo "clocks per sec: ", clocksPerSec, "clock: ", int(clock()) - #return clock() div (clocksPerSec div 1000) + #echo "clocks per sec: ", clocksPerSec, "clock: ", int(getClock()) + #return getClock() div (clocksPerSec div 1000) when defined(macosx): - result = toInt(toFloat(int(clock())) / (toFloat(clocksPerSec) / 1000.0)) + result = toInt(toFloat(int(getClock())) / (toFloat(clocksPerSec) / 1000.0)) else: - result = int(clock()) div (clocksPerSec div 1000) + result = int(getClock()) div (clocksPerSec div 1000) when false: - var a: Ttimeval + var a: Timeval posix_gettimeofday(a) result = a.tv_sec * 1000'i64 + a.tv_usec div 1000'i64 #echo "result: ", result - proc getTime(): TTime = return timec(nil) - proc getLocalTime(t: TTime): TTimeInfo = + proc getTime(): Time = return timec(nil) + proc getLocalTime(t: Time): TimeInfo = var a = t result = tmToTimeInfo(localtime(addr(a))[], true) # copying is needed anyway to provide reentrancity; thus # the conversion is not expensive - proc getGMTime(t: TTime): TTimeInfo = + proc getGMTime(t: Time): TimeInfo = var a = t result = tmToTimeInfo(gmtime(addr(a))[], false) # copying is needed anyway to provide reentrancity; thus # the conversion is not expensive - proc timeInfoToTime(timeInfo: TTimeInfo): TTime = + proc timeInfoToTime(timeInfo: TimeInfo): Time = var cTimeInfo = timeInfo # for C++ we have to make a copy, # because the header of mktime is broken in my version of libc return mktime(timeInfoToTM(cTimeInfo)) @@ -419,12 +420,12 @@ when not defined(JS): add(result, p[i]) inc(i) - proc `$`(timeInfo: TTimeInfo): string = + proc `$`(timeInfo: TimeInfo): string = # BUGFIX: asctime returns a newline at the end! var p = asctime(timeInfoToTM(timeInfo)) result = toStringTillNL(p) - proc `$`(time: TTime): string = + proc `$`(time: Time): string = # BUGFIX: ctime returns a newline at the end! var a = time return toStringTillNL(ctime(addr(a))) @@ -433,13 +434,13 @@ when not defined(JS): epochDiff = 116444736000000000'i64 rateDiff = 10000000'i64 # 100 nsecs - proc unixTimeToWinTime*(t: TTime): int64 = - ## converts a UNIX `TTime` (``time_t``) to a Windows file time + proc unixTimeToWinTime*(t: Time): int64 = + ## converts a UNIX `Time` (``time_t``) to a Windows file time result = int64(t) * rateDiff + epochDiff - proc winTimeToUnixTime*(t: int64): TTime = - ## converts a Windows time to a UNIX `TTime` (``time_t``) - result = TTime((t - epochDiff) div rateDiff) + proc winTimeToUnixTime*(t: int64): Time = + ## converts a Windows time to a UNIX `Time` (``time_t``) + result = Time((t - epochDiff) div rateDiff) proc getTzname(): tuple[nonDST, DST: string] = return ($tzname[0], $tzname[1]) @@ -447,9 +448,9 @@ when not defined(JS): proc getTimezone(): int = return timezone - proc fromSeconds(since1970: float): TTime = TTime(since1970) + proc fromSeconds(since1970: float): Time = Time(since1970) - proc toSeconds(time: TTime): float = float(time) + proc toSeconds(time: Time): float = float(time) when not defined(useNimRtl): proc epochTime(): float = @@ -468,15 +469,15 @@ when not defined(JS): {.error: "unknown OS".} proc cpuTime(): float = - result = toFloat(int(clock())) / toFloat(clocksPerSec) + result = toFloat(int(getClock())) / toFloat(clocksPerSec) elif defined(JS): - proc newDate(): TTime {.importc: "new Date".} - proc internGetTime(): TTime {.importc: "new Date", tags: [].} + proc newDate(): Time {.importc: "new Date".} + proc internGetTime(): Time {.importc: "new Date", tags: [].} - proc newDate(value: float): TTime {.importc: "new Date".} - proc newDate(value: string): TTime {.importc: "new Date".} - proc getTime(): TTime = + proc newDate(value: float): Time {.importc: "new Date".} + proc newDate(value: string): Time {.importc: "new Date".} + proc getTime(): Time = # Warning: This is something different in JS. return newDate() @@ -484,7 +485,7 @@ elif defined(JS): weekDays: array [0..6, TWeekDay] = [ dSun, dMon, dTue, dWed, dThu, dFri, dSat] - proc getLocalTime(t: TTime): TTimeInfo = + proc getLocalTime(t: Time): TimeInfo = result.second = t.getSeconds() result.minute = t.getMinutes() result.hour = t.getHours() @@ -494,7 +495,7 @@ elif defined(JS): result.weekday = weekDays[t.getDay()] result.yearday = 0 - proc getGMTime(t: TTime): TTimeInfo = + proc getGMTime(t: Time): TimeInfo = result.second = t.getUTCSeconds() result.minute = t.getUTCMinutes() result.hour = t.getUTCHours() @@ -504,7 +505,7 @@ elif defined(JS): result.weekday = weekDays[t.getUTCDay()] result.yearday = 0 - proc timeInfoToTime*(timeInfo: TTimeInfo): TTime = + proc timeInfoToTime*(timeInfo: TimeInfo): Time = result = internGetTime() result.setSeconds(timeInfo.second) result.setMinutes(timeInfo.minute) @@ -513,10 +514,10 @@ elif defined(JS): result.setFullYear(timeInfo.year) result.setDate(timeInfo.monthday) - proc `$`(timeInfo: TTimeInfo): string = return $(TimeInfoToTIme(timeInfo)) - proc `$`(time: TTime): string = return $time.toLocaleString() + proc `$`(timeInfo: TimeInfo): string = return $(TimeInfoToTIme(timeInfo)) + proc `$`(time: Time): string = return $time.toLocaleString() - proc `-` (a, b: TTime): int64 = + proc `-` (a, b: Time): int64 = return a.getTime() - b.getTime() var @@ -526,11 +527,11 @@ elif defined(JS): ## get the miliseconds from the start of the program return int(getTime() - startMilsecs) - proc valueOf(time: TTime): float {.importcpp: "getTime", tags:[]} + proc valueOf(time: Time): float {.importcpp: "getTime", tags:[]} - proc fromSeconds(since1970: float): TTime = result = newDate(since1970) + proc fromSeconds(since1970: float): Time = result = newDate(since1970) - proc toSeconds(time: TTime): float = result = time.valueOf() / 1000 + proc toSeconds(time: Time): float = result = time.valueOf() / 1000 proc getTimezone(): int = result = newDate().getTimezoneOffset() @@ -546,20 +547,20 @@ proc getClockStr*(): string {.rtl, extern: "nt$1", tags: [TimeEffect].} = result = intToStr(ti.hour, 2) & ':' & intToStr(ti.minute, 2) & ':' & intToStr(ti.second, 2) -proc `$`*(day: TWeekDay): string = - ## stingify operator for ``TWeekDay``. - const lookup: array[TWeekDay, string] = ["Monday", "Tuesday", "Wednesday", +proc `$`*(day: WeekDay): string = + ## stingify operator for ``WeekDay``. + const lookup: array[WeekDay, string] = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] return lookup[day] -proc `$`*(m: TMonth): string = +proc `$`*(m: Month): string = ## stingify operator for ``TMonth``. - const lookup: array[TMonth, string] = ["January", "February", "March", + const lookup: array[Month, string] = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"] return lookup[m] -proc format_token(info: TTimeInfo, token: string, buf: var string) = +proc formatToken(info: TimeInfo, 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 @@ -672,7 +673,7 @@ proc format_token(info: TTimeInfo, token: string, buf: var string) = raise newException(ValueError, "Invalid format string: " & token) -proc format*(info: TTimeInfo, f: string): string = +proc format*(info: TimeInfo, f: string): string = ## This function formats `info` as specified by `f`. The following format ## specifiers are available: ## @@ -718,7 +719,7 @@ proc format*(info: TTimeInfo, f: string): string = while true: case f[i] of ' ', '-', '/', ':', '\'', '\0', '(', ')', '[', ']', ',': - format_token(info, currentF, result) + formatToken(info, currentF, result) currentF = "" if f[i] == '\0': break @@ -735,7 +736,7 @@ proc format*(info: TTimeInfo, f: string): string = if currentF.len < 1 or currentF[high(currentF)] == f[i]: currentF.add(f[i]) else: - format_token(info, currentF, result) + formatToken(info, currentF, result) dec(i) # Move position back to re-process the character separately. currentF = "" @@ -764,7 +765,7 @@ when isMainModule: " ss t tt y yy yyy yyyy yyyyy z zz zzz ZZZ") == "27 27 Mon Monday 4 04 16 16 6 06 1 01 Jan January 29 29 P PM 5 75 975 1975 01975 0 00 00:00 UTC" - when not defined(JS) and sizeof(TTime) == 8: + when not defined(JS) and sizeof(Time) == 8: var t3 = getGMTime(fromSeconds(889067643645)) # Fri 7 Jun 19:20:45 BST 30143 assert t3.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") == diff --git a/lib/pure/typetraits.nim b/lib/pure/typetraits.nim index 3203ee699..1180b98f0 100644 --- a/lib/pure/typetraits.nim +++ b/lib/pure/typetraits.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Nimrod Contributors # # See the file "copying.txt", included in this diff --git a/lib/pure/unicode.nim b/lib/pure/unicode.nim index 6e73eea3f..c2eb001f6 100644 --- a/lib/pure/unicode.nim +++ b/lib/pure/unicode.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -14,13 +14,15 @@ include "system/inclrtl" type - IRune = int # underlying type of TRune - TRune* = distinct IRune ## type that can hold any Unicode character - TRune16* = distinct int16 ## 16 bit Unicode character + RuneImpl = int # underlying type of Rune + Rune* = distinct RuneImpl ## type that can hold any Unicode character + Rune16* = distinct int16 ## 16 bit Unicode character + +{.deprecated: [TRune: Rune, TRune16: Rune16].} -proc `<=%`*(a, b: TRune): bool = return int(a) <=% int(b) -proc `<%`*(a, b: TRune): bool = return int(a) <% int(b) -proc `==`*(a, b: TRune): bool = return int(a) == int(b) +proc `<=%`*(a, b: Rune): bool = return int(a) <=% int(b) +proc `<%`*(a, b: Rune): bool = return int(a) <% int(b) +proc `==`*(a, b: Rune): bool = return int(a) == int(b) template ones(n: expr): expr = ((1 shl n)-1) @@ -52,17 +54,17 @@ template fastRuneAt*(s: string, i: int, result: expr, doInc = true) = ## `i` is incremented by the number of bytes that have been processed. bind ones if ord(s[i]) <=% 127: - result = TRune(ord(s[i])) + result = Rune(ord(s[i])) when doInc: inc(i) elif ord(s[i]) shr 5 == 0b110: # assert(ord(s[i+1]) shr 6 == 0b10) - result = TRune((ord(s[i]) and (ones(5))) shl 6 or - (ord(s[i+1]) and ones(6))) + result = Rune((ord(s[i]) and (ones(5))) shl 6 or + (ord(s[i+1]) and ones(6))) when doInc: inc(i, 2) elif ord(s[i]) shr 4 == 0b1110: # assert(ord(s[i+1]) shr 6 == 0b10) # assert(ord(s[i+2]) shr 6 == 0b10) - result = TRune((ord(s[i]) and ones(4)) shl 12 or + result = Rune((ord(s[i]) and ones(4)) shl 12 or (ord(s[i+1]) and ones(6)) shl 6 or (ord(s[i+2]) and ones(6))) when doInc: inc(i, 3) @@ -70,7 +72,7 @@ template fastRuneAt*(s: string, i: int, result: expr, doInc = true) = # assert(ord(s[i+1]) shr 6 == 0b10) # assert(ord(s[i+2]) shr 6 == 0b10) # assert(ord(s[i+3]) shr 6 == 0b10) - result = TRune((ord(s[i]) and ones(3)) shl 18 or + result = Rune((ord(s[i]) and ones(3)) shl 18 or (ord(s[i+1]) and ones(6)) shl 12 or (ord(s[i+2]) and ones(6)) shl 6 or (ord(s[i+3]) and ones(6))) @@ -80,7 +82,7 @@ template fastRuneAt*(s: string, i: int, result: expr, doInc = true) = # assert(ord(s[i+2]) shr 6 == 0b10) # assert(ord(s[i+3]) shr 6 == 0b10) # assert(ord(s[i+4]) shr 6 == 0b10) - result = TRune((ord(s[i]) and ones(2)) shl 24 or + result = Rune((ord(s[i]) and ones(2)) shl 24 or (ord(s[i+1]) and ones(6)) shl 18 or (ord(s[i+2]) and ones(6)) shl 12 or (ord(s[i+3]) and ones(6)) shl 6 or @@ -92,7 +94,7 @@ template fastRuneAt*(s: string, i: int, result: expr, doInc = true) = # assert(ord(s[i+3]) shr 6 == 0b10) # assert(ord(s[i+4]) shr 6 == 0b10) # assert(ord(s[i+5]) shr 6 == 0b10) - result = TRune((ord(s[i]) and ones(1)) shl 30 or + result = Rune((ord(s[i]) and ones(1)) shl 30 or (ord(s[i+1]) and ones(6)) shl 24 or (ord(s[i+2]) and ones(6)) shl 18 or (ord(s[i+3]) and ones(6)) shl 12 or @@ -100,16 +102,16 @@ template fastRuneAt*(s: string, i: int, result: expr, doInc = true) = (ord(s[i+5]) and ones(6))) when doInc: inc(i, 6) else: - result = TRune(ord(s[i])) + result = Rune(ord(s[i])) when doInc: inc(i) -proc runeAt*(s: string, i: int): TRune = +proc runeAt*(s: string, i: int): Rune = ## returns the unicode character in `s` at byte index `i` fastRuneAt(s, i, result, false) -proc toUTF8*(c: TRune): string {.rtl, extern: "nuc$1".} = +proc toUTF8*(c: Rune): string {.rtl, extern: "nuc$1".} = ## converts a rune into its UTF8 representation - var i = IRune(c) + var i = RuneImpl(c) if i <=% 127: result = newString(1) result[0] = chr(i) @@ -132,11 +134,11 @@ proc toUTF8*(c: TRune): string {.rtl, extern: "nuc$1".} = result = newString(1) result[0] = chr(i) -proc `$`*(rune: TRune): string = +proc `$`*(rune: Rune): string = ## converts a rune to a string rune.toUTF8 -proc `$`*(runes: seq[TRune]): string = +proc `$`*(runes: seq[Rune]): string = ## converts a sequence of runes to a string result = "" for rune in runes: result.add(rune.toUTF8) @@ -1100,7 +1102,7 @@ const 0x01f1, 501, # 0x01f3, 499] # -proc binarySearch(c: IRune, tab: openArray[IRune], len, stride: int): int = +proc binarySearch(c: RuneImpl, tab: openArray[RuneImpl], len, stride: int): int = var n = len var t = 0 while n > 1: @@ -1115,41 +1117,41 @@ proc binarySearch(c: IRune, tab: openArray[IRune], len, stride: int): int = return t return -1 -proc toLower*(c: TRune): TRune {.rtl, extern: "nuc$1", procvar.} = +proc toLower*(c: Rune): Rune {.rtl, extern: "nuc$1", procvar.} = ## Converts `c` into lower case. This works for any Unicode character. ## If possible, prefer `toLower` over `toUpper`. - var c = IRune(c) + var c = RuneImpl(c) var p = binarySearch(c, tolowerRanges, len(tolowerRanges) div 3, 3) if p >= 0 and c >= tolowerRanges[p] and c <= tolowerRanges[p+1]: - return TRune(c + tolowerRanges[p+2] - 500) + return Rune(c + tolowerRanges[p+2] - 500) p = binarySearch(c, tolowerSinglets, len(tolowerSinglets) div 2, 2) if p >= 0 and c == tolowerSinglets[p]: - return TRune(c + tolowerSinglets[p+1] - 500) - return TRune(c) + return Rune(c + tolowerSinglets[p+1] - 500) + return Rune(c) -proc toUpper*(c: TRune): TRune {.rtl, extern: "nuc$1", procvar.} = +proc toUpper*(c: Rune): Rune {.rtl, extern: "nuc$1", procvar.} = ## Converts `c` into upper case. This works for any Unicode character. ## If possible, prefer `toLower` over `toUpper`. - var c = IRune(c) + var c = RuneImpl(c) var p = binarySearch(c, toupperRanges, len(toupperRanges) div 3, 3) if p >= 0 and c >= toupperRanges[p] and c <= toupperRanges[p+1]: - return TRune(c + toupperRanges[p+2] - 500) + return Rune(c + toupperRanges[p+2] - 500) p = binarySearch(c, toupperSinglets, len(toupperSinglets) div 2, 2) if p >= 0 and c == toupperSinglets[p]: - return TRune(c + toupperSinglets[p+1] - 500) - return TRune(c) + return Rune(c + toupperSinglets[p+1] - 500) + return Rune(c) -proc toTitle*(c: TRune): TRune {.rtl, extern: "nuc$1", procvar.} = - var c = IRune(c) +proc toTitle*(c: Rune): Rune {.rtl, extern: "nuc$1", procvar.} = + var c = RuneImpl(c) var p = binarySearch(c, toTitleSinglets, len(toTitleSinglets) div 2, 2) if p >= 0 and c == toTitleSinglets[p]: - return TRune(c + toTitleSinglets[p+1] - 500) - return TRune(c) + return Rune(c + toTitleSinglets[p+1] - 500) + return Rune(c) -proc isLower*(c: TRune): bool {.rtl, extern: "nuc$1", procvar.} = +proc isLower*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} = ## returns true iff `c` is a lower case Unicode character ## If possible, prefer `isLower` over `isUpper`. - var c = IRune(c) + var c = RuneImpl(c) # Note: toUpperRanges is correct here! var p = binarySearch(c, toupperRanges, len(toupperRanges) div 3, 3) if p >= 0 and c >= toupperRanges[p] and c <= toupperRanges[p+1]: @@ -1158,10 +1160,10 @@ proc isLower*(c: TRune): bool {.rtl, extern: "nuc$1", procvar.} = if p >= 0 and c == toupperSinglets[p]: return true -proc isUpper*(c: TRune): bool {.rtl, extern: "nuc$1", procvar.} = +proc isUpper*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} = ## returns true iff `c` is a upper case Unicode character ## If possible, prefer `isLower` over `isUpper`. - var c = IRune(c) + var c = RuneImpl(c) # Note: toLowerRanges is correct here! var p = binarySearch(c, tolowerRanges, len(tolowerRanges) div 3, 3) if p >= 0 and c >= tolowerRanges[p] and c <= tolowerRanges[p+1]: @@ -1170,11 +1172,11 @@ proc isUpper*(c: TRune): bool {.rtl, extern: "nuc$1", procvar.} = if p >= 0 and c == tolowerSinglets[p]: return true -proc isAlpha*(c: TRune): bool {.rtl, extern: "nuc$1", procvar.} = +proc isAlpha*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} = ## returns true iff `c` is an *alpha* Unicode character (i.e. a letter) if isUpper(c) or isLower(c): return true - var c = IRune(c) + var c = RuneImpl(c) var p = binarySearch(c, alphaRanges, len(alphaRanges) div 2, 2) if p >= 0 and c >= alphaRanges[p] and c <= alphaRanges[p+1]: return true @@ -1182,21 +1184,21 @@ proc isAlpha*(c: TRune): bool {.rtl, extern: "nuc$1", procvar.} = if p >= 0 and c == alphaSinglets[p]: return true -proc isTitle*(c: TRune): bool {.rtl, extern: "nuc$1", procvar.} = +proc isTitle*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} = return isUpper(c) and isLower(c) -proc isWhiteSpace*(c: TRune): bool {.rtl, extern: "nuc$1", procvar.} = +proc isWhiteSpace*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} = ## returns true iff `c` is a Unicode whitespace character - var c = IRune(c) + var c = RuneImpl(c) var p = binarySearch(c, spaceRanges, len(spaceRanges) div 2, 2) if p >= 0 and c >= spaceRanges[p] and c <= spaceRanges[p+1]: return true -iterator runes*(s: string): TRune = +iterator runes*(s: string): Rune = ## iterates over any unicode character of the string `s`. var i = 0 - result: TRune + result: Rune while i < len(s): fastRuneAt(s, i, result, true) yield result @@ -1209,12 +1211,12 @@ proc cmpRunesIgnoreCase*(a, b: string): int {.rtl, extern: "nuc$1", procvar.} = ## | > 0 iff a > b var i = 0 var j = 0 - var ar, br: TRune + var ar, br: Rune while i < a.len and j < b.len: # slow path: fastRuneAt(a, i, ar) fastRuneAt(b, j, br) - result = IRune(toLower(ar)) - IRune(toLower(br)) + result = RuneImpl(toLower(ar)) - RuneImpl(toLower(br)) if result != 0: return result = a.len - b.len diff --git a/lib/pure/unidecode/unidecode.nim b/lib/pure/unidecode/unidecode.nim index 1d36d11b5..798eef5d0 100644 --- a/lib/pure/unidecode/unidecode.nim +++ b/lib/pure/unidecode/unidecode.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -55,7 +55,7 @@ proc unidecode*(s: string): string = ## ## Example: ## - ## ..code-block:: nimrod + ## ..code-block:: nim ## ## unidecode("\x53\x17\x4E\xB0") ## diff --git a/lib/pure/unittest.nim b/lib/pure/unittest.nim index 7cc95f0ad..f26d8c3e6 100644 --- a/lib/pure/unittest.nim +++ b/lib/pure/unittest.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Nimrod Contributors # # See the file "copying.txt", included in this @@ -26,16 +26,19 @@ when not defined(ECMAScript): import terminal type - TTestStatus* = enum OK, FAILED - TOutputLevel* = enum PRINT_ALL, PRINT_FAILURES, PRINT_NONE + TestStatus* = enum OK, FAILED + OutputLevel* = enum PRINT_ALL, PRINT_FAILURES, PRINT_NONE + +{.deprecated: [TTestStatus: TestStatus, TOutputLevel: OutputLevel]} var - # XXX: These better be thread-local - AbortOnError*: bool - OutputLevel*: TOutputLevel - ColorOutput*: bool + abortOnError* {.threadvar.}: bool + outputLevel* {.threadvar.}: OutputLevel + colorOutput* {.threadvar.}: bool - checkpoints: seq[string] = @[] + checkpoints {.threadvar.}: seq[string] + +checkpoints = @[] template TestSetupIMPL*: stmt {.immediate, dirty.} = discard template TestTeardownIMPL*: stmt {.immediate, dirty.} = discard @@ -53,7 +56,7 @@ template suite*(name: expr, body: stmt): stmt {.immediate, dirty.} = body -proc testDone(name: string, s: TTestStatus) = +proc testDone(name: string, s: TestStatus) = if s == FAILED: program_result += 1 @@ -192,15 +195,15 @@ when declared(stdout): ## Reading settings var envOutLvl = os.getEnv("NIMTEST_OUTPUT_LVL").string - AbortOnError = existsEnv("NIMTEST_ABORT_ON_ERROR") - ColorOutput = not existsEnv("NIMTEST_NO_COLOR") + abortOnError = existsEnv("NIMTEST_ABORT_ON_ERROR") + colorOutput = not existsEnv("NIMTEST_NO_COLOR") else: var envOutLvl = "" # TODO - ColorOutput = false + colorOutput = false if envOutLvl.len > 0: - for opt in countup(low(TOutputLevel), high(TOutputLevel)): + for opt in countup(low(OutputLevel), high(OutputLevel)): if $opt == envOutLvl: - OutputLevel = opt + outputLevel = opt break diff --git a/lib/pure/uri.nim b/lib/pure/uri.nim index 7ec823033..ed1059cc2 100644 --- a/lib/pure/uri.nim +++ b/lib/pure/uri.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2014 Dominik Picheta # # See the file "copying.txt", included in this @@ -11,12 +11,14 @@ import strutils, parseutils type - TUrl* = distinct string + Url* = distinct string - TUri* = object + Uri* = object scheme*, username*, password*: string hostname*, port*, path*, query*, anchor*: string +{.deprecated: [TUrl: Url, TUri: Uri].} + proc `$`*(url: TUrl): string {.deprecated.} = ## **Deprecated since 0.9.6**: Use ``TUri`` instead. return string(url) @@ -172,7 +174,7 @@ proc combine*(base: TUri, reference: TUri): TUri = ## ## Examples: ## - ## .. code-block:: nimrod + ## .. code-block:: ## let foo = combine(parseUri("http://example.com/foo/bar"), parseUri("/baz")) ## assert foo.path == "/baz" ## @@ -229,7 +231,7 @@ proc `/`*(x: TUri, path: string): TUri = ## ## Examples: ## - ## .. code-block:: nimrod + ## .. code-block:: ## let foo = parseUri("http://example.com/foo/bar") / parseUri("/baz") ## assert foo.path == "/foo/bar/baz" ## diff --git a/lib/pure/xmldom.nim b/lib/pure/xmldom.nim index d63b6c5dd..afd26a584 100644 --- a/lib/pure/xmldom.nim +++ b/lib/pure/xmldom.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2010 Dominik Picheta # # See the file "copying.txt", included in this @@ -9,7 +9,8 @@ import strutils -## This module implements XML DOM Level 2 Core specification(http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html) +## This module implements XML DOM Level 2 Core +## specification (http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html) #http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html diff --git a/lib/pure/xmldomparser.nim b/lib/pure/xmldomparser.nim index fda46bac0..b92a9600c 100644 --- a/lib/pure/xmldomparser.nim +++ b/lib/pure/xmldomparser.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2010 Dominik Picheta # # See the file "copying.txt", included in this @@ -156,7 +156,7 @@ proc loadXMLFile*(path: string): PDocument = when isMainModule: - var xml = loadXMLFile(r"C:\Users\Dominik\Desktop\Code\Nimrod\xmldom\test.xml") + var xml = loadXMLFile("nim/xmldom/test.xml") #echo(xml.getElementsByTagName("m:test2")[0].namespaceURI) #echo(xml.getElementsByTagName("bla:test")[0].namespaceURI) #echo(xml.getElementsByTagName("test")[0].namespaceURI) diff --git a/lib/pure/xmlparser.nim b/lib/pure/xmlparser.nim index 8b8bb3b03..83bd45e7d 100644 --- a/lib/pure/xmlparser.nim +++ b/lib/pure/xmlparser.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2010 Andreas Rumpf # # See the file "copying.txt", included in this @@ -12,9 +12,11 @@ import streams, parsexml, strtabs, xmltree type - EInvalidXml* = object of EInvalidValue ## exception that is raised - ## for invalid XML - errors*: seq[string] ## all detected parsing errors + XmlError* = object of ValueError ## exception that is raised + ## for invalid XML + errors*: seq[string] ## all detected parsing errors + +{.deprecated: [EInvalidXml: XmlError].} proc raiseInvalidXml(errors: seq[string]) = var e: ref EInvalidXml @@ -23,12 +25,12 @@ proc raiseInvalidXml(errors: seq[string]) = e.errors = errors raise e -proc addNode(father, son: PXmlNode) = +proc addNode(father, son: XmlNode) = if son != nil: add(father, son) -proc parse(x: var TXmlParser, errors: var seq[string]): PXmlNode +proc parse(x: var XmlParser, errors: var seq[string]): XmlNode -proc untilElementEnd(x: var TXmlParser, result: PXmlNode, +proc untilElementEnd(x: var XmlParser, result: XmlNode, errors: var seq[string]) = while true: case x.kind @@ -45,7 +47,7 @@ proc untilElementEnd(x: var TXmlParser, result: PXmlNode, else: result.addNode(parse(x, errors)) -proc parse(x: var TXmlParser, errors: var seq[string]): PXmlNode = +proc parse(x: var XmlParser, errors: var seq[string]): XmlNode = case x.kind of xmlComment: result = newComment(x.charData) @@ -98,11 +100,11 @@ proc parse(x: var TXmlParser, errors: var seq[string]): PXmlNode = next(x) of xmlEof: discard -proc parseXml*(s: PStream, filename: string, - errors: var seq[string]): PXmlNode = +proc parseXml*(s: Stream, filename: string, + errors: var seq[string]): XmlNode = ## parses the XML from stream `s` and returns a ``PXmlNode``. Every ## occured parsing error is added to the `errors` sequence. - var x: TXmlParser + var x: XmlParser open(x, s, filename, {reportComments}) while true: x.next() @@ -118,14 +120,14 @@ proc parseXml*(s: PStream, filename: string, break close(x) -proc parseXml*(s: PStream): PXmlNode = +proc parseXml*(s: Stream): XmlNode = ## parses the XTML from stream `s` and returns a ``PXmlNode``. All parsing ## errors are turned into an ``EInvalidXML`` exception. var errors: seq[string] = @[] result = parseXml(s, "unknown_html_doc", errors) if errors.len > 0: raiseInvalidXMl(errors) -proc loadXml*(path: string, errors: var seq[string]): PXmlNode = +proc loadXml*(path: string, errors: var seq[string]): XmlNode = ## Loads and parses XML from file specified by ``path``, and returns ## a ``PXmlNode``. Every occured parsing error is added to the `errors` ## sequence. @@ -133,7 +135,7 @@ proc loadXml*(path: string, errors: var seq[string]): PXmlNode = if s == nil: raise newException(EIO, "Unable to read file: " & path) result = parseXml(s, path, errors) -proc loadXml*(path: string): PXmlNode = +proc loadXml*(path: string): XmlNode = ## Loads and parses XML from file specified by ``path``, and returns ## a ``PXmlNode``. All parsing errors are turned into an ``EInvalidXML`` ## exception. @@ -148,7 +150,7 @@ when isMainModule: var x = loadXml(paramStr(1), errors) for e in items(errors): echo e - var f: TFile + var f: File if open(f, "xmltest.txt", fmWrite): f.write($x) f.close() diff --git a/lib/pure/xmltree.nim b/lib/pure/xmltree.nim index 7392eb470..6007232c5 100644 --- a/lib/pure/xmltree.nim +++ b/lib/pure/xmltree.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -12,33 +12,36 @@ import macros, strtabs type - PXmlNode* = ref TXmlNode ## an XML tree consists of ``PXmlNode``'s. + XmlNode* = ref TXmlNode ## an XML tree consists of ``PXmlNode``'s. - TXmlNodeKind* = enum ## different kinds of ``PXmlNode``'s + XmlNodeKind* = enum ## different kinds of ``PXmlNode``'s xnText, ## a text element xnElement, ## an element with 0 or more children xnCData, ## a CDATA node xnEntity, ## an entity (like ``&thing;``) xnComment ## an XML comment - PXmlAttributes* = PStringTable ## an alias for a string to string mapping + XmlAttributes* = StringTableRef ## an alias for a string to string mapping - TXmlNode {.pure, final, acyclic.} = object - case k: TXmlNodeKind # private, use the kind() proc to read this field. + XmlNodeObj {.acyclic.} = object + case k: XmlNodeKind # private, use the kind() proc to read this field. of xnText, xnComment, xnCData, xnEntity: fText: string of xnElement: fTag: string - s: seq[PXmlNode] - fAttr: PXmlAttributes + s: seq[XmlNode] + fAttr: XmlAttributes fClientData: int ## for other clients - -proc newXmlNode(kind: TXmlNodeKind): PXmlNode = - ## creates a new ``PXmlNode``. + +{.deprecated: [PXmlNode: XmlNode, TXmlNodeKind: XmlNodeKind, PXmlAttributes: + XmlAttributes, TXmlNode: XmlNodeObj].} + +proc newXmlNode(kind: XmlNodeKind): XmlNode = + ## creates a new ``XmlNode``. new(result) result.k = kind -proc newElement*(tag: string): PXmlNode = +proc newElement*(tag: string): XmlNode = ## creates a new ``PXmlNode`` of kind ``xnText`` with the given `tag`. result = newXmlNode(xnElement) result.fTag = tag @@ -304,10 +307,10 @@ proc findAll*(n: PXmlNode, tag: string, result: var seq[PXmlNode]) = ## Found nodes satisfying the condition will be appended to the `result` ## sequence, which can't be nil or the proc will crash. Usage example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## var - ## html: PXmlNode - ## tags: seq[PXmlNode] = @[] + ## html: XmlNode + ## tags: seq[XmlNode] = @[] ## ## html = buildHtml() ## findAll(html, "img", tags) @@ -326,8 +329,8 @@ proc findAll*(n: PXmlNode, tag: string, result: var seq[PXmlNode]) = proc findAll*(n: PXmlNode, tag: string): seq[PXmlNode] = ## Shortcut version to assign in let blocks. Example: ## - ## .. code-block:: nimrod - ## var html: PXmlNode + ## .. code-block:: + ## var html: XmlNode ## ## html = buildHtml(html) ## for imgTag in html.findAll("img"): |