diff options
Diffstat (limited to 'lib/pure')
48 files changed, 930 insertions, 1545 deletions
diff --git a/lib/pure/actors.nim b/lib/pure/actors.nim index 294c24741..da9037285 100644 --- a/lib/pure/actors.nim +++ b/lib/pure/actors.nim @@ -16,7 +16,7 @@ ## .. code-block:: nim ## ## var -## a: TActorPool[int, void] +## a: ActorPool[int, void] ## createActorPool(a) ## for i in 0 .. < 300: ## a.spawn(i, proc (x: int) {.thread.} = echo x) @@ -30,75 +30,76 @@ from os import sleep type - TTask*[TIn, TOut] = object{.pure, final.} ## a task - when TOut isnot void: - receiver*: ptr TChannel[TOut] ## the receiver channel of the response - action*: proc (x: TIn): TOut {.thread.} ## action to execute; + Task*[In, Out] = object{.pure, final.} ## a task + when Out isnot void: + receiver*: ptr Channel[Out] ## the receiver channel of the response + action*: proc (x: In): Out {.thread.} ## action to execute; ## sometimes useful shutDown*: bool ## set to tell an actor to shut-down - data*: TIn ## the data to process + data*: In ## the data to process - TActor[TIn, TOut] = object{.pure, final.} - i: TChannel[TTask[TIn, TOut]] - t: TThread[ptr TActor[TIn, TOut]] + Actor[In, Out] = object{.pure, final.} + i: Channel[Task[In, Out]] + t: TThread[ptr Actor[In, Out]] - PActor*[TIn, TOut] = ptr TActor[TIn, TOut] ## an actor - -proc spawn*[TIn, TOut](action: proc( - self: PActor[TIn, TOut]){.thread.}): PActor[TIn, TOut] = + PActor*[In, Out] = ptr Actor[In, Out] ## an actor +{.deprecated: [TTask: Task, TActor: Actor].} + +proc spawn*[In, Out](action: proc( + self: PActor[In, Out]){.thread.}): PActor[In, Out] = ## creates an actor; that is a thread with an inbox. The caller MUST call ## ``join`` because that also frees the actor's associated resources. - result = cast[PActor[TIn, TOut]](allocShared0(sizeof(result[]))) + result = cast[PActor[In, Out]](allocShared0(sizeof(result[]))) open(result.i) createThread(result.t, action, result) -proc inbox*[TIn, TOut](self: PActor[TIn, TOut]): ptr TChannel[TIn] = +proc inbox*[In, Out](self: PActor[In, Out]): ptr Channel[In] = ## gets a pointer to the associated inbox of the actor `self`. result = addr(self.i) -proc running*[TIn, TOut](a: PActor[TIn, TOut]): bool = +proc running*[In, Out](a: PActor[In, Out]): bool = ## returns true if the actor `a` is running. result = running(a.t) -proc ready*[TIn, TOut](a: PActor[TIn, TOut]): bool = +proc ready*[In, Out](a: PActor[In, Out]): bool = ## returns true if the actor `a` is ready to process new messages. result = ready(a.i) -proc join*[TIn, TOut](a: PActor[TIn, TOut]) = +proc join*[In, Out](a: PActor[In, Out]) = ## joins an actor. joinThread(a.t) close(a.i) deallocShared(a) -proc recv*[TIn, TOut](a: PActor[TIn, TOut]): TTask[TIn, TOut] = +proc recv*[In, Out](a: PActor[In, Out]): Task[In, Out] = ## receives a task from `a`'s inbox. result = recv(a.i) -proc send*[TIn, TOut, X, Y](receiver: PActor[TIn, TOut], msg: TIn, +proc send*[In, Out, X, Y](receiver: PActor[In, Out], msg: In, sender: PActor[X, Y]) = ## sends a message to `a`'s inbox. - var t: TTask[TIn, TOut] + var t: Task[In, Out] t.receiver = addr(sender.i) shallowCopy(t.data, msg) send(receiver.i, t) -proc send*[TIn, TOut](receiver: PActor[TIn, TOut], msg: TIn, - sender: ptr TChannel[TOut] = nil) = +proc send*[In, Out](receiver: PActor[In, Out], msg: In, + sender: ptr Channel[Out] = nil) = ## sends a message to `receiver`'s inbox. - var t: TTask[TIn, TOut] + var t: Task[In, Out] t.receiver = sender shallowCopy(t.data, msg) send(receiver.i, t) -proc sendShutdown*[TIn, TOut](receiver: PActor[TIn, TOut]) = +proc sendShutdown*[In, Out](receiver: PActor[In, Out]) = ## send a shutdown message to `receiver`. - var t: TTask[TIn, TOut] + var t: Task[In, Out] t.shutdown = true send(receiver.i, t) -proc reply*[TIn, TOut](t: TTask[TIn, TOut], m: TOut) = +proc reply*[In, Out](t: Task[In, Out], m: Out) = ## sends a message to io's output message box. - when TOut is void: + when Out is void: {.error: "you cannot reply to a void outbox".} assert t.receiver != nil send(t.receiver[], m) @@ -107,34 +108,35 @@ proc reply*[TIn, TOut](t: TTask[TIn, TOut], m: TOut) = # ----------------- actor pools ---------------------------------------------- type - TActorPool*[TIn, TOut] = object{.pure, final.} ## an actor pool - actors: seq[PActor[TIn, TOut]] - when TOut isnot void: - outputs: TChannel[TOut] + ActorPool*[In, Out] = object{.pure, final.} ## an actor pool + actors: seq[PActor[In, Out]] + when Out isnot void: + outputs: Channel[Out] +{.deprecated: [TActorPool: ActorPool].} -proc `^`*[T](f: ptr TChannel[T]): T = +proc `^`*[T](f: ptr Channel[T]): T = ## alias for 'recv'. result = recv(f[]) -proc poolWorker[TIn, TOut](self: PActor[TIn, TOut]) {.thread.} = +proc poolWorker[In, Out](self: PActor[In, Out]) {.thread.} = while true: var m = self.recv if m.shutDown: break - when TOut is void: + when Out is void: m.action(m.data) else: send(m.receiver[], m.action(m.data)) #self.reply() -proc createActorPool*[TIn, TOut](a: var TActorPool[TIn, TOut], poolSize = 4) = +proc createActorPool*[In, Out](a: var ActorPool[In, Out], poolSize = 4) = ## creates an actor pool. newSeq(a.actors, poolSize) - when TOut isnot void: + when Out isnot void: open(a.outputs) for i in 0 .. < a.actors.len: - a.actors[i] = spawn(poolWorker[TIn, TOut]) + a.actors[i] = spawn(poolWorker[In, Out]) -proc sync*[TIn, TOut](a: var TActorPool[TIn, TOut], polling=50) = +proc sync*[In, Out](a: var ActorPool[In, Out], polling=50) = ## waits for every actor of `a` to finish with its work. Currently this is ## implemented as polling every `polling` ms and has a slight chance ## of failing since we check for every actor to be in `ready` state and not @@ -157,18 +159,18 @@ proc sync*[TIn, TOut](a: var TActorPool[TIn, TOut], polling=50) = if allReadyCount > 1: break sleep(polling) -proc terminate*[TIn, TOut](a: var TActorPool[TIn, TOut]) = +proc terminate*[In, Out](a: var ActorPool[In, Out]) = ## terminates each actor in the actor pool `a` and frees the ## resources attached to `a`. - var t: TTask[TIn, TOut] + var t: Task[In, Out] t.shutdown = true for i in 0.. <a.actors.len: send(a.actors[i].i, t) for i in 0.. <a.actors.len: join(a.actors[i]) - when TOut isnot void: + when Out isnot void: close(a.outputs) a.actors = nil -proc join*[TIn, TOut](a: var TActorPool[TIn, TOut]) = +proc join*[In, Out](a: var ActorPool[In, Out]) = ## short-cut for `sync` and then `terminate`. sync(a) terminate(a) @@ -202,28 +204,28 @@ template schedule = else: raise newException(DeadThreadError, "cannot send message; thread died") -proc spawn*[TIn, TOut](p: var TActorPool[TIn, TOut], input: TIn, - action: proc (input: TIn): TOut {.thread.} - ): ptr TChannel[TOut] = +proc spawn*[In, Out](p: var ActorPool[In, Out], input: In, + action: proc (input: In): Out {.thread.} + ): ptr Channel[Out] = ## uses the actor pool to run ``action(input)`` concurrently. ## `spawn` is guaranteed to not block. - var t: TTask[TIn, TOut] + var t: Task[In, Out] setupTask() result = addr(p.outputs) t.receiver = result schedule() -proc spawn*[TIn](p: var TActorPool[TIn, void], input: TIn, - action: proc (input: TIn) {.thread.}) = +proc spawn*[In](p: var ActorPool[In, void], input: In, + action: proc (input: In) {.thread.}) = ## uses the actor pool to run ``action(input)`` concurrently. ## `spawn` is guaranteed to not block. - var t: TTask[TIn, void] + var t: Task[In, void] setupTask() schedule() when not defined(testing) and isMainModule: var - a: TActorPool[int, void] + a: ActorPool[int, void] createActorPool(a) for i in 0 .. < 300: a.spawn(i, proc (x: int) {.thread.} = echo x) diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim index 0eafb316a..c9f779018 100644 --- a/lib/pure/algorithm.nim +++ b/lib/pure/algorithm.nim @@ -99,16 +99,13 @@ proc lowerBound*[T](a: openArray[T], key: T, cmp: proc(x,y: T): int {.closure.}) ## arr.insert(4, arr.lowerBound(4)) ## `after running the above arr is `[1,2,3,4,5,6,7,8,9]` result = a.low - var pos = result - var count, step: int - count = a.high - a.low + 1 + var count = a.high - a.low + 1 + var step, pos: int while count != 0: - pos = result step = count div 2 - pos += step + pos = result + step if cmp(a[pos], key) < 0: - pos.inc - result = pos + result = pos + 1 count -= step + 1 else: count = step @@ -331,3 +328,16 @@ proc prevPermutation*[T](x: var openarray[T]): bool {.discardable.} = swap x[i-1], x[j] result = true + +when isMainModule: + # Tests for lowerBound + var arr = @[1,2,3,5,6,7,8,9] + assert arr.lowerBound(0) == 0 + assert arr.lowerBound(4) == 3 + assert arr.lowerBound(5) == 3 + assert arr.lowerBound(10) == 8 + arr = @[1,5,10] + assert arr.lowerBound(4) == 1 + assert arr.lowerBound(5) == 1 + assert arr.lowerBound(6) == 2 + diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index 8010e9ebc..550b82f49 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -323,32 +323,34 @@ proc processTimers(p: PDispatcherBase) = when defined(windows) or defined(nimdoc): import winlean, sets, hashes type - TCompletionKey = Dword + CompletionKey = Dword - TCompletionData* = object - fd*: TAsyncFD # TODO: Rename this. - cb*: proc (fd: TAsyncFD, bytesTransferred: Dword, + CompletionData* = object + fd*: AsyncFD # TODO: Rename this. + cb*: proc (fd: AsyncFD, bytesTransferred: Dword, errcode: OSErrorCode) {.closure,gcsafe.} PDispatcher* = ref object of PDispatcherBase - ioPort: THandle - handles: HashSet[TAsyncFD] + ioPort: Handle + handles: HashSet[AsyncFD] - TCustomOverlapped = object of TOVERLAPPED - data*: TCompletionData + CustomOverlapped = object of TOVERLAPPED + data*: CompletionData - PCustomOverlapped* = ref TCustomOverlapped + PCustomOverlapped* = ref CustomOverlapped - TAsyncFD* = distinct int + AsyncFD* = distinct int + {.deprecated: [TCompletionKey: CompletionKey, TAsyncFD: AsyncFD, + TCustomOverlapped: CustomOverlapped, TCompletionData: CompletionData].} - proc hash(x: TAsyncFD): THash {.borrow.} - proc `==`*(x: TAsyncFD, y: TAsyncFD): bool {.borrow.} + proc hash(x: AsyncFD): Hash {.borrow.} + proc `==`*(x: AsyncFD, y: AsyncFD): bool {.borrow.} proc newDispatcher*(): PDispatcher = ## Creates a new Dispatcher instance. new result result.ioPort = createIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 1) - result.handles = initSet[TAsyncFD]() + result.handles = initSet[AsyncFD]() result.timers = @[] var gDisp{.threadvar.}: PDispatcher ## Global dispatcher @@ -357,15 +359,15 @@ when defined(windows) or defined(nimdoc): if gDisp.isNil: gDisp = newDispatcher() result = gDisp - proc register*(fd: TAsyncFD) = + proc register*(fd: AsyncFD) = ## Registers ``fd`` with the dispatcher. let p = getGlobalDispatcher() - if createIoCompletionPort(fd.THandle, p.ioPort, - cast[TCompletionKey](fd), 1) == 0: + if createIoCompletionPort(fd.Handle, p.ioPort, + cast[CompletionKey](fd), 1) == 0: raiseOSError(osLastError()) p.handles.incl(fd) - proc verifyPresence(fd: TAsyncFD) = + proc verifyPresence(fd: AsyncFD) = ## Ensures that file descriptor has been registered with the dispatcher. let p = getGlobalDispatcher() if fd notin p.handles: @@ -394,7 +396,7 @@ when defined(windows) or defined(nimdoc): # TODO: http://www.serverframework.com/handling-multiple-pending-socket-read-and-write-operations.html if res: # This is useful for ensuring the reliability of the overlapped struct. - assert customOverlapped.data.fd == lpCompletionKey.TAsyncFD + assert customOverlapped.data.fd == lpCompletionKey.AsyncFD customOverlapped.data.cb(customOverlapped.data.fd, lpNumberOfBytesTransferred, OSErrorCode(-1)) @@ -402,7 +404,7 @@ when defined(windows) or defined(nimdoc): else: let errCode = osLastError() if customOverlapped != nil: - assert customOverlapped.data.fd == lpCompletionKey.TAsyncFD + assert customOverlapped.data.fd == lpCompletionKey.AsyncFD customOverlapped.data.cb(customOverlapped.data.fd, lpNumberOfBytesTransferred, errCode) GC_unref(customOverlapped) @@ -480,7 +482,7 @@ when defined(windows) or defined(nimdoc): dwRemoteAddressLength, LocalSockaddr, LocalSockaddrLength, RemoteSockaddr, RemoteSockaddrLength) - proc connect*(socket: TAsyncFD, address: string, port: Port, + proc connect*(socket: AsyncFD, address: string, port: Port, af = AF_INET): Future[void] = ## Connects ``socket`` to server at ``address:port``. ## @@ -506,8 +508,8 @@ when defined(windows) or defined(nimdoc): # http://blogs.msdn.com/b/oldnewthing/archive/2011/02/02/10123392.aspx var ol = PCustomOverlapped() GC_ref(ol) - ol.data = TCompletionData(fd: socket, cb: - proc (fd: TAsyncFD, bytesCount: Dword, errcode: OSErrorCode) = + ol.data = CompletionData(fd: socket, cb: + proc (fd: AsyncFD, bytesCount: Dword, errcode: OSErrorCode) = if not retFuture.finished: if errcode == OSErrorCode(-1): retFuture.complete() @@ -542,7 +544,7 @@ when defined(windows) or defined(nimdoc): retFuture.fail(newException(OSError, osErrorMsg(lastError))) return retFuture - proc recv*(socket: TAsyncFD, size: int, + proc recv*(socket: AsyncFD, size: int, flags = {SocketFlag.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 @@ -570,8 +572,8 @@ when defined(windows) or defined(nimdoc): var flagsio = flags.toOSFlags().Dword var ol = PCustomOverlapped() GC_ref(ol) - ol.data = TCompletionData(fd: socket, cb: - proc (fd: TAsyncFD, bytesCount: Dword, errcode: OSErrorCode) = + ol.data = CompletionData(fd: socket, cb: + proc (fd: AsyncFD, bytesCount: Dword, errcode: OSErrorCode) = if not retFuture.finished: if errcode == OSErrorCode(-1): if bytesCount == 0 and dataBuf.buf[0] == '\0': @@ -634,7 +636,7 @@ when defined(windows) or defined(nimdoc): # free ``ol``. return retFuture - proc recvInto*(socket: TAsyncFD, buf: cstring, size: int, + proc recvInto*(socket: AsyncFD, buf: cstring, size: int, flags = {SocketFlag.SafeDisconn}): Future[int] = ## Reads **up to** ``size`` bytes from ``socket`` into ``buf``, which must ## at least be of that size. Returned future will complete once all the @@ -665,8 +667,8 @@ when defined(windows) or defined(nimdoc): var flagsio = flags.toOSFlags().Dword var ol = PCustomOverlapped() GC_ref(ol) - ol.data = TCompletionData(fd: socket, cb: - proc (fd: TAsyncFD, bytesCount: Dword, errcode: OSErrorCode) = + ol.data = CompletionData(fd: socket, cb: + proc (fd: AsyncFD, bytesCount: Dword, errcode: OSErrorCode) = if not retFuture.finished: if errcode == OSErrorCode(-1): if bytesCount == 0 and dataBuf.buf[0] == '\0': @@ -721,7 +723,7 @@ when defined(windows) or defined(nimdoc): # free ``ol``. return retFuture - proc send*(socket: TAsyncFD, data: string, + proc send*(socket: AsyncFD, data: string, flags = {SocketFlag.SafeDisconn}): Future[void] = ## Sends ``data`` to ``socket``. The returned future will complete once all ## data has been sent. @@ -735,8 +737,8 @@ when defined(windows) or defined(nimdoc): var bytesReceived, lowFlags: Dword var ol = PCustomOverlapped() GC_ref(ol) - ol.data = TCompletionData(fd: socket, cb: - proc (fd: TAsyncFD, bytesCount: Dword, errcode: OSErrorCode) = + ol.data = CompletionData(fd: socket, cb: + proc (fd: AsyncFD, bytesCount: Dword, errcode: OSErrorCode) = if not retFuture.finished: if errcode == OSErrorCode(-1): retFuture.complete() @@ -764,8 +766,8 @@ when defined(windows) or defined(nimdoc): # free ``ol``. return retFuture - proc acceptAddr*(socket: TAsyncFD, flags = {SocketFlag.SafeDisconn}): - Future[tuple[address: string, client: TAsyncFD]] = + proc acceptAddr*(socket: AsyncFD, flags = {SocketFlag.SafeDisconn}): + Future[tuple[address: string, client: AsyncFD]] = ## 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. @@ -778,7 +780,7 @@ when defined(windows) or defined(nimdoc): ## flag is specified then this error will not be raised and instead ## accept will be called again. verifyPresence(socket) - var retFuture = newFuture[tuple[address: string, client: TAsyncFD]]("acceptAddr") + var retFuture = newFuture[tuple[address: string, client: AsyncFD]]("acceptAddr") var clientSock = newRawSocket() if clientSock == osInvalidSocket: raiseOSError(osLastError()) @@ -803,11 +805,11 @@ when defined(windows) or defined(nimdoc): dwLocalAddressLength, dwRemoteAddressLength, addr localSockaddr, addr localLen, addr remoteSockaddr, addr remoteLen) - register(clientSock.TAsyncFD) + register(clientSock.AsyncFD) # TODO: IPv6. Check ``sa_family``. http://stackoverflow.com/a/9212542/492186 retFuture.complete( (address: $inet_ntoa(cast[ptr Sockaddr_in](remoteSockAddr).sin_addr), - client: clientSock.TAsyncFD) + client: clientSock.AsyncFD) ) template failAccept(errcode): stmt = @@ -824,8 +826,8 @@ when defined(windows) or defined(nimdoc): var ol = PCustomOverlapped() GC_ref(ol) - ol.data = TCompletionData(fd: socket, cb: - proc (fd: TAsyncFD, bytesCount: Dword, errcode: OSErrorCode) = + ol.data = CompletionData(fd: socket, cb: + proc (fd: AsyncFD, bytesCount: Dword, errcode: OSErrorCode) = if not retFuture.finished: if errcode == OSErrorCode(-1): completeAccept() @@ -853,26 +855,26 @@ when defined(windows) or defined(nimdoc): return retFuture - proc newAsyncRawSocket*(domain, typ, protocol: cint): TAsyncFD = + proc newAsyncRawSocket*(domain, typ, protocol: cint): AsyncFD = ## Creates a new socket and registers it with the dispatcher implicitly. - result = newRawSocket(domain, typ, protocol).TAsyncFD + result = newRawSocket(domain, typ, protocol).AsyncFD result.SocketHandle.setBlocking(false) register(result) proc newAsyncRawSocket*(domain: Domain = AF_INET, typ: SockType = SOCK_STREAM, - protocol: Protocol = IPPROTO_TCP): TAsyncFD = + protocol: Protocol = IPPROTO_TCP): AsyncFD = ## Creates a new socket and registers it with the dispatcher implicitly. - result = newRawSocket(domain, typ, protocol).TAsyncFD + result = newRawSocket(domain, typ, protocol).AsyncFD result.SocketHandle.setBlocking(false) register(result) - proc closeSocket*(socket: TAsyncFD) = + proc closeSocket*(socket: AsyncFD) = ## Closes a socket and ensures that it is unregistered. socket.SocketHandle.close() getGlobalDispatcher().handles.excl(socket) - proc unregister*(fd: TAsyncFD) = + proc unregister*(fd: AsyncFD) = ## Unregisters ``fd``. getGlobalDispatcher().handles.excl(fd) @@ -892,18 +894,19 @@ else: MSG_NOSIGNAL type - TAsyncFD* = distinct cint - TCallback = proc (fd: TAsyncFD): bool {.closure,gcsafe.} + AsyncFD* = distinct cint + Callback = proc (fd: AsyncFD): bool {.closure,gcsafe.} PData* = ref object of RootRef - fd: TAsyncFD - readCBs: seq[TCallback] - writeCBs: seq[TCallback] + fd: AsyncFD + readCBs: seq[Callback] + writeCBs: seq[Callback] PDispatcher* = ref object of PDispatcherBase selector: Selector + {.deprecated: [TAsyncFD: AsyncFD, TCallback: Callback].} - proc `==`*(x, y: TAsyncFD): bool {.borrow.} + proc `==`*(x, y: AsyncFD): bool {.borrow.} proc newDispatcher*(): PDispatcher = new result @@ -915,18 +918,18 @@ else: if gDisp.isNil: gDisp = newDispatcher() result = gDisp - proc update(fd: TAsyncFD, events: set[Event]) = + proc update(fd: AsyncFD, events: set[Event]) = let p = getGlobalDispatcher() assert fd.SocketHandle in p.selector discard p.selector.update(fd.SocketHandle, events) - proc register*(fd: TAsyncFD) = + proc register*(fd: AsyncFD) = let p = getGlobalDispatcher() var data = PData(fd: fd, readCBs: @[], writeCBs: @[]) p.selector.register(fd.SocketHandle, {}, data.RootRef) - proc newAsyncRawSocket*(domain: cint, typ: cint, protocol: cint): TAsyncFD = - result = newRawSocket(domain, typ, protocol).TAsyncFD + proc newAsyncRawSocket*(domain: cint, typ: cint, protocol: cint): AsyncFD = + result = newRawSocket(domain, typ, protocol).AsyncFD result.SocketHandle.setBlocking(false) when defined(macosx): result.SocketHandle.setSockOptInt(SOL_SOCKET, SO_NOSIGPIPE, 1) @@ -934,29 +937,29 @@ else: proc newAsyncRawSocket*(domain: Domain = AF_INET, typ: SockType = SOCK_STREAM, - protocol: Protocol = IPPROTO_TCP): TAsyncFD = - result = newRawSocket(domain, typ, protocol).TAsyncFD + protocol: Protocol = IPPROTO_TCP): AsyncFD = + result = newRawSocket(domain, typ, protocol).AsyncFD result.SocketHandle.setBlocking(false) when defined(macosx): result.SocketHandle.setSockOptInt(SOL_SOCKET, SO_NOSIGPIPE, 1) register(result) - proc closeSocket*(sock: TAsyncFD) = + proc closeSocket*(sock: AsyncFD) = let disp = getGlobalDispatcher() sock.SocketHandle.close() disp.selector.unregister(sock.SocketHandle) - proc unregister*(fd: TAsyncFD) = + proc unregister*(fd: AsyncFD) = getGlobalDispatcher().selector.unregister(fd.SocketHandle) - proc addRead*(fd: TAsyncFD, cb: TCallback) = + proc addRead*(fd: AsyncFD, cb: Callback) = let p = getGlobalDispatcher() if fd.SocketHandle notin p.selector: raise newException(ValueError, "File descriptor not registered.") p.selector[fd.SocketHandle].data.PData.readCBs.add(cb) update(fd, p.selector[fd.SocketHandle].events + {EvRead}) - proc addWrite*(fd: TAsyncFD, cb: TCallback) = + proc addWrite*(fd: AsyncFD, cb: Callback) = let p = getGlobalDispatcher() if fd.SocketHandle notin p.selector: raise newException(ValueError, "File descriptor not registered.") @@ -967,7 +970,7 @@ else: let p = getGlobalDispatcher() for info in p.selector.select(timeout): let data = PData(info.key.data) - assert data.fd == info.key.fd.TAsyncFD + assert data.fd == info.key.fd.AsyncFD #echo("In poll ", data.fd.cint) if EvError in info.events: closeSocket(data.fd) @@ -1005,11 +1008,11 @@ else: processTimers(p) - proc connect*(socket: TAsyncFD, address: string, port: Port, + proc connect*(socket: AsyncFD, address: string, port: Port, af = AF_INET): Future[void] = var retFuture = newFuture[void]("connect") - proc cb(fd: TAsyncFD): bool = + proc cb(fd: AsyncFD): bool = # We have connected. retFuture.complete() return true @@ -1040,13 +1043,13 @@ else: retFuture.fail(newException(OSError, osErrorMsg(lastError))) return retFuture - proc recv*(socket: TAsyncFD, size: int, + proc recv*(socket: AsyncFD, size: int, flags = {SocketFlag.SafeDisconn}): Future[string] = var retFuture = newFuture[string]("recv") var readBuffer = newString(size) - proc cb(sock: TAsyncFD): bool = + proc cb(sock: AsyncFD): bool = result = true let res = recv(sock.SocketHandle, addr readBuffer[0], size.cint, flags.toOSFlags()) @@ -1070,11 +1073,11 @@ else: addRead(socket, cb) return retFuture - proc recvInto*(socket: TAsyncFD, buf: cstring, size: int, + proc recvInto*(socket: AsyncFD, buf: cstring, size: int, flags = {SocketFlag.SafeDisconn}): Future[int] = var retFuture = newFuture[int]("recvInto") - proc cb(sock: TAsyncFD): bool = + proc cb(sock: AsyncFD): bool = result = true let res = recv(sock.SocketHandle, buf, size.cint, flags.toOSFlags()) @@ -1094,13 +1097,13 @@ else: addRead(socket, cb) return retFuture - proc send*(socket: TAsyncFD, data: string, + proc send*(socket: AsyncFD, data: string, flags = {SocketFlag.SafeDisconn}): Future[void] = var retFuture = newFuture[void]("send") var written = 0 - proc cb(sock: TAsyncFD): bool = + proc cb(sock: AsyncFD): bool = result = true let netSize = data.len-written var d = data.cstring @@ -1126,11 +1129,11 @@ else: addWrite(socket, cb) return retFuture - proc acceptAddr*(socket: TAsyncFD, flags = {SocketFlag.SafeDisconn}): - Future[tuple[address: string, client: TAsyncFD]] = + proc acceptAddr*(socket: AsyncFD, flags = {SocketFlag.SafeDisconn}): + Future[tuple[address: string, client: AsyncFD]] = var retFuture = newFuture[tuple[address: string, - client: TAsyncFD]]("acceptAddr") - proc cb(sock: TAsyncFD): bool = + client: AsyncFD]]("acceptAddr") + proc cb(sock: AsyncFD): bool = result = true var sockAddress: SockAddr_in var addrLen = sizeof(sockAddress).Socklen @@ -1147,8 +1150,8 @@ else: else: retFuture.fail(newException(OSError, osErrorMsg(lastError))) else: - register(client.TAsyncFD) - retFuture.complete(($inet_ntoa(sockAddress.sin_addr), client.TAsyncFD)) + register(client.AsyncFD) + retFuture.complete(($inet_ntoa(sockAddress.sin_addr), client.AsyncFD)) addRead(socket, cb) return retFuture @@ -1160,15 +1163,15 @@ proc sleepAsync*(ms: int): Future[void] = p.timers.add((epochTime() + (ms / 1000), retFuture)) return retFuture -proc accept*(socket: TAsyncFD, - flags = {SocketFlag.SafeDisconn}): Future[TAsyncFD] = +proc accept*(socket: AsyncFD, + flags = {SocketFlag.SafeDisconn}): Future[AsyncFD] = ## 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 retFut = newFuture[AsyncFD]("accept") var fut = acceptAddr(socket, flags) fut.callback = - proc (future: Future[tuple[address: string, client: TAsyncFD]]) = + proc (future: Future[tuple[address: string, client: AsyncFD]]) = assert future.finished if future.failed: retFut.fail(future.error) @@ -1495,7 +1498,7 @@ macro async*(prc: stmt): stmt {.immediate.} = #if prc[0].getName == "test": # echo(toStrLit(result)) -proc recvLine*(socket: TAsyncFD): Future[string] {.async.} = +proc recvLine*(socket: AsyncFD): 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/asyncfile.nim b/lib/pure/asyncfile.nim index 25e121183..ece9b4dfb 100644 --- a/lib/pure/asyncfile.nim +++ b/lib/pure/asyncfile.nim @@ -31,7 +31,7 @@ else: type AsyncFile* = ref object - fd: TAsyncFd + fd: AsyncFd offset: int64 when defined(windows) or defined(nimdoc): @@ -72,7 +72,7 @@ proc getFileSize(f: AsyncFile): int64 = ## Retrieves the specified file's size. when defined(windows) or defined(nimdoc): var high: DWord - let low = getFileSize(f.fd.THandle, addr high) + let low = getFileSize(f.fd.Handle, addr high) if low == INVALID_FILE_SIZE: raiseOSError(osLastError()) return (high shl 32) or low @@ -88,13 +88,13 @@ proc openAsync*(filename: string, mode = fmRead): AsyncFile = when useWinUnicode: result.fd = createFileW(newWideCString(filename), desiredAccess, FILE_SHARE_READ, - nil, creationDisposition, flags, 0).TAsyncFd + nil, creationDisposition, flags, 0).AsyncFd else: result.fd = createFileA(filename, desiredAccess, FILE_SHARE_READ, - nil, creationDisposition, flags, 0).TAsyncFd + nil, creationDisposition, flags, 0).AsyncFd - if result.fd.THandle == INVALID_HANDLE_VALUE: + if result.fd.Handle == INVALID_HANDLE_VALUE: raiseOSError(osLastError()) register(result.fd) @@ -106,7 +106,7 @@ proc openAsync*(filename: string, mode = fmRead): AsyncFile = let flags = getPosixFlags(mode) # RW (Owner), RW (Group), R (Other) let perm = S_IRUSR or S_IWUSR or S_IRGRP or S_IWGRP or S_IROTH - result.fd = open(filename, flags, perm).TAsyncFD + result.fd = open(filename, flags, perm).AsyncFD if result.fd.cint == -1: raiseOSError(osLastError()) @@ -125,8 +125,8 @@ proc read*(f: AsyncFile, size: int): Future[string] = var ol = PCustomOverlapped() GC_ref(ol) - ol.data = TCompletionData(fd: f.fd, cb: - proc (fd: TAsyncFD, bytesCount: Dword, errcode: OSErrorCode) = + ol.data = CompletionData(fd: f.fd, cb: + proc (fd: AsyncFD, bytesCount: Dword, errcode: OSErrorCode) = if not retFuture.finished: if errcode == OSErrorCode(-1): assert bytesCount > 0 @@ -148,7 +148,7 @@ proc read*(f: AsyncFile, size: int): Future[string] = ol.offsetHigh = DWord(f.offset shr 32) # According to MSDN we're supposed to pass nil to lpNumberOfBytesRead. - let ret = readFile(f.fd.THandle, buffer, size.int32, nil, + let ret = readFile(f.fd.Handle, buffer, size.int32, nil, cast[POVERLAPPED](ol)) if not ret.bool: let err = osLastError() @@ -161,7 +161,7 @@ proc read*(f: AsyncFile, size: int): Future[string] = else: # Request completed immediately. var bytesRead: DWord - let overlappedRes = getOverlappedResult(f.fd.THandle, + let overlappedRes = getOverlappedResult(f.fd.Handle, cast[POverlapped](ol)[], bytesRead, false.WinBool) if not overlappedRes.bool: let err = osLastError() @@ -179,7 +179,7 @@ proc read*(f: AsyncFile, size: int): Future[string] = else: var readBuffer = newString(size) - proc cb(fd: TAsyncFD): bool = + proc cb(fd: AsyncFD): bool = result = true let res = read(fd.cint, addr readBuffer[0], size.cint) if res < 0: @@ -251,8 +251,8 @@ proc write*(f: AsyncFile, data: string): Future[void] = var ol = PCustomOverlapped() GC_ref(ol) - ol.data = TCompletionData(fd: f.fd, cb: - proc (fd: TAsyncFD, bytesCount: DWord, errcode: OSErrorCode) = + ol.data = CompletionData(fd: f.fd, cb: + proc (fd: AsyncFD, bytesCount: DWord, errcode: OSErrorCode) = if not retFuture.finished: if errcode == OSErrorCode(-1): assert bytesCount == data.len.int32 @@ -268,7 +268,7 @@ proc write*(f: AsyncFile, data: string): Future[void] = ol.offsetHigh = DWord(f.offset shr 32) # According to MSDN we're supposed to pass nil to lpNumberOfBytesWritten. - let ret = writeFile(f.fd.THandle, buffer, data.len.int32, nil, + let ret = writeFile(f.fd.Handle, buffer, data.len.int32, nil, cast[POVERLAPPED](ol)) if not ret.bool: let err = osLastError() @@ -281,7 +281,7 @@ proc write*(f: AsyncFile, data: string): Future[void] = else: # Request completed immediately. var bytesWritten: DWord - let overlappedRes = getOverlappedResult(f.fd.THandle, + let overlappedRes = getOverlappedResult(f.fd.Handle, cast[POverlapped](ol)[], bytesWritten, false.WinBool) if not overlappedRes.bool: retFuture.fail(newException(OSError, osErrorMsg(osLastError()))) @@ -292,7 +292,7 @@ proc write*(f: AsyncFile, data: string): Future[void] = else: var written = 0 - proc cb(fd: TAsyncFD): bool = + proc cb(fd: AsyncFD): bool = result = true let remainderSize = data.len-written let res = write(fd.cint, addr copy[written], remainderSize.cint) @@ -317,7 +317,7 @@ proc write*(f: AsyncFile, data: string): Future[void] = proc close*(f: AsyncFile) = ## Closes the file specified. when defined(windows) or defined(nimdoc): - if not closeHandle(f.fd.THandle).bool: + if not closeHandle(f.fd.Handle).bool: raiseOSError(osLastError()) else: if close(f.fd.cint) == -1: diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim index 279cedb5d..9e036443c 100644 --- a/lib/pure/asynchttpserver.nim +++ b/lib/pure/asynchttpserver.nim @@ -210,6 +210,7 @@ proc processClient(client: AsyncSocket, address: string, var contentLength = 0 if parseInt(request.headers["Content-Length"], contentLength) == 0: await request.respond(Http400, "Bad Request. Invalid Content-Length.") + continue else: request.body = await client.recv(contentLength) assert request.body.len == contentLength diff --git a/lib/pure/asyncio.nim b/lib/pure/asyncio.nim index 6ae2c608b..5fd45b215 100644 --- a/lib/pure/asyncio.nim +++ b/lib/pure/asyncio.nim @@ -188,8 +188,8 @@ proc asyncSocket*(domain: Domain = AF_INET, typ: SockType = SOCK_STREAM, result.socket.setBlocking(false) proc toAsyncSocket*(sock: Socket, state: SocketStatus = SockConnected): AsyncSocket = - ## Wraps an already initialized ``TSocket`` into a AsyncSocket. - ## This is useful if you want to use an already connected TSocket as an + ## Wraps an already initialized ``Socket`` into a AsyncSocket. + ## This is useful if you want to use an already connected Socket as an ## asynchronous AsyncSocket in asyncio's event loop. ## ## ``state`` may be overriden, i.e. if ``sock`` is not connected it should be diff --git a/lib/pure/asyncnet.nim b/lib/pure/asyncnet.nim index aadbde824..01c28a13a 100644 --- a/lib/pure/asyncnet.nim +++ b/lib/pure/asyncnet.nim @@ -91,13 +91,13 @@ type # TODO: Save AF, domain etc info and reuse it in procs which need it like connect. -proc newAsyncSocket*(fd: TAsyncFD, isBuff: bool): AsyncSocket = +proc newAsyncSocket*(fd: AsyncFD, buffered = true): AsyncSocket = ## Creates a new ``AsyncSocket`` based on the supplied params. - assert fd != osInvalidSocket.TAsyncFD + assert fd != osInvalidSocket.AsyncFD new(result) result.fd = fd.SocketHandle - result.isBuffered = isBuff - if isBuff: + result.isBuffered = buffered + if buffered: result.currPos = 0 proc newAsyncSocket*(domain: Domain = AF_INET, typ: SockType = SOCK_STREAM, @@ -142,7 +142,7 @@ when defined(ssl): if read < 0: raiseSslError() data.setLen(read) - await socket.fd.TAsyncFd.send(data, flags) + await socket.fd.AsyncFd.send(data, flags) proc appeaseSsl(socket: AsyncSocket, flags: set[SocketFlag], sslError: cint) {.async.} = @@ -150,7 +150,7 @@ when defined(ssl): of SSL_ERROR_WANT_WRITE: await sendPendingSslData(socket, flags) of SSL_ERROR_WANT_READ: - var data = await recv(socket.fd.TAsyncFD, BufferSize, flags) + var data = await recv(socket.fd.AsyncFD, BufferSize, flags) let ret = bioWrite(socket.bioIn, addr data[0], data.len.cint) if ret < 0: raiseSSLError() @@ -175,7 +175,7 @@ proc connect*(socket: AsyncSocket, address: string, port: Port, ## ## Returns a ``Future`` which will complete when the connection succeeds ## or an error occurs. - await connect(socket.fd.TAsyncFD, address, port, af) + await connect(socket.fd.AsyncFD, address, port, af) if socket.isSsl: when defined(ssl): let flags = {SocketFlag.SafeDisconn} @@ -194,7 +194,7 @@ template readInto(buf: cstring, size: int, socket: AsyncSocket, sslRead(socket.sslHandle, buf, size.cint)) res = opResult else: - var recvIntoFut = recvInto(socket.fd.TAsyncFD, buf, size, flags) + var recvIntoFut = recvInto(socket.fd.AsyncFD, buf, size, flags) yield recvIntoFut # Not in SSL mode. res = recvIntoFut.read() @@ -271,7 +271,7 @@ proc send*(socket: AsyncSocket, data: string, sslWrite(socket.sslHandle, addr copy[0], copy.len.cint)) await sendPendingSslData(socket, flags) else: - await send(socket.fd.TAsyncFD, data, flags) + await send(socket.fd.AsyncFD, data, flags) proc acceptAddr*(socket: AsyncSocket, flags = {SocketFlag.SafeDisconn}): Future[tuple[address: string, client: AsyncSocket]] = @@ -279,9 +279,9 @@ proc acceptAddr*(socket: AsyncSocket, flags = {SocketFlag.SafeDisconn}): ## corresponding to that connection and the remote address of the client. ## The future will complete when the connection is successfully accepted. var retFuture = newFuture[tuple[address: string, client: AsyncSocket]]("asyncnet.acceptAddr") - var fut = acceptAddr(socket.fd.TAsyncFD, flags) + var fut = acceptAddr(socket.fd.AsyncFD, flags) fut.callback = - proc (future: Future[tuple[address: string, client: TAsyncFD]]) = + proc (future: Future[tuple[address: string, client: AsyncFD]]) = assert future.finished if future.failed: retFuture.fail(future.readError) @@ -445,7 +445,7 @@ proc bindAddr*(socket: AsyncSocket, port = Port(0), address = "") {. proc close*(socket: AsyncSocket) = ## Closes the socket. defer: - socket.fd.TAsyncFD.closeSocket() + socket.fd.AsyncFD.closeSocket() when defined(ssl): if socket.isSSL: let res = SslShutdown(socket.sslHandle) diff --git a/lib/pure/basic2d.nim b/lib/pure/basic2d.nim index a344cd053..d18e73c16 100644 --- a/lib/pure/basic2d.nim +++ b/lib/pure/basic2d.nim @@ -20,20 +20,20 @@ import strutils ## ## # Create a matrix which first rotates, then scales and at last translates ## -## var m:TMatrix2d=rotate(DEG90) & scale(2.0) & move(100.0,200.0) +## var m:Matrix2d=rotate(DEG90) & scale(2.0) & move(100.0,200.0) ## ## # Create a 2d point at (100,0) and a vector (5,2) ## -## var pt:TPoint2d=point2d(100.0,0.0) +## var pt:Point2d=point2d(100.0,0.0) ## -## var vec:TVector2d=vector2d(5.0,2.0) +## var vec:Vector2d=vector2d(5.0,2.0) ## ## ## pt &= m # transforms pt in place ## -## var pt2:TPoint2d=pt & m #concatenates pt with m and returns a new point +## var pt2:Point2d=pt & m #concatenates pt with m and returns a new point ## -## var vec2:TVector2d=vec & m #concatenates vec with m and returns a new vector +## var vec2:Vector2d=vec & m #concatenates vec with m and returns a new vector const @@ -57,46 +57,46 @@ const ## used internally by DegToRad and RadToDeg type - TMatrix2d* = object + Matrix2d* = object ## Implements a row major 2d matrix, which means ## transformations are applied the order they are concatenated. ## The rightmost column of the 3x3 matrix is left out since normally ## not used for geometric transformations in 2d. ax*,ay*,bx*,by*,tx*,ty*:float - TPoint2d* = object + Point2d* = object ## Implements a non-homegeneous 2d point stored as ## an `x` coordinate and an `y` coordinate. x*,y*:float - TVector2d* = object + Vector2d* = object ## Implements a 2d **direction vector** stored as ## an `x` coordinate and an `y` coordinate. Direction vector means, ## that when transforming a vector with a matrix, the translational ## part of the matrix is ignored. x*,y*:float - +{.deprecated: [TMatrix2d: Matrix2d, TPoint2d: Point2d, TVector2d: Vector2d].} # Some forward declarations... -proc matrix2d*(ax,ay,bx,by,tx,ty:float):TMatrix2d {.noInit.} +proc matrix2d*(ax,ay,bx,by,tx,ty:float):Matrix2d {.noInit.} ## Creates a new matrix. ## `ax`,`ay` is the local x axis ## `bx`,`by` is the local y axis ## `tx`,`ty` is the translation -proc vector2d*(x,y:float):TVector2d {.noInit,inline.} +proc vector2d*(x,y:float):Vector2d {.noInit,inline.} ## Returns a new vector (`x`,`y`) -proc point2d*(x,y:float):TPoint2d {.noInit,inline.} +proc point2d*(x,y:float):Point2d {.noInit,inline.} ## Returns a new point (`x`,`y`) let - IDMATRIX*:TMatrix2d=matrix2d(1.0,0.0,0.0,1.0,0.0,0.0) + IDMATRIX*:Matrix2d=matrix2d(1.0,0.0,0.0,1.0,0.0,0.0) ## Quick access to an identity matrix - ORIGO*:TPoint2d=point2d(0.0,0.0) + ORIGO*:Point2d=point2d(0.0,0.0) ## Quick acces to point (0,0) - XAXIS*:TVector2d=vector2d(1.0,0.0) + XAXIS*:Vector2d=vector2d(1.0,0.0) ## Quick acces to an 2d x-axis unit vector - YAXIS*:TVector2d=vector2d(0.0,1.0) + YAXIS*:Vector2d=vector2d(0.0,1.0) ## Quick acces to an 2d y-axis unit vector @@ -116,21 +116,21 @@ proc safeArccos(v:float):float= template makeBinOpVector(s:expr)= ## implements binary operators + , - , * and / for vectors - proc s*(a,b:TVector2d):TVector2d {.inline,noInit.} = vector2d(s(a.x,b.x),s(a.y,b.y)) - proc s*(a:TVector2d,b:float):TVector2d {.inline,noInit.} = vector2d(s(a.x,b),s(a.y,b)) - proc s*(a:float,b:TVector2d):TVector2d {.inline,noInit.} = vector2d(s(a,b.x),s(a,b.y)) + proc s*(a,b:Vector2d):Vector2d {.inline,noInit.} = vector2d(s(a.x,b.x),s(a.y,b.y)) + proc s*(a:Vector2d,b:float):Vector2d {.inline,noInit.} = vector2d(s(a.x,b),s(a.y,b)) + proc s*(a:float,b:Vector2d):Vector2d {.inline,noInit.} = vector2d(s(a,b.x),s(a,b.y)) template makeBinOpAssignVector(s:expr)= ## implements inplace binary operators += , -= , /= and *= for vectors - proc s*(a:var TVector2d,b:TVector2d) {.inline.} = s(a.x,b.x) ; s(a.y,b.y) - proc s*(a:var TVector2d,b:float) {.inline.} = s(a.x,b) ; s(a.y,b) + proc s*(a:var Vector2d,b:Vector2d) {.inline.} = s(a.x,b.x) ; s(a.y,b.y) + proc s*(a:var Vector2d,b:float) {.inline.} = s(a.x,b) ; s(a.y,b) # *************************************** -# TMatrix2d implementation +# Matrix2d implementation # *************************************** -proc setElements*(t:var TMatrix2d,ax,ay,bx,by,tx,ty:float) {.inline.}= +proc setElements*(t:var Matrix2d,ax,ay,bx,by,tx,ty:float) {.inline.}= ## Sets arbitrary elements in an existing matrix. t.ax=ax t.ay=ay @@ -139,10 +139,10 @@ proc setElements*(t:var TMatrix2d,ax,ay,bx,by,tx,ty:float) {.inline.}= t.tx=tx t.ty=ty -proc matrix2d*(ax,ay,bx,by,tx,ty:float):TMatrix2d = +proc matrix2d*(ax,ay,bx,by,tx,ty:float):Matrix2d = result.setElements(ax,ay,bx,by,tx,ty) -proc `&`*(a,b:TMatrix2d):TMatrix2d {.noInit.} = #concatenate matrices +proc `&`*(a,b:Matrix2d):Matrix2d {.noInit.} = #concatenate matrices ## Concatenates matrices returning a new matrix. # | a.AX a.AY 0 | | b.AX b.AY 0 | @@ -157,34 +157,34 @@ proc `&`*(a,b:TMatrix2d):TMatrix2d {.noInit.} = #concatenate matrices a.tx * b.ay + a.ty * b.by + b.ty) -proc scale*(s:float):TMatrix2d {.noInit.} = +proc scale*(s:float):Matrix2d {.noInit.} = ## Returns a new scale matrix. result.setElements(s,0,0,s,0,0) -proc scale*(s:float,org:TPoint2d):TMatrix2d {.noInit.} = +proc scale*(s:float,org:Point2d):Matrix2d {.noInit.} = ## Returns a new scale matrix using, `org` as scale origin. result.setElements(s,0,0,s,org.x-s*org.x,org.y-s*org.y) -proc stretch*(sx,sy:float):TMatrix2d {.noInit.} = +proc stretch*(sx,sy:float):Matrix2d {.noInit.} = ## Returns new a stretch matrix, which is a ## scale matrix with non uniform scale in x and y. result.setElements(sx,0,0,sy,0,0) -proc stretch*(sx,sy:float,org:TPoint2d):TMatrix2d {.noInit.} = +proc stretch*(sx,sy:float,org:Point2d):Matrix2d {.noInit.} = ## Returns a new stretch matrix, which is a ## scale matrix with non uniform scale in x and y. ## `org` is used as stretch origin. result.setElements(sx,0,0,sy,org.x-sx*org.x,org.y-sy*org.y) -proc move*(dx,dy:float):TMatrix2d {.noInit.} = +proc move*(dx,dy:float):Matrix2d {.noInit.} = ## Returns a new translation matrix. result.setElements(1,0,0,1,dx,dy) -proc move*(v:TVector2d):TMatrix2d {.noInit.} = +proc move*(v:Vector2d):Matrix2d {.noInit.} = ## Returns a new translation matrix from a vector. result.setElements(1,0,0,1,v.x,v.y) -proc rotate*(rad:float):TMatrix2d {.noInit.} = +proc rotate*(rad:float):Matrix2d {.noInit.} = ## Returns a new rotation matrix, which ## represents a rotation by `rad` radians let @@ -192,7 +192,7 @@ proc rotate*(rad:float):TMatrix2d {.noInit.} = c=cos(rad) result.setElements(c,s,-s,c,0,0) -proc rotate*(rad:float,org:TPoint2d):TMatrix2d {.noInit.} = +proc rotate*(rad:float,org:Point2d):Matrix2d {.noInit.} = ## Returns a new rotation matrix, which ## represents a rotation by `rad` radians around ## the origin `org` @@ -201,7 +201,7 @@ proc rotate*(rad:float,org:TPoint2d):TMatrix2d {.noInit.} = c=cos(rad) result.setElements(c,s,-s,c,org.x+s*org.y-c*org.x,org.y-c*org.y-s*org.x) -proc mirror*(v:TVector2d):TMatrix2d {.noInit.} = +proc mirror*(v:Vector2d):Matrix2d {.noInit.} = ## Returns a new mirror matrix, mirroring ## around the line that passes through origo and ## has the direction of `v` @@ -220,7 +220,7 @@ proc mirror*(v:TVector2d):TMatrix2d {.noInit.} = xy2,-sqd, 0.0,0.0) -proc mirror*(org:TPoint2d,v:TVector2d):TMatrix2d {.noInit.} = +proc mirror*(org:Point2d,v:Vector2d):Matrix2d {.noInit.} = ## Returns a new mirror matrix, mirroring ## around the line that passes through `org` and ## has the direction of `v` @@ -241,20 +241,20 @@ proc mirror*(org:TPoint2d,v:TVector2d):TMatrix2d {.noInit.} = -proc skew*(xskew,yskew:float):TMatrix2d {.noInit.} = +proc skew*(xskew,yskew:float):Matrix2d {.noInit.} = ## Returns a new skew matrix, which has its ## x axis rotated `xskew` radians from the local x axis, and ## y axis rotated `yskew` radians from the local y axis result.setElements(cos(yskew),sin(yskew),-sin(xskew),cos(xskew),0,0) -proc `$`* (t:TMatrix2d):string {.noInit.} = +proc `$`* (t:Matrix2d):string {.noInit.} = ## Returns a string representation of the matrix return rtos(t.ax) & "," & rtos(t.ay) & "," & rtos(t.bx) & "," & rtos(t.by) & "," & rtos(t.tx) & "," & rtos(t.ty) -proc isUniform*(t:TMatrix2d,tol=1.0e-6):bool= +proc isUniform*(t:Matrix2d,tol=1.0e-6):bool= ## Checks if the transform is uniform, that is ## perpendicular axes of equal length, which means (for example) ## it cannot transform a circle into an ellipse. @@ -268,18 +268,18 @@ proc isUniform*(t:TMatrix2d,tol=1.0e-6):bool= return true return false -proc determinant*(t:TMatrix2d):float= +proc determinant*(t:Matrix2d):float= ## Computes the determinant of the matrix. #NOTE: equivalent with perp.dot product for two 2d vectors return t.ax*t.by-t.bx*t.ay -proc isMirroring* (m:TMatrix2d):bool= +proc isMirroring* (m:Matrix2d):bool= ## Checks if the `m` is a mirroring matrix, ## which means it will reverse direction of a curve transformed with it return m.determinant<0.0 -proc inverse*(m:TMatrix2d):TMatrix2d {.noInit.} = +proc inverse*(m:Matrix2d):Matrix2d {.noInit.} = ## Returns a new matrix, which is the inverse of the matrix ## If the matrix is not invertible (determinant=0), an EDivByZero ## will be raised. @@ -293,7 +293,7 @@ proc inverse*(m:TMatrix2d):TMatrix2d {.noInit.} = (m.bx*m.ty-m.by*m.tx)/d, (m.ay*m.tx-m.ax*m.ty)/d) -proc equals*(m1:TMatrix2d,m2:TMatrix2d,tol=1.0e-6):bool= +proc equals*(m1:Matrix2d,m2:Matrix2d,tol=1.0e-6):bool= ## Checks if all elements of `m1`and `m2` is equal within ## a given tolerance `tol`. return @@ -304,17 +304,17 @@ proc equals*(m1:TMatrix2d,m2:TMatrix2d,tol=1.0e-6):bool= abs(m1.tx-m2.tx)<=tol and abs(m1.ty-m2.ty)<=tol -proc `=~`*(m1,m2:TMatrix2d):bool= +proc `=~`*(m1,m2:Matrix2d):bool= ## Checks if `m1`and `m2` is approximately equal, using a ## tolerance of 1e-6. equals(m1,m2) -proc isIdentity*(m:TMatrix2d,tol=1.0e-6):bool= +proc isIdentity*(m:Matrix2d,tol=1.0e-6):bool= ## Checks is a matrix is approximately an identity matrix, ## using `tol` as tolerance for each element. return equals(m,IDMATRIX,tol) -proc apply*(m:TMatrix2d,x,y:var float,translate=false)= +proc apply*(m:Matrix2d,x,y:var float,translate=false)= ## Applies transformation `m` onto `x`,`y`, optionally ## using the translation part of the matrix. if translate: # positional style transform @@ -329,29 +329,29 @@ proc apply*(m:TMatrix2d,x,y:var float,translate=false)= # *************************************** -# TVector2d implementation +# Vector2d implementation # *************************************** -proc vector2d*(x,y:float):TVector2d = #forward decl. +proc vector2d*(x,y:float):Vector2d = #forward decl. result.x=x result.y=y -proc polarVector2d*(ang:float,len:float):TVector2d {.noInit.} = +proc polarVector2d*(ang:float,len:float):Vector2d {.noInit.} = ## Returns a new vector with angle `ang` and magnitude `len` result.x=cos(ang)*len result.y=sin(ang)*len -proc slopeVector2d*(slope:float,len:float):TVector2d {.noInit.} = +proc slopeVector2d*(slope:float,len:float):Vector2d {.noInit.} = ## Returns a new vector having slope (dy/dx) given by ## `slope`, and a magnitude of `len` let ang=arctan(slope) result.x=cos(ang)*len result.y=sin(ang)*len -proc len*(v:TVector2d):float {.inline.}= +proc len*(v:Vector2d):float {.inline.}= ## Returns the length of the vector. sqrt(v.x*v.x+v.y*v.y) -proc `len=`*(v:var TVector2d,newlen:float) {.noInit.} = +proc `len=`*(v:var Vector2d,newlen:float) {.noInit.} = ## Sets the length of the vector, keeping its angle. let fac=newlen/v.len @@ -369,25 +369,25 @@ proc `len=`*(v:var TVector2d,newlen:float) {.noInit.} = v.x*=fac v.y*=fac -proc sqrLen*(v:TVector2d):float {.inline.}= +proc sqrLen*(v:Vector2d):float {.inline.}= ## Computes the squared length of the vector, which is ## faster than computing the absolute length. v.x*v.x+v.y*v.y -proc angle*(v:TVector2d):float= +proc angle*(v:Vector2d):float= ## Returns the angle of the vector. ## (The counter clockwise plane angle between posetive x axis and `v`) result=arctan2(v.y,v.x) if result<0.0: result+=DEG360 -proc `$` *(v:TVector2d):string= +proc `$` *(v:Vector2d):string= ## String representation of `v` result=rtos(v.x) result.add(",") result.add(rtos(v.y)) -proc `&` *(v:TVector2d,m:TMatrix2d):TVector2d {.noInit.} = +proc `&` *(v:Vector2d,m:Matrix2d):Vector2d {.noInit.} = ## Concatenate vector `v` with a transformation matrix. ## Transforming a vector ignores the translational part ## of the matrix. @@ -399,7 +399,7 @@ proc `&` *(v:TVector2d,m:TMatrix2d):TVector2d {.noInit.} = result.y=v.x*m.ay+v.y*m.by -proc `&=`*(v:var TVector2d,m:TMatrix2d) {.inline.}= +proc `&=`*(v:var Vector2d,m:Matrix2d) {.inline.}= ## Applies transformation `m` onto `v` in place. ## Transforming a vector ignores the translational part ## of the matrix. @@ -412,7 +412,7 @@ proc `&=`*(v:var TVector2d,m:TMatrix2d) {.inline.}= v.x=newx -proc tryNormalize*(v:var TVector2d):bool= +proc tryNormalize*(v:var Vector2d):bool= ## Modifies `v` to have a length of 1.0, keeping its angle. ## If `v` has zero length (and thus no angle), it is left unmodified and ## false is returned, otherwise true is returned. @@ -427,13 +427,13 @@ proc tryNormalize*(v:var TVector2d):bool= return true -proc normalize*(v:var TVector2d) {.inline.}= +proc normalize*(v:var Vector2d) {.inline.}= ## Modifies `v` to have a length of 1.0, keeping its angle. ## If `v` has zero length, an EDivByZero will be raised. if not tryNormalize(v): raise newException(DivByZeroError,"Cannot normalize zero length vector") -proc transformNorm*(v:var TVector2d,t:TMatrix2d)= +proc transformNorm*(v:var Vector2d,t:Matrix2d)= ## Applies a normal direction transformation `t` onto `v` in place. ## The resulting vector is *not* normalized. Transforming a vector ignores the ## translational part of the matrix. If the matrix is not invertible @@ -452,7 +452,7 @@ proc transformNorm*(v:var TVector2d,t:TMatrix2d)= v.y = (t.ax*v.y-t.bx*v.x)/d v.x = newx -proc transformInv*(v:var TVector2d,t:TMatrix2d)= +proc transformInv*(v:var Vector2d,t:Matrix2d)= ## Applies inverse of a transformation `t` to `v` in place. ## This is faster than creating an inverse matrix and apply() it. ## Transforming a vector ignores the translational part @@ -467,7 +467,7 @@ proc transformInv*(v:var TVector2d,t:TMatrix2d)= v.y = (t.ax*v.y-t.ay*v.x)/d v.x = newx -proc transformNormInv*(v:var TVector2d,t:TMatrix2d)= +proc transformNormInv*(v:var Vector2d,t:Matrix2d)= ## Applies an inverse normal direction transformation `t` onto `v` in place. ## This is faster than creating an inverse ## matrix and transformNorm(...) it. Transforming a vector ignores the @@ -484,25 +484,25 @@ proc transformNormInv*(v:var TVector2d,t:TMatrix2d)= v.y=t.by*v.y+t.bx*v.x v.x=newx -proc rotate90*(v:var TVector2d) {.inline.}= +proc rotate90*(v:var Vector2d) {.inline.}= ## Quickly rotates vector `v` 90 degrees counter clockwise, ## without using any trigonometrics. swap(v.x,v.y) v.x= -v.x -proc rotate180*(v:var TVector2d){.inline.}= +proc rotate180*(v:var Vector2d){.inline.}= ## Quickly rotates vector `v` 180 degrees counter clockwise, ## without using any trigonometrics. v.x= -v.x v.y= -v.y -proc rotate270*(v:var TVector2d) {.inline.}= +proc rotate270*(v:var Vector2d) {.inline.}= ## Quickly rotates vector `v` 270 degrees counter clockwise, ## without using any trigonometrics. swap(v.x,v.y) v.y= -v.y -proc rotate*(v:var TVector2d,rad:float) = +proc rotate*(v:var Vector2d,rad:float) = ## Rotates vector `v` `rad` radians in place. let s=sin(rad) @@ -511,18 +511,18 @@ proc rotate*(v:var TVector2d,rad:float) = v.y=c*v.y+s*v.x v.x=newx -proc scale*(v:var TVector2d,fac:float){.inline.}= +proc scale*(v:var Vector2d,fac:float){.inline.}= ## Scales vector `v` `rad` radians in place. v.x*=fac v.y*=fac -proc stretch*(v:var TVector2d,facx,facy:float){.inline.}= +proc stretch*(v:var Vector2d,facx,facy:float){.inline.}= ## Stretches vector `v` `facx` times horizontally, ## and `facy` times vertically. v.x*=facx v.y*=facy -proc mirror*(v:var TVector2d,mirrvec:TVector2d)= +proc mirror*(v:var Vector2d,mirrvec:Vector2d)= ## Mirrors vector `v` using `mirrvec` as mirror direction. let sqx=mirrvec.x*mirrvec.x @@ -539,7 +539,7 @@ proc mirror*(v:var TVector2d,mirrvec:TVector2d)= v.x=newx -proc `-` *(v:TVector2d):TVector2d= +proc `-` *(v:Vector2d):Vector2d= ## Negates a vector result.x= -v.x result.y= -v.y @@ -555,27 +555,27 @@ makeBinOpAssignVector(`*=`) makeBinOpAssignVector(`/=`) -proc dot*(v1,v2:TVector2d):float= +proc dot*(v1,v2:Vector2d):float= ## Computes the dot product of two vectors. ## Returns 0.0 if the vectors are perpendicular. return v1.x*v2.x+v1.y*v2.y -proc cross*(v1,v2:TVector2d):float= +proc cross*(v1,v2:Vector2d):float= ## Computes the cross product of two vectors, also called ## the 'perpendicular dot product' in 2d. Returns 0.0 if the vectors ## are parallel. return v1.x*v2.y-v1.y*v2.x -proc equals*(v1,v2:TVector2d,tol=1.0e-6):bool= +proc equals*(v1,v2:Vector2d,tol=1.0e-6):bool= ## Checks if two vectors approximately equals with a tolerance. return abs(v2.x-v1.x)<=tol and abs(v2.y-v1.y)<=tol -proc `=~` *(v1,v2:TVector2d):bool= +proc `=~` *(v1,v2:Vector2d):bool= ## Checks if two vectors approximately equals with a ## hardcoded tolerance 1e-6 equals(v1,v2) -proc angleTo*(v1,v2:TVector2d):float= +proc angleTo*(v1,v2:Vector2d):float= ## Returns the smallest of the two possible angles ## between `v1` and `v2` in radians. var @@ -585,7 +585,7 @@ proc angleTo*(v1,v2:TVector2d):float= return 0.0 # zero length vector has zero angle to any other vector return safeArccos(dot(nv1,nv2)) -proc angleCCW*(v1,v2:TVector2d):float= +proc angleCCW*(v1,v2:Vector2d):float= ## Returns the counter clockwise plane angle from `v1` to `v2`, ## in range 0 - 2*PI let a=v1.angleTo(v2) @@ -593,7 +593,7 @@ proc angleCCW*(v1,v2:TVector2d):float= return a return DEG360-a -proc angleCW*(v1,v2:TVector2d):float= +proc angleCW*(v1,v2:Vector2d):float= ## Returns the clockwise plane angle from `v1` to `v2`, ## in range 0 - 2*PI let a=v1.angleTo(v2) @@ -601,7 +601,7 @@ proc angleCW*(v1,v2:TVector2d):float= return a return DEG360-a -proc turnAngle*(v1,v2:TVector2d):float= +proc turnAngle*(v1,v2:Vector2d):float= ## Returns the amount v1 should be rotated (in radians) to equal v2, ## in range -PI to PI let a=v1.angleTo(v2) @@ -609,7 +609,7 @@ proc turnAngle*(v1,v2:TVector2d):float= return -a return a -proc bisect*(v1,v2:TVector2d):TVector2d {.noInit.}= +proc bisect*(v1,v2:Vector2d):Vector2d {.noInit.}= ## Computes the bisector between v1 and v2 as a normalized vector. ## If one of the input vectors has zero length, a normalized version ## of the other is returned. If both input vectors has zero length, @@ -645,24 +645,24 @@ proc bisect*(v1,v2:TVector2d):TVector2d {.noInit.}= # *************************************** -# TPoint2d implementation +# Point2d implementation # *************************************** -proc point2d*(x,y:float):TPoint2d = +proc point2d*(x,y:float):Point2d = result.x=x result.y=y -proc sqrDist*(a,b:TPoint2d):float= +proc sqrDist*(a,b:Point2d):float= ## Computes the squared distance between `a` and `b` let dx=b.x-a.x let dy=b.y-a.y result=dx*dx+dy*dy -proc dist*(a,b:TPoint2d):float {.inline.}= +proc dist*(a,b:Point2d):float {.inline.}= ## Computes the absolute distance between `a` and `b` result=sqrt(sqrDist(a,b)) -proc angle*(a,b:TPoint2d):float= +proc angle*(a,b:Point2d):float= ## Computes the angle of the vector `b`-`a` let dx=b.x-a.x let dy=b.y-a.y @@ -670,13 +670,13 @@ proc angle*(a,b:TPoint2d):float= if result<0: result += DEG360 -proc `$` *(p:TPoint2d):string= +proc `$` *(p:Point2d):string= ## String representation of `p` result=rtos(p.x) result.add(",") result.add(rtos(p.y)) -proc `&`*(p:TPoint2d,t:TMatrix2d):TPoint2d {.noInit,inline.} = +proc `&`*(p:Point2d,t:Matrix2d):Point2d {.noInit,inline.} = ## Concatenates a point `p` with a transform `t`, ## resulting in a new, transformed point. @@ -686,14 +686,14 @@ proc `&`*(p:TPoint2d,t:TMatrix2d):TPoint2d {.noInit,inline.} = result.x=p.x*t.ax+p.y*t.bx+t.tx result.y=p.x*t.ay+p.y*t.by+t.ty -proc `&=` *(p:var TPoint2d,t:TMatrix2d) {.inline.}= +proc `&=` *(p:var Point2d,t:Matrix2d) {.inline.}= ## Applies transformation `t` onto `p` in place. let newx=p.x*t.ax+p.y*t.bx+t.tx p.y=p.x*t.ay+p.y*t.by+t.ty p.x=newx -proc transformInv*(p:var TPoint2d,t:TMatrix2d){.inline.}= +proc transformInv*(p:var Point2d,t:Matrix2d){.inline.}= ## Applies the inverse of transformation `t` onto `p` in place. ## If the matrix is not invertable (determinant=0) , EDivByZero will ## be raised. @@ -710,48 +710,48 @@ proc transformInv*(p:var TPoint2d,t:TMatrix2d){.inline.}= p.x=newx -proc `+`*(p:TPoint2d,v:TVector2d):TPoint2d {.noInit,inline.} = +proc `+`*(p:Point2d,v:Vector2d):Point2d {.noInit,inline.} = ## Adds a vector `v` to a point `p`, resulting ## in a new point. result.x=p.x+v.x result.y=p.y+v.y -proc `+=`*(p:var TPoint2d,v:TVector2d) {.noInit,inline.} = +proc `+=`*(p:var Point2d,v:Vector2d) {.noInit,inline.} = ## Adds a vector `v` to a point `p` in place. p.x+=v.x p.y+=v.y -proc `-`*(p:TPoint2d,v:TVector2d):TPoint2d {.noInit,inline.} = +proc `-`*(p:Point2d,v:Vector2d):Point2d {.noInit,inline.} = ## Subtracts a vector `v` from a point `p`, resulting ## in a new point. result.x=p.x-v.x result.y=p.y-v.y -proc `-`*(p1,p2:TPoint2d):TVector2d {.noInit,inline.} = +proc `-`*(p1,p2:Point2d):Vector2d {.noInit,inline.} = ## Subtracts `p2`from `p1` resulting in a difference vector. result.x=p1.x-p2.x result.y=p1.y-p2.y -proc `-=`*(p:var TPoint2d,v:TVector2d) {.noInit,inline.} = +proc `-=`*(p:var Point2d,v:Vector2d) {.noInit,inline.} = ## Subtracts a vector `v` from a point `p` in place. p.x-=v.x p.y-=v.y -proc equals(p1,p2:TPoint2d,tol=1.0e-6):bool {.inline.}= +proc equals(p1,p2:Point2d,tol=1.0e-6):bool {.inline.}= ## Checks if two points approximately equals with a tolerance. return abs(p2.x-p1.x)<=tol and abs(p2.y-p1.y)<=tol -proc `=~`*(p1,p2:TPoint2d):bool {.inline.}= +proc `=~`*(p1,p2:Point2d):bool {.inline.}= ## Checks if two vectors approximately equals with a ## hardcoded tolerance 1e-6 equals(p1,p2) -proc polar*(p:TPoint2d,ang,dist:float):TPoint2d {.noInit.} = +proc polar*(p:Point2d,ang,dist:float):Point2d {.noInit.} = ## Returns a point with a given angle and distance away from `p` result.x=p.x+cos(ang)*dist result.y=p.y+sin(ang)*dist -proc rotate*(p:var TPoint2d,rad:float)= +proc rotate*(p:var Point2d,rad:float)= ## Rotates a point in place `rad` radians around origo. let c=cos(rad) @@ -760,7 +760,7 @@ proc rotate*(p:var TPoint2d,rad:float)= p.y=p.y*c+p.x*s p.x=newx -proc rotate*(p:var TPoint2d,rad:float,org:TPoint2d)= +proc rotate*(p:var Point2d,rad:float,org:Point2d)= ## Rotates a point in place `rad` radians using `org` as ## center of rotation. let @@ -770,50 +770,50 @@ proc rotate*(p:var TPoint2d,rad:float,org:TPoint2d)= p.y=(p.y - org.y) * c + (p.x - org.x) * s + org.y p.x=newx -proc scale*(p:var TPoint2d,fac:float) {.inline.}= +proc scale*(p:var Point2d,fac:float) {.inline.}= ## Scales a point in place `fac` times with world origo as origin. p.x*=fac p.y*=fac -proc scale*(p:var TPoint2d,fac:float,org:TPoint2d){.inline.}= +proc scale*(p:var Point2d,fac:float,org:Point2d){.inline.}= ## Scales the point in place `fac` times with `org` as origin. p.x=(p.x - org.x) * fac + org.x p.y=(p.y - org.y) * fac + org.y -proc stretch*(p:var TPoint2d,facx,facy:float){.inline.}= +proc stretch*(p:var Point2d,facx,facy:float){.inline.}= ## Scales a point in place non uniformly `facx` and `facy` times with ## world origo as origin. p.x*=facx p.y*=facy -proc stretch*(p:var TPoint2d,facx,facy:float,org:TPoint2d){.inline.}= +proc stretch*(p:var Point2d,facx,facy:float,org:Point2d){.inline.}= ## Scales the point in place non uniformly `facx` and `facy` times with ## `org` as origin. p.x=(p.x - org.x) * facx + org.x p.y=(p.y - org.y) * facy + org.y -proc move*(p:var TPoint2d,dx,dy:float){.inline.}= +proc move*(p:var Point2d,dx,dy:float){.inline.}= ## Translates a point `dx`, `dy` in place. p.x+=dx p.y+=dy -proc move*(p:var TPoint2d,v:TVector2d){.inline.}= +proc move*(p:var Point2d,v:Vector2d){.inline.}= ## Translates a point with vector `v` in place. p.x+=v.x p.y+=v.y -proc sgnArea*(a,b,c:TPoint2d):float= +proc sgnArea*(a,b,c:Point2d):float= ## Computes the signed area of the triangle thru points `a`,`b` and `c` ## result>0.0 for counter clockwise triangle ## result<0.0 for clockwise triangle ## This is commonly used to determinate side of a point with respect to a line. return ((b.x - c.x) * (b.y - a.y)-(b.y - c.y) * (b.x - a.x))*0.5 -proc area*(a,b,c:TPoint2d):float= +proc area*(a,b,c:Point2d):float= ## Computes the area of the triangle thru points `a`,`b` and `c` return abs(sgnArea(a,b,c)) -proc closestPoint*(p:TPoint2d,pts:varargs[TPoint2d]):TPoint2d= +proc closestPoint*(p:Point2d,pts:varargs[Point2d]):Point2d= ## Returns a point selected from `pts`, that has the closest ## euclidean distance to `p` assert(pts.len>0) # must have at least one point diff --git a/lib/pure/basic3d.nim b/lib/pure/basic3d.nim index 5a943dd05..b99357e3a 100644 --- a/lib/pure/basic3d.nim +++ b/lib/pure/basic3d.nim @@ -25,25 +25,25 @@ import times ## ## # Create a matrix which first rotates, then scales and at last translates ## -## var m:TMatrix3d=rotate(PI,vector3d(1,1,2.5)) & scale(2.0) & move(100.0,200.0,300.0) +## var m:Matrix3d=rotate(PI,vector3d(1,1,2.5)) & scale(2.0) & move(100.0,200.0,300.0) ## ## # Create a 3d point at (100,150,200) and a vector (5,2,3) ## -## var pt:TPoint3d=point3d(100.0,150.0,200.0) +## var pt:Point3d=point3d(100.0,150.0,200.0) ## -## var vec:TVector3d=vector3d(5.0,2.0,3.0) +## var vec:Vector3d=vector3d(5.0,2.0,3.0) ## ## ## pt &= m # transforms pt in place ## -## var pt2:TPoint3d=pt & m #concatenates pt with m and returns a new point +## var pt2:Point3d=pt & m #concatenates pt with m and returns a new point ## -## var vec2:TVector3d=vec & m #concatenates vec with m and returns a new vector +## var vec2:Vector3d=vec & m #concatenates vec with m and returns a new vector type - TMatrix3d* =object + Matrix3d* =object ## Implements a row major 3d matrix, which means ## transformations are applied the order they are concatenated. ## This matrix is stored as an 4x4 matrix: @@ -52,31 +52,31 @@ type ## [ cx cy cz cw ] ## [ tx ty tz tw ] ax*,ay*,az*,aw*, bx*,by*,bz*,bw*, cx*,cy*,cz*,cw*, tx*,ty*,tz*,tw*:float - TPoint3d* = object + Point3d* = object ## Implements a non-homegeneous 2d point stored as ## an `x` , `y` and `z` coordinate. x*,y*,z*:float - TVector3d* = object + Vector3d* = object ## Implements a 3d **direction vector** stored as ## an `x` , `y` and `z` coordinate. Direction vector means, ## that when transforming a vector with a matrix, the translational ## part of the matrix is ignored. x*,y*,z*:float - +{.deprecated: [TMatrix3d: Matrix3d, TPoint3d: Point3d, TVector3d: Vector3d].} # Some forward declarations -proc matrix3d*(ax,ay,az,aw,bx,by,bz,bw,cx,cy,cz,cw,tx,ty,tz,tw:float):TMatrix3d {.noInit.} +proc matrix3d*(ax,ay,az,aw,bx,by,bz,bw,cx,cy,cz,cw,tx,ty,tz,tw:float):Matrix3d {.noInit.} ## Creates a new 4x4 3d transformation matrix. ## `ax` , `ay` , `az` is the local x axis. ## `bx` , `by` , `bz` is the local y axis. ## `cx` , `cy` , `cz` is the local z axis. ## `tx` , `ty` , `tz` is the translation. -proc vector3d*(x,y,z:float):TVector3d {.noInit,inline.} +proc vector3d*(x,y,z:float):Vector3d {.noInit,inline.} ## Returns a new 3d vector (`x`,`y`,`z`) -proc point3d*(x,y,z:float):TPoint3d {.noInit,inline.} +proc point3d*(x,y,z:float):Point3d {.noInit,inline.} ## Returns a new 4d point (`x`,`y`,`z`) -proc tryNormalize*(v:var TVector3d):bool +proc tryNormalize*(v:var Vector3d):bool ## Modifies `v` to have a length of 1.0, keeping its angle. ## If `v` has zero length (and thus no angle), it is left unmodified and false is ## returned, otherwise true is returned. @@ -84,19 +84,19 @@ proc tryNormalize*(v:var TVector3d):bool let - IDMATRIX*:TMatrix3d=matrix3d( + IDMATRIX*:Matrix3d=matrix3d( 1.0,0.0,0.0,0.0, 0.0,1.0,0.0,0.0, 0.0,0.0,1.0,0.0, 0.0,0.0,0.0,1.0) ## Quick access to a 3d identity matrix - ORIGO*:TPoint3d=point3d(0.0,0.0,0.0) + ORIGO*:Point3d=point3d(0.0,0.0,0.0) ## Quick access to point (0,0) - XAXIS*:TVector3d=vector3d(1.0,0.0,0.0) + XAXIS*:Vector3d=vector3d(1.0,0.0,0.0) ## Quick access to an 3d x-axis unit vector - YAXIS*:TVector3d=vector3d(0.0,1.0,0.0) + YAXIS*:Vector3d=vector3d(0.0,1.0,0.0) ## Quick access to an 3d y-axis unit vector - ZAXIS*:TVector3d=vector3d(0.0,0.0,1.0) + ZAXIS*:Vector3d=vector3d(0.0,0.0,1.0) ## Quick access to an 3d z-axis unit vector @@ -116,27 +116,27 @@ proc safeArccos(v:float):float= template makeBinOpVector(s:expr)= ## implements binary operators + , - , * and / for vectors - proc s*(a,b:TVector3d):TVector3d {.inline,noInit.} = + proc s*(a,b:Vector3d):Vector3d {.inline,noInit.} = vector3d(s(a.x,b.x),s(a.y,b.y),s(a.z,b.z)) - proc s*(a:TVector3d,b:float):TVector3d {.inline,noInit.} = + proc s*(a:Vector3d,b:float):Vector3d {.inline,noInit.} = vector3d(s(a.x,b),s(a.y,b),s(a.z,b)) - proc s*(a:float,b:TVector3d):TVector3d {.inline,noInit.} = + proc s*(a:float,b:Vector3d):Vector3d {.inline,noInit.} = vector3d(s(a,b.x),s(a,b.y),s(a,b.z)) template makeBinOpAssignVector(s:expr)= ## implements inplace binary operators += , -= , /= and *= for vectors - proc s*(a:var TVector3d,b:TVector3d) {.inline.} = + proc s*(a:var Vector3d,b:Vector3d) {.inline.} = s(a.x,b.x) ; s(a.y,b.y) ; s(a.z,b.z) - proc s*(a:var TVector3d,b:float) {.inline.} = + proc s*(a:var Vector3d,b:float) {.inline.} = s(a.x,b) ; s(a.y,b) ; s(a.z,b) # *************************************** -# TMatrix3d implementation +# Matrix3d implementation # *************************************** -proc setElements*(t:var TMatrix3d,ax,ay,az,aw,bx,by,bz,bw,cx,cy,cz,cw,tx,ty,tz,tw:float) {.inline.}= +proc setElements*(t:var Matrix3d,ax,ay,az,aw,bx,by,bz,bw,cx,cy,cz,cw,tx,ty,tz,tw:float) {.inline.}= ## Sets arbitrary elements in an exisitng matrix. t.ax=ax t.ay=ay @@ -155,10 +155,10 @@ proc setElements*(t:var TMatrix3d,ax,ay,az,aw,bx,by,bz,bw,cx,cy,cz,cw,tx,ty,tz,t t.tz=tz t.tw=tw -proc matrix3d*(ax,ay,az,aw,bx,by,bz,bw,cx,cy,cz,cw,tx,ty,tz,tw:float):TMatrix3d = +proc matrix3d*(ax,ay,az,aw,bx,by,bz,bw,cx,cy,cz,cw,tx,ty,tz,tw:float):Matrix3d = result.setElements(ax,ay,az,aw,bx,by,bz,bw,cx,cy,cz,cw,tx,ty,tz,tw) -proc `&`*(a,b:TMatrix3d):TMatrix3d {.noinit.} = +proc `&`*(a,b:Matrix3d):Matrix3d {.noinit.} = ## Concatenates matrices returning a new matrix. result.setElements( a.aw*b.tx+a.az*b.cx+a.ay*b.bx+a.ax*b.ax, @@ -182,36 +182,36 @@ proc `&`*(a,b:TMatrix3d):TMatrix3d {.noinit.} = a.tw*b.tw+a.tz*b.cw+a.ty*b.bw+a.tx*b.aw) -proc scale*(s:float):TMatrix3d {.noInit.} = +proc scale*(s:float):Matrix3d {.noInit.} = ## Returns a new scaling matrix. result.setElements(s,0,0,0, 0,s,0,0, 0,0,s,0, 0,0,0,1) -proc scale*(s:float,org:TPoint3d):TMatrix3d {.noInit.} = +proc scale*(s:float,org:Point3d):Matrix3d {.noInit.} = ## Returns a new scaling matrix using, `org` as scale origin. result.setElements(s,0,0,0, 0,s,0,0, 0,0,s,0, org.x-s*org.x,org.y-s*org.y,org.z-s*org.z,1.0) -proc stretch*(sx,sy,sz:float):TMatrix3d {.noInit.} = +proc stretch*(sx,sy,sz:float):Matrix3d {.noInit.} = ## Returns new a stretch matrix, which is a ## scale matrix with non uniform scale in x,y and z. result.setElements(sx,0,0,0, 0,sy,0,0, 0,0,sz,0, 0,0,0,1) -proc stretch*(sx,sy,sz:float,org:TPoint3d):TMatrix3d {.noInit.} = +proc stretch*(sx,sy,sz:float,org:Point3d):Matrix3d {.noInit.} = ## Returns a new stretch matrix, which is a ## scale matrix with non uniform scale in x,y and z. ## `org` is used as stretch origin. result.setElements(sx,0,0,0, 0,sy,0,0, 0,0,sz,0, org.x-sx*org.x,org.y-sy*org.y,org.z-sz*org.z,1) -proc move*(dx,dy,dz:float):TMatrix3d {.noInit.} = +proc move*(dx,dy,dz:float):Matrix3d {.noInit.} = ## Returns a new translation matrix. result.setElements(1,0,0,0, 0,1,0,0, 0,0,1,0, dx,dy,dz,1) -proc move*(v:TVector3d):TMatrix3d {.noInit.} = +proc move*(v:Vector3d):Matrix3d {.noInit.} = ## Returns a new translation matrix from a vector. result.setElements(1,0,0,0, 0,1,0,0, 0,0,1,0, v.x,v.y,v.z,1) -proc rotate*(angle:float,axis:TVector3d):TMatrix3d {.noInit.}= +proc rotate*(angle:float,axis:Vector3d):Matrix3d {.noInit.}= ## Creates a rotation matrix that rotates `angle` radians over ## `axis`, which passes through origo. @@ -242,7 +242,7 @@ proc rotate*(angle:float,axis:TVector3d):TMatrix3d {.noInit.}= uwomc+vsi, vwomc-usi, w2+(1.0-w2)*cs, 0.0, 0.0,0.0,0.0,1.0) -proc rotate*(angle:float,org:TPoint3d,axis:TVector3d):TMatrix3d {.noInit.}= +proc rotate*(angle:float,org:Point3d,axis:Vector3d):Matrix3d {.noInit.}= ## Creates a rotation matrix that rotates `angle` radians over ## `axis`, which passes through `org`. @@ -282,7 +282,7 @@ proc rotate*(angle:float,org:TPoint3d,axis:TVector3d):TMatrix3d {.noInit.}= (c*(u2+v2)-w*(a*u+b*v))*omc+(a*v-b*u)*si,1.0) -proc rotateX*(angle:float):TMatrix3d {.noInit.}= +proc rotateX*(angle:float):Matrix3d {.noInit.}= ## Creates a matrix that rotates around the x-axis with `angle` radians, ## which is also called a 'roll' matrix. let @@ -294,7 +294,7 @@ proc rotateX*(angle:float):TMatrix3d {.noInit.}= 0,-s,c,0, 0,0,0,1) -proc rotateY*(angle:float):TMatrix3d {.noInit.}= +proc rotateY*(angle:float):Matrix3d {.noInit.}= ## Creates a matrix that rotates around the y-axis with `angle` radians, ## which is also called a 'pitch' matrix. let @@ -306,7 +306,7 @@ proc rotateY*(angle:float):TMatrix3d {.noInit.}= s,0,c,0, 0,0,0,1) -proc rotateZ*(angle:float):TMatrix3d {.noInit.}= +proc rotateZ*(angle:float):Matrix3d {.noInit.}= ## Creates a matrix that rotates around the z-axis with `angle` radians, ## which is also called a 'yaw' matrix. let @@ -318,7 +318,7 @@ proc rotateZ*(angle:float):TMatrix3d {.noInit.}= 0,0,1,0, 0,0,0,1) -proc isUniform*(m:TMatrix3d,tol=1.0e-6):bool= +proc isUniform*(m:Matrix3d,tol=1.0e-6):bool= ## Checks if the transform is uniform, that is ## perpendicular axes of equal length, which means (for example) ## it cannot transform a sphere into an ellipsoid. @@ -341,7 +341,7 @@ proc isUniform*(m:TMatrix3d,tol=1.0e-6):bool= -proc mirror*(planeperp:TVector3d):TMatrix3d {.noInit.}= +proc mirror*(planeperp:Vector3d):Matrix3d {.noInit.}= ## Creates a matrix that mirrors over the plane that has `planeperp` as normal, ## and passes through origo. `planeperp` does not need to be normalized. @@ -365,7 +365,7 @@ proc mirror*(planeperp:TVector3d):TMatrix3d {.noInit.}= 0,0,0,1) -proc mirror*(org:TPoint3d,planeperp:TVector3d):TMatrix3d {.noInit.}= +proc mirror*(org:Point3d,planeperp:Vector3d):Matrix3d {.noInit.}= ## Creates a matrix that mirrors over the plane that has `planeperp` as normal, ## and passes through `org`. `planeperp` does not need to be normalized. @@ -400,7 +400,7 @@ proc mirror*(org:TPoint3d,planeperp:TVector3d):TMatrix3d {.noInit.}= 2*(cc*tz+bc*ty+ac*tx) ,1) -proc determinant*(m:TMatrix3d):float= +proc determinant*(m:Matrix3d):float= ## Computes the determinant of matrix `m`. # This computation is gotten from ratsimp(optimize(determinant(m))) @@ -419,7 +419,7 @@ proc determinant*(m:TMatrix3d):float= (O3*m.az-O5*m.ay+O6*m.ax)*m.bw -proc inverse*(m:TMatrix3d):TMatrix3d {.noInit.}= +proc inverse*(m:Matrix3d):Matrix3d {.noInit.}= ## Computes the inverse of matrix `m`. If the matrix ## determinant is zero, thus not invertible, a EDivByZero ## will be raised. @@ -461,7 +461,7 @@ proc inverse*(m:TMatrix3d):TMatrix3d {.noInit.}= (-m.ax*O7+m.ay*O14-m.az*O18)/det , (m.ax*O10-m.ay*O16+m.az*O19)/det) -proc equals*(m1:TMatrix3d,m2:TMatrix3d,tol=1.0e-6):bool= +proc equals*(m1:Matrix3d,m2:Matrix3d,tol=1.0e-6):bool= ## Checks if all elements of `m1`and `m2` is equal within ## a given tolerance `tol`. return @@ -482,42 +482,42 @@ proc equals*(m1:TMatrix3d,m2:TMatrix3d,tol=1.0e-6):bool= abs(m1.tz-m2.tz)<=tol and abs(m1.tw-m2.tw)<=tol -proc `=~`*(m1,m2:TMatrix3d):bool= +proc `=~`*(m1,m2:Matrix3d):bool= ## Checks if `m1` and `m2` is approximately equal, using a ## tolerance of 1e-6. equals(m1,m2) -proc transpose*(m:TMatrix3d):TMatrix3d {.noInit.}= +proc transpose*(m:Matrix3d):Matrix3d {.noInit.}= ## Returns the transpose of `m` result.setElements(m.ax,m.bx,m.cx,m.tx,m.ay,m.by,m.cy,m.ty,m.az,m.bz,m.cz,m.tz,m.aw,m.bw,m.cw,m.tw) -proc getXAxis*(m:TMatrix3d):TVector3d {.noInit.}= +proc getXAxis*(m:Matrix3d):Vector3d {.noInit.}= ## Gets the local x axis of `m` result.x=m.ax result.y=m.ay result.z=m.az -proc getYAxis*(m:TMatrix3d):TVector3d {.noInit.}= +proc getYAxis*(m:Matrix3d):Vector3d {.noInit.}= ## Gets the local y axis of `m` result.x=m.bx result.y=m.by result.z=m.bz -proc getZAxis*(m:TMatrix3d):TVector3d {.noInit.}= +proc getZAxis*(m:Matrix3d):Vector3d {.noInit.}= ## Gets the local y axis of `m` result.x=m.cx result.y=m.cy result.z=m.cz -proc `$`*(m:TMatrix3d):string= +proc `$`*(m:Matrix3d):string= ## String representation of `m` return rtos(m.ax) & "," & rtos(m.ay) & "," & rtos(m.az) & "," & rtos(m.aw) & "\n" & rtos(m.bx) & "," & rtos(m.by) & "," & rtos(m.bz) & "," & rtos(m.bw) & "\n" & rtos(m.cx) & "," & rtos(m.cy) & "," & rtos(m.cz) & "," & rtos(m.cw) & "\n" & rtos(m.tx) & "," & rtos(m.ty) & "," & rtos(m.tz) & "," & rtos(m.tw) -proc apply*(m:TMatrix3d, x,y,z:var float, translate=false)= +proc apply*(m:Matrix3d, x,y,z:var float, translate=false)= ## Applies transformation `m` onto `x` , `y` , `z` , optionally ## using the translation part of the matrix. let @@ -535,18 +535,18 @@ proc apply*(m:TMatrix3d, x,y,z:var float, translate=false)= z+=m.tz # *************************************** -# TVector3d implementation +# Vector3d implementation # *************************************** -proc vector3d*(x,y,z:float):TVector3d= +proc vector3d*(x,y,z:float):Vector3d= result.x=x result.y=y result.z=z -proc len*(v:TVector3d):float= +proc len*(v:Vector3d):float= ## Returns the length of the vector `v`. sqrt(v.x*v.x+v.y*v.y+v.z*v.z) -proc `len=`*(v:var TVector3d,newlen:float) {.noInit.} = +proc `len=`*(v:var Vector3d,newlen:float) {.noInit.} = ## Sets the length of the vector, keeping its direction. ## If the vector has zero length before changing it's length, ## an arbitrary vector of the requested length is returned. @@ -571,12 +571,12 @@ proc `len=`*(v:var TVector3d,newlen:float) {.noInit.} = v.z*=fac -proc sqrLen*(v:TVector3d):float {.inline.}= +proc sqrLen*(v:Vector3d):float {.inline.}= ## Computes the squared length of the vector, which is ## faster than computing the absolute length. return v.x*v.x+v.y*v.y+v.z*v.z -proc `$` *(v:TVector3d):string= +proc `$` *(v:Vector3d):string= ## String representation of `v` result=rtos(v.x) result.add(",") @@ -584,7 +584,7 @@ proc `$` *(v:TVector3d):string= result.add(",") result.add(rtos(v.z)) -proc `&` *(v:TVector3d,m:TMatrix3d):TVector3d {.noInit.} = +proc `&` *(v:Vector3d,m:Matrix3d):Vector3d {.noInit.} = ## Concatenate vector `v` with a transformation matrix. ## Transforming a vector ignores the translational part ## of the matrix. @@ -601,7 +601,7 @@ proc `&` *(v:TVector3d,m:TMatrix3d):TVector3d {.noInit.} = result.x=newx -proc `&=` *(v:var TVector3d,m:TMatrix3d) {.noInit.} = +proc `&=` *(v:var Vector3d,m:Matrix3d) {.noInit.} = ## Applies transformation `m` onto `v` in place. ## Transforming a vector ignores the translational part ## of the matrix. @@ -618,7 +618,7 @@ proc `&=` *(v:var TVector3d,m:TMatrix3d) {.noInit.} = v.y=newy v.x=newx -proc transformNorm*(v:var TVector3d,m:TMatrix3d)= +proc transformNorm*(v:var Vector3d,m:Matrix3d)= ## Applies a normal direction transformation `m` onto `v` in place. ## The resulting vector is *not* normalized. Transforming a vector ignores the ## translational part of the matrix. If the matrix is not invertible @@ -631,7 +631,7 @@ proc transformNorm*(v:var TVector3d,m:TMatrix3d)= # (possibly by hardware) as well as having a consistent API with the 2d version. v&=transpose(inverse(m)) -proc transformInv*(v:var TVector3d,m:TMatrix3d)= +proc transformInv*(v:var Vector3d,m:Matrix3d)= ## Applies the inverse of `m` on vector `v`. Transforming a vector ignores ## the translational part of the matrix. Transforming a vector ignores the ## translational part of the matrix. @@ -642,7 +642,7 @@ proc transformInv*(v:var TVector3d,m:TMatrix3d)= # (possibly by hardware) as well as having a consistent API with the 2d version. v&=m.inverse -proc transformNormInv*(vec:var TVector3d,m:TMatrix3d)= +proc transformNormInv*(vec:var Vector3d,m:Matrix3d)= ## Applies an inverse normal direction transformation `m` onto `v` in place. ## This is faster than creating an inverse ## matrix and transformNorm(...) it. Transforming a vector ignores the @@ -651,7 +651,7 @@ proc transformNormInv*(vec:var TVector3d,m:TMatrix3d)= # see vector2d:s equivalent for a deeper look how/why this works vec&=m.transpose -proc tryNormalize*(v:var TVector3d):bool= +proc tryNormalize*(v:var Vector3d):bool= ## Modifies `v` to have a length of 1.0, keeping its angle. ## If `v` has zero length (and thus no angle), it is left unmodified and false is ## returned, otherwise true is returned. @@ -666,13 +666,13 @@ proc tryNormalize*(v:var TVector3d):bool= return true -proc normalize*(v:var TVector3d) {.inline.}= +proc normalize*(v:var Vector3d) {.inline.}= ## Modifies `v` to have a length of 1.0, keeping its angle. ## If `v` has zero length, an EDivByZero will be raised. if not tryNormalize(v): raise newException(DivByZeroError,"Cannot normalize zero length vector") -proc rotate*(vec:var TVector3d,angle:float,axis:TVector3d)= +proc rotate*(vec:var Vector3d,angle:float,axis:Vector3d)= ## Rotates `vec` in place, with `angle` radians over `axis`, which passes ## through origo. @@ -699,19 +699,19 @@ proc rotate*(vec:var TVector3d,angle:float,axis:TVector3d)= vec.y=v*uxyzomc+y*cs+(w*x-u*z)*si vec.z=w*uxyzomc+z*cs+(u*y-v*x)*si -proc scale*(v:var TVector3d,s:float)= +proc scale*(v:var Vector3d,s:float)= ## Scales the vector in place with factor `s` v.x*=s v.y*=s v.z*=s -proc stretch*(v:var TVector3d,sx,sy,sz:float)= +proc stretch*(v:var Vector3d,sx,sy,sz:float)= ## Scales the vector non uniformly with factors `sx` , `sy` , `sz` v.x*=sx v.y*=sy v.z*=sz -proc mirror*(v:var TVector3d,planeperp:TVector3d)= +proc mirror*(v:var Vector3d,planeperp:Vector3d)= ## Computes the mirrored vector of `v` over the plane ## that has `planeperp` as normal direction. ## `planeperp` does not need to be normalized. @@ -735,7 +735,7 @@ proc mirror*(v:var TVector3d,planeperp:TVector3d)= v.z= -2*(c*c*z+bc*y+ac*x)+z -proc `-` *(v:TVector3d):TVector3d= +proc `-` *(v:Vector3d):Vector3d= ## Negates a vector result.x= -v.x result.y= -v.y @@ -751,12 +751,12 @@ makeBinOpAssignVector(`-=`) makeBinOpAssignVector(`*=`) makeBinOpAssignVector(`/=`) -proc dot*(v1,v2:TVector3d):float {.inline.}= +proc dot*(v1,v2:Vector3d):float {.inline.}= ## Computes the dot product of two vectors. ## Returns 0.0 if the vectors are perpendicular. return v1.x*v2.x+v1.y*v2.y+v1.z*v2.z -proc cross*(v1,v2:TVector3d):TVector3d {.inline.}= +proc cross*(v1,v2:Vector3d):Vector3d {.inline.}= ## Computes the cross product of two vectors. ## The result is a vector which is perpendicular ## to the plane of `v1` and `v2`, which means @@ -766,16 +766,16 @@ proc cross*(v1,v2:TVector3d):TVector3d {.inline.}= result.y = (v1.z * v2.x) - (v2.z * v1.x) result.z = (v1.x * v2.y) - (v2.x * v1.y) -proc equals*(v1,v2:TVector3d,tol=1.0e-6):bool= +proc equals*(v1,v2:Vector3d,tol=1.0e-6):bool= ## Checks if two vectors approximately equals with a tolerance. return abs(v2.x-v1.x)<=tol and abs(v2.y-v1.y)<=tol and abs(v2.z-v1.z)<=tol -proc `=~` *(v1,v2:TVector3d):bool= +proc `=~` *(v1,v2:Vector3d):bool= ## Checks if two vectors approximately equals with a ## hardcoded tolerance 1e-6 equals(v1,v2) -proc angleTo*(v1,v2:TVector3d):float= +proc angleTo*(v1,v2:Vector3d):float= ## Returns the smallest angle between v1 and v2, ## which is in range 0-PI var @@ -785,13 +785,13 @@ proc angleTo*(v1,v2:TVector3d):float= return 0.0 # zero length vector has zero angle to any other vector return safeArccos(dot(nv1,nv2)) -proc arbitraryAxis*(norm:TVector3d):TMatrix3d {.noInit.}= +proc arbitraryAxis*(norm:Vector3d):Matrix3d {.noInit.}= ## Computes the rotation matrix that would transform ## world z vector into `norm`. The inverse of this matrix ## is useful to transform a planar 3d object to 2d space. ## This is the same algorithm used to interpret DXF and DWG files. const lim=1.0/64.0 - var ax,ay,az:TVector3d + var ax,ay,az:Vector3d if abs(norm.x)<lim and abs(norm.y)<lim: ax=cross(YAXIS,norm) else: @@ -808,7 +808,7 @@ proc arbitraryAxis*(norm:TVector3d):TMatrix3d {.noInit.}= az.x,az.y,az.z,0.0, 0.0,0.0,0.0,1.0) -proc bisect*(v1,v2:TVector3d):TVector3d {.noInit.}= +proc bisect*(v1,v2:Vector3d):Vector3d {.noInit.}= ## Computes the bisector between v1 and v2 as a normalized vector. ## If one of the input vectors has zero length, a normalized version ## of the other is returned. If both input vectors has zero length, @@ -851,25 +851,25 @@ proc bisect*(v1,v2:TVector3d):TVector3d {.noInit.}= # *************************************** -# TPoint3d implementation +# Point3d implementation # *************************************** -proc point3d*(x,y,z:float):TPoint3d= +proc point3d*(x,y,z:float):Point3d= result.x=x result.y=y result.z=z -proc sqrDist*(a,b:TPoint3d):float= +proc sqrDist*(a,b:Point3d):float= ## Computes the squared distance between `a`and `b` let dx=b.x-a.x let dy=b.y-a.y let dz=b.z-a.z result=dx*dx+dy*dy+dz*dz -proc dist*(a,b:TPoint3d):float {.inline.}= +proc dist*(a,b:Point3d):float {.inline.}= ## Computes the absolute distance between `a`and `b` result=sqrt(sqrDist(a,b)) -proc `$` *(p:TPoint3d):string= +proc `$` *(p:Point3d):string= ## String representation of `p` result=rtos(p.x) result.add(",") @@ -877,14 +877,14 @@ proc `$` *(p:TPoint3d):string= result.add(",") result.add(rtos(p.z)) -proc `&`*(p:TPoint3d,m:TMatrix3d):TPoint3d= +proc `&`*(p:Point3d,m:Matrix3d):Point3d= ## Concatenates a point `p` with a transform `m`, ## resulting in a new, transformed point. result.z=m.cz*p.z+m.bz*p.y+m.az*p.x+m.tz result.y=m.cy*p.z+m.by*p.y+m.ay*p.x+m.ty result.x=m.cx*p.z+m.bx*p.y+m.ax*p.x+m.tx -proc `&=` *(p:var TPoint3d,m:TMatrix3d)= +proc `&=` *(p:var Point3d,m:Matrix3d)= ## Applies transformation `m` onto `p` in place. let x=p.x @@ -894,7 +894,7 @@ proc `&=` *(p:var TPoint3d,m:TMatrix3d)= p.y=m.cy*z+m.by*y+m.ay*x+m.ty p.z=m.cz*z+m.bz*y+m.az*x+m.tz -proc transformInv*(p:var TPoint3d,m:TMatrix3d)= +proc transformInv*(p:var Point3d,m:Matrix3d)= ## Applies the inverse of transformation `m` onto `p` in place. ## If the matrix is not invertable (determinant=0) , EDivByZero will ## be raised. @@ -903,48 +903,48 @@ proc transformInv*(p:var TPoint3d,m:TMatrix3d)= p&=inverse(m) -proc `+`*(p:TPoint3d,v:TVector3d):TPoint3d {.noInit,inline.} = +proc `+`*(p:Point3d,v:Vector3d):Point3d {.noInit,inline.} = ## Adds a vector `v` to a point `p`, resulting ## in a new point. result.x=p.x+v.x result.y=p.y+v.y result.z=p.z+v.z -proc `+=`*(p:var TPoint3d,v:TVector3d) {.noInit,inline.} = +proc `+=`*(p:var Point3d,v:Vector3d) {.noInit,inline.} = ## Adds a vector `v` to a point `p` in place. p.x+=v.x p.y+=v.y p.z+=v.z -proc `-`*(p:TPoint3d,v:TVector3d):TPoint3d {.noInit,inline.} = +proc `-`*(p:Point3d,v:Vector3d):Point3d {.noInit,inline.} = ## Subtracts a vector `v` from a point `p`, resulting ## in a new point. result.x=p.x-v.x result.y=p.y-v.y result.z=p.z-v.z -proc `-`*(p1,p2:TPoint3d):TVector3d {.noInit,inline.} = +proc `-`*(p1,p2:Point3d):Vector3d {.noInit,inline.} = ## Subtracts `p2`from `p1` resulting in a difference vector. result.x=p1.x-p2.x result.y=p1.y-p2.y result.z=p1.z-p2.z -proc `-=`*(p:var TPoint3d,v:TVector3d) {.noInit,inline.} = +proc `-=`*(p:var Point3d,v:Vector3d) {.noInit,inline.} = ## Subtracts a vector `v` from a point `p` in place. p.x-=v.x p.y-=v.y p.z-=v.z -proc equals(p1,p2:TPoint3d,tol=1.0e-6):bool {.inline.}= +proc equals(p1,p2:Point3d,tol=1.0e-6):bool {.inline.}= ## Checks if two points approximately equals with a tolerance. return abs(p2.x-p1.x)<=tol and abs(p2.y-p1.y)<=tol and abs(p2.z-p1.z)<=tol -proc `=~`*(p1,p2:TPoint3d):bool {.inline.}= +proc `=~`*(p1,p2:Point3d):bool {.inline.}= ## Checks if two vectors approximately equals with a ## hardcoded tolerance 1e-6 equals(p1,p2) -proc rotate*(p:var TPoint3d,rad:float,axis:TVector3d)= +proc rotate*(p:var Point3d,rad:float,axis:Vector3d)= ## Rotates point `p` in place `rad` radians about an axis ## passing through origo. @@ -954,7 +954,7 @@ proc rotate*(p:var TPoint3d,rad:float,axis:TVector3d)= p.y=v.y p.z=v.z -proc rotate*(p:var TPoint3d,angle:float,org:TPoint3d,axis:TVector3d)= +proc rotate*(p:var Point3d,angle:float,org:Point3d,axis:Vector3d)= ## Rotates point `p` in place `rad` radians about an axis ## passing through `org` @@ -992,26 +992,26 @@ proc rotate*(p:var TPoint3d,angle:float,org:TPoint3d,axis:TVector3d)= p.y=(b*(uu+ww)-v*(au+cw-uxmvymwz))*omc + y*cs + (c*u-a*w+w*x-u*z)*si p.z=(c*(uu+vv)-w*(au+bv-uxmvymwz))*omc + z*cs + (a*v+u*y-b*u-v*x)*si -proc scale*(p:var TPoint3d,fac:float) {.inline.}= +proc scale*(p:var Point3d,fac:float) {.inline.}= ## Scales a point in place `fac` times with world origo as origin. p.x*=fac p.y*=fac p.z*=fac -proc scale*(p:var TPoint3d,fac:float,org:TPoint3d){.inline.}= +proc scale*(p:var Point3d,fac:float,org:Point3d){.inline.}= ## Scales the point in place `fac` times with `org` as origin. p.x=(p.x - org.x) * fac + org.x p.y=(p.y - org.y) * fac + org.y p.z=(p.z - org.z) * fac + org.z -proc stretch*(p:var TPoint3d,facx,facy,facz:float){.inline.}= +proc stretch*(p:var Point3d,facx,facy,facz:float){.inline.}= ## Scales a point in place non uniformly `facx` , `facy` , `facz` times ## with world origo as origin. p.x*=facx p.y*=facy p.z*=facz -proc stretch*(p:var TPoint3d,facx,facy,facz:float,org:TPoint3d){.inline.}= +proc stretch*(p:var Point3d,facx,facy,facz:float,org:Point3d){.inline.}= ## Scales the point in place non uniformly `facx` , `facy` , `facz` times ## with `org` as origin. p.x=(p.x - org.x) * facx + org.x @@ -1019,19 +1019,19 @@ proc stretch*(p:var TPoint3d,facx,facy,facz:float,org:TPoint3d){.inline.}= p.z=(p.z - org.z) * facz + org.z -proc move*(p:var TPoint3d,dx,dy,dz:float){.inline.}= +proc move*(p:var Point3d,dx,dy,dz:float){.inline.}= ## Translates a point `dx` , `dy` , `dz` in place. p.x+=dx p.y+=dy p.z+=dz -proc move*(p:var TPoint3d,v:TVector3d){.inline.}= +proc move*(p:var Point3d,v:Vector3d){.inline.}= ## Translates a point with vector `v` in place. p.x+=v.x p.y+=v.y p.z+=v.z -proc area*(a,b,c:TPoint3d):float {.inline.}= +proc area*(a,b,c:Point3d):float {.inline.}= ## Computes the area of the triangle thru points `a` , `b` and `c` # The area of a planar 3d quadliteral is the magnitude of the cross diff --git a/lib/pure/collections/LockFreeHash.nim b/lib/pure/collections/LockFreeHash.nim index 0df97c685..1758c5b1a 100644 --- a/lib/pure/collections/LockFreeHash.nim +++ b/lib/pure/collections/LockFreeHash.nim @@ -46,24 +46,25 @@ const when sizeof(int) == 4: # 32bit type - TRaw = range[0..1073741823] + Raw = range[0..1073741823] ## The range of uint values that can be stored directly in a value slot ## when on a 32 bit platform - + {.deprecated: [TRaw: Raw].} elif sizeof(int) == 8: # 64bit type - TRaw = range[0..4611686018427387903] + Raw = range[0..4611686018427387903] ## The range of uint values that can be stored directly in a value slot ## when on a 64 bit platform + {.deprecated: [TRaw: Raw].} else: {.error: "unsupported platform".} type - TEntry = tuple + Entry = tuple key: int value: int - TEntryArr = ptr array[0..10_000_000, TEntry] + EntryArr = ptr array[0..10_000_000, Entry] PConcTable[K,V] = ptr object {.pure.} len: int @@ -72,8 +73,8 @@ type copyIdx: int copyDone: int next: PConcTable[K,V] - data: TEntryArr - + data: EntryArr +{.deprecated: [TEntry: Entry, TEntryArr: EntryArr.} proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int, expVal: int, match: bool): int @@ -84,7 +85,7 @@ proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int, proc newLFTable*[K,V](size: int = minTableSize): PConcTable[K,V] = let dataLen = max(nextPowerOfTwo(size), minTableSize) - dataSize = dataLen*sizeof(TEntry) + dataSize = dataLen*sizeof(Entry) dataMem = allocShared0(dataSize) tableSize = 7 * intSize tableMem = allocShared0(tableSize) @@ -95,7 +96,7 @@ proc newLFTable*[K,V](size: int = minTableSize): PConcTable[K,V] = table.copyIdx = 0 table.copyDone = 0 table.next = nil - table.data = cast[TEntryArr](dataMem) + table.data = cast[EntryArr](dataMem) result = table #------------------------------------------------------------------------------ @@ -107,7 +108,7 @@ proc deleteConcTable[K,V](tbl: PConcTable[K,V]) = #------------------------------------------------------------------------------ -proc `[]`[K,V](table: var PConcTable[K,V], i: int): var TEntry {.inline.} = +proc `[]`[K,V](table: var PConcTable[K,V], i: int): var Entry {.inline.} = table.data[i] #------------------------------------------------------------------------------ @@ -191,7 +192,7 @@ proc resize[K,V](self: PConcTable[K,V]): PConcTable[K,V] = #proc keyEQ[K](key1: ptr K, key2: ptr K): bool {.inline.} = proc keyEQ[K](key1: int, key2: int): bool {.inline.} = result = false - when K is TRaw: + when K is Raw: if key1 == key2: result = true else: @@ -236,7 +237,7 @@ proc copySlot[K,V](idx: int, oldTbl: var PConcTable[K,V], newTbl: var PConcTable break #echo("oldVal was = ", oldVal, " set it to prime ", box) if isPrime(oldVal) and isTomb(oldVal): - #when not (K is TRaw): + #when not (K is Raw): # deallocShared(popPtr[K](oldKey)) return false if isTomb(oldVal): @@ -343,7 +344,7 @@ proc helpCopy[K,V](table: var PConcTable[K,V]): PConcTable[K,V] = proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int, expVal: int, match: bool): int = #echo("-try set- in table ", " key = ", (popPtr[K](key)[]), " val = ", val) - when K is TRaw: + when K is Raw: var idx = hashInt(key) else: var idx = popPtr[K](key)[].hash @@ -428,7 +429,7 @@ proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int, proc getVal[K,V](table: var PConcTable[K,V], key: int): int = #echo("-try get- key = " & $key) - when K is TRaw: + when K is Raw: var idx = hashInt(key) else: var idx = popPtr[K](key)[].hash @@ -468,37 +469,37 @@ proc getVal[K,V](table: var PConcTable[K,V], key: int): int = #------------------------------------------------------------------------------ -#proc set*(table: var PConcTable[TRaw,TRaw], key: TRaw, val: TRaw) = +#proc set*(table: var PConcTable[Raw,Raw], key: Raw, val: Raw) = # discard setVal(table, pack(key), pack(key), 0, false) -#proc set*[V](table: var PConcTable[TRaw,V], key: TRaw, val: ptr V) = +#proc set*[V](table: var PConcTable[Raw,V], key: Raw, val: ptr V) = # 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): + when not (K is Raw): var newKey = cast[int](copyShared(key)) else: var newKey = pack(key) - when not (V is TRaw): + when not (V is Raw): var newVal = cast[int](copyShared(val)) else: var newVal = pack(val) var oldPtr = pop(setVal(table, newKey, newVal, 0, false)) #echo("oldPtr = ", cast[int](oldPtr), " newPtr = ", cast[int](newPtr)) - when not (V is TRaw): + when not (V is Raw): if newVal != oldPtr and oldPtr != 0: deallocShared(cast[ptr V](oldPtr)) proc get*[K,V](table: var PConcTable[K,V], key: var K): V = - when not (V is TRaw): - when not (K is TRaw): + when not (V is Raw): + when not (K is Raw): return popPtr[V](getVal(table, cast[int](key.addr)))[] else: return popPtr[V](getVal(table, pack(key)))[] else: - when not (K is TRaw): + when not (K is Raw): return popRaw(getVal(table, cast[int](key.addr))) else: return popRaw(getVal(table, pack(key))) @@ -535,23 +536,24 @@ when not defined(testing) and isMainModule: type - TTestObj = tuple + TestObj = tuple thr: int f0: int f1: int - TData = tuple[k: string,v: TTestObj] - PDataArr = array[0..numTests-1, TData] - Dict = PConcTable[string,TTestObj] + Data = tuple[k: string,v: TestObj] + PDataArr = array[0..numTests-1, Data] + Dict = PConcTable[string,TestObj] + {.deprecated: [TTestObj: TestObj, TData: Data].} var - thr: array[0..numThreads-1, TThread[Dict]] + thr: array[0..numThreads-1, Thread[Dict]] - table = newLFTable[string,TTestObj](8) + table = newLFTable[string,TestObj](8) rand = newMersenneTwister(2525) proc createSampleData(len: int): PDataArr = - #result = cast[PDataArr](allocShared0(sizeof(TData)*numTests)) + #result = cast[PDataArr](allocShared0(sizeof(Data)*numTests)) for i in 0..len-1: result[i].k = "mark" & $(i+1) #echo("mark" & $(i+1), " ", hash("mark" & $(i+1))) diff --git a/lib/pure/collections/intsets.nim b/lib/pure/collections/intsets.nim index 25f6616a6..38bc9d462 100644 --- a/lib/pure/collections/intsets.nim +++ b/lib/pure/collections/intsets.nim @@ -30,25 +30,25 @@ const IntMask = 1 shl IntShift - 1 type - PTrunk = ref TTrunk - TTrunk {.final.} = object + PTrunk = ref Trunk + Trunk {.final.} = object next: PTrunk # all nodes are connected with this pointer key: int # start address at bit 0 bits: array[0..IntsPerTrunk - 1, BitScalar] # a bit vector - TTrunkSeq = seq[PTrunk] + TrunkSeq = seq[PTrunk] IntSet* = object ## an efficient set of 'int' implemented as a sparse bit set counter, max: int head: PTrunk - data: TTrunkSeq + data: TrunkSeq -{.deprecated: [TIntSet: IntSet].} +{.deprecated: [TIntSet: IntSet, TTrunk: Trunk, TTrunkSeq: TrunkSeq].} proc mustRehash(length, counter: int): bool {.inline.} = assert(length > counter) result = (length * 2 < counter * 3) or (length - counter < 4) -proc nextTry(h, maxHash: THash): THash {.inline.} = +proc nextTry(h, maxHash: Hash): Hash {.inline.} = result = ((5 * h) + 1) and maxHash proc intSetGet(t: IntSet, key: int): PTrunk = @@ -59,7 +59,7 @@ proc intSetGet(t: IntSet, key: int): PTrunk = h = nextTry(h, t.max) result = nil -proc intSetRawInsert(t: IntSet, data: var TTrunkSeq, desc: PTrunk) = +proc intSetRawInsert(t: IntSet, data: var TrunkSeq, desc: PTrunk) = var h = desc.key and t.max while data[h] != nil: assert(data[h] != desc) @@ -68,7 +68,7 @@ proc intSetRawInsert(t: IntSet, data: var TTrunkSeq, desc: PTrunk) = data[h] = desc proc intSetEnlarge(t: var IntSet) = - var n: TTrunkSeq + var n: TrunkSeq var oldMax = t.max t.max = ((t.max + 1) * 2) - 1 newSeq(n, t.max + 1) diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim index 280e0eeba..3d4de8fdc 100644 --- a/lib/pure/collections/sets.nim +++ b/lib/pure/collections/sets.nim @@ -29,7 +29,7 @@ when not defined(nimhygiene): # codes should never be needed, and this can pack more entries per cache-line. # Losing hcode entirely is also possible - if some element value is forbidden. type - KeyValuePair[A] = tuple[hcode: THash, key: A] + KeyValuePair[A] = tuple[hcode: Hash, key: A] KeyValuePairSeq[A] = seq[KeyValuePair[A]] HashSet* {.myShallow.}[A] = object ## \ ## A generic hash set. @@ -43,10 +43,10 @@ type # hcode for real keys cannot be zero. hcode==0 signifies an empty slot. These # two procs retain clarity of that encoding without the space cost of an enum. -proc isEmpty(hcode: THash): bool {.inline.} = +proc isEmpty(hcode: Hash): bool {.inline.} = result = hcode == 0 -proc isFilled(hcode: THash): bool {.inline.} = +proc isFilled(hcode: Hash): bool {.inline.} = result = hcode != 0 proc isValid*[A](s: HashSet[A]): bool = @@ -58,7 +58,7 @@ proc isValid*[A](s: HashSet[A]): bool = ## initialized. Example: ## ## .. code-block :: - ## proc savePreferences(options: TSet[string]) = + ## proc savePreferences(options: Set[string]) = ## assert options.isValid, "Pass an initialized set!" ## # Do stuff here, may crash in release builds! result = not s.data.isNil @@ -72,7 +72,7 @@ proc len*[A](s: HashSet[A]): int = ## ## .. code-block:: ## - ## var values: TSet[int] + ## var values: Set[int] ## assert(not values.isValid) ## assert values.len == 0 result = s.counter @@ -123,15 +123,15 @@ proc rightSize*(count: Natural): int {.inline.} = ## Internally, we want mustRehash(rightSize(x), x) == false. result = nextPowerOfTwo(count * 3 div 2 + 4) -proc nextTry(h, maxHash: THash): THash {.inline.} = +proc nextTry(h, maxHash: Hash): Hash {.inline.} = result = (h + 1) and maxHash template rawGetKnownHCImpl() {.dirty.} = - var h: THash = hc and high(s.data) # start with real hash value + var h: Hash = hc and high(s.data) # start with real hash value while isFilled(s.data[h].hcode): # Compare hc THEN key with boolean short circuit. This makes the common case # zero ==key's for missing (e.g.inserts) and exactly one ==key for present. - # It does slow down succeeding lookups by one extra THash cmp&and..usually + # It does slow down succeeding lookups by one extra Hash cmp&and..usually # just a few clock cycles, generally worth it for any non-integer-like A. if s.data[h].hcode == hc and s.data[h].key == key: # compare hc THEN key return h @@ -148,10 +148,10 @@ template rawInsertImpl() {.dirty.} = data[h].key = key data[h].hcode = hc -proc rawGetKnownHC[A](s: HashSet[A], key: A, hc: THash): int {.inline.} = +proc rawGetKnownHC[A](s: HashSet[A], key: A, hc: Hash): int {.inline.} = rawGetKnownHCImpl() -proc rawGet[A](s: HashSet[A], key: A, hc: var THash): int {.inline.} = +proc rawGet[A](s: HashSet[A], key: A, hc: var Hash): int {.inline.} = rawGetImpl() proc mget*[A](s: var HashSet[A], key: A): var A = @@ -160,7 +160,7 @@ proc mget*[A](s: var HashSet[A], key: A): var A = ## when one overloaded 'hash' and '==' but still needs reference semantics ## for sharing. assert s.isValid, "The set needs to be initialized." - var hc: THash + var hc: Hash var index = rawGet(s, key, hc) if index >= 0: result = s.data[index].key else: raise newException(KeyError, "key not found: " & $key) @@ -178,12 +178,12 @@ proc contains*[A](s: HashSet[A], key: A): bool = ## values.excl(2) ## assert(not values.contains(2)) assert s.isValid, "The set needs to be initialized." - var hc: THash + var hc: Hash var index = rawGet(s, key, hc) result = index >= 0 proc rawInsert[A](s: var HashSet[A], data: var KeyValuePairSeq[A], key: A, - hc: THash, h: THash) = + hc: Hash, h: Hash) = rawInsertImpl() proc enlarge[A](s: var HashSet[A]) = @@ -196,7 +196,7 @@ proc enlarge[A](s: var HashSet[A]) = rawInsert(s, s.data, n[i].key, n[i].hcode, j) template inclImpl() {.dirty.} = - var hc: THash + var hc: Hash var index = rawGet(s, key, hc) if index < 0: if mustRehash(len(s.data), s.counter): @@ -206,7 +206,7 @@ template inclImpl() {.dirty.} = inc(s.counter) template containsOrInclImpl() {.dirty.} = - var hc: THash + var hc: Hash var index = rawGet(s, key, hc) if index >= 0: result = true @@ -261,7 +261,7 @@ proc excl*[A](s: var HashSet[A], key: A) = ## s.excl(2) ## assert s.len == 3 assert s.isValid, "The set needs to be initialized." - var hc: THash + var hc: Hash var i = rawGet(s, key, hc) var msk = high(s.data) if i >= 0: @@ -323,7 +323,7 @@ proc init*[A](s: var HashSet[A], initialSize=64) = ## existing values and calling `excl() <#excl,TSet[A],A>`_ on them. Example: ## ## .. code-block :: - ## var a: TSet[int] + ## var a: Set[int] ## a.init(4) ## a.incl(2) ## a.init @@ -552,7 +552,7 @@ proc map*[A, B](data: HashSet[A], op: proc (x: A): B {.closure.}): HashSet[B] = type OrderedKeyValuePair[A] = tuple[ - hcode: THash, next: int, key: A] + hcode: Hash, next: int, key: A] OrderedKeyValuePairSeq[A] = seq[OrderedKeyValuePair[A]] OrderedSet* {.myShallow.}[A] = object ## \ ## A generic hash set that remembers insertion order. @@ -574,7 +574,7 @@ proc isValid*[A](s: OrderedSet[A]): bool = ## correctly initialized. Example: ## ## .. code-block:: - ## proc saveTarotCards(cards: TOrderedSet[int]) = + ## proc saveTarotCards(cards: OrderedSet[int]) = ## assert cards.isValid, "Pass an initialized set!" ## # Do stuff here, may crash in release builds! result = not s.data.isNil @@ -588,7 +588,7 @@ proc len*[A](s: OrderedSet[A]): int {.inline.} = ## ## .. code-block:: ## - ## var values: TOrderedSet[int] + ## var values: OrderedSet[int] ## assert(not values.isValid) ## assert values.len == 0 result = s.counter @@ -629,10 +629,10 @@ iterator items*[A](s: OrderedSet[A]): A = forAllOrderedPairs: yield s.data[h].key -proc rawGetKnownHC[A](s: OrderedSet[A], key: A, hc: THash): int {.inline.} = +proc rawGetKnownHC[A](s: OrderedSet[A], key: A, hc: Hash): int {.inline.} = rawGetKnownHCImpl() -proc rawGet[A](s: OrderedSet[A], key: A, hc: var THash): int {.inline.} = +proc rawGet[A](s: OrderedSet[A], key: A, hc: var Hash): int {.inline.} = rawGetImpl() proc contains*[A](s: OrderedSet[A], key: A): bool = @@ -646,12 +646,12 @@ proc contains*[A](s: OrderedSet[A], key: A): bool = ## values.incl(2) ## assert values.contains(2) assert s.isValid, "The set needs to be initialized." - var hc: THash + var hc: Hash var index = rawGet(s, key, hc) result = index >= 0 proc rawInsert[A](s: var OrderedSet[A], data: var OrderedKeyValuePairSeq[A], - key: A, hc: THash, h: THash) = + key: A, hc: Hash, h: Hash) = rawInsertImpl() data[h].next = -1 if s.first < 0: s.first = h @@ -729,7 +729,7 @@ proc init*[A](s: var OrderedSet[A], initialSize=64) = ## from an ordered hash set. Example: ## ## .. code-block :: - ## 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 9496fa2fe..c44adfc82 100644 --- a/lib/pure/collections/tables.nim +++ b/lib/pure/collections/tables.nim @@ -24,13 +24,13 @@ ## ## Error: type mismatch: got (Person) ## but expected one of: -## hashes.hash(x: openarray[A]): THash -## hashes.hash(x: int): THash -## hashes.hash(x: float): THash +## hashes.hash(x: openarray[A]): Hash +## hashes.hash(x: int): Hash +## hashes.hash(x: float): Hash ## … ## ## What is happening here is that the types used for table keys require to have -## a ``hash()`` proc which will convert them to a `THash <hashes.html#THash>`_ +## a ``hash()`` proc which will convert them to a `Hash <hashes.html#Hash>`_ ## value, and the compiler is listing all the hash functions it knows. ## Additionally there has to be a ``==`` operator that provides the same ## semantics as its corresponding ``hash`` proc. @@ -46,7 +46,7 @@ ## Person = object ## firstName, lastName: string ## -## proc hash(x: Person): THash = +## proc hash(x: Person): Hash = ## ## Piggyback on the already available string hash proc. ## ## ## ## Without this proc nothing works! @@ -71,7 +71,7 @@ import {.pragma: myShallow.} type - KeyValuePair[A, B] = tuple[hcode: THash, key: A, val: B] + KeyValuePair[A, B] = tuple[hcode: Hash, key: A, val: B] KeyValuePairSeq[A, B] = seq[KeyValuePair[A, B]] Table* {.myShallow.}[A, B] = object ## generic hash table data: KeyValuePairSeq[A, B] @@ -85,10 +85,10 @@ when not defined(nimhygiene): # hcode for real keys cannot be zero. hcode==0 signifies an empty slot. These # two procs retain clarity of that encoding without the space cost of an enum. -proc isEmpty(hcode: THash): bool {.inline.} = +proc isEmpty(hcode: Hash): bool {.inline.} = result = hcode == 0 -proc isFilled(hcode: THash): bool {.inline.} = +proc isFilled(hcode: Hash): bool {.inline.} = result = hcode != 0 proc len*[A, B](t: Table[A, B]): int = @@ -137,15 +137,15 @@ proc rightSize*(count: Natural): int {.inline.} = ## Internally, we want mustRehash(rightSize(x), x) == false. result = nextPowerOfTwo(count * 3 div 2 + 4) -proc nextTry(h, maxHash: THash): THash {.inline.} = +proc nextTry(h, maxHash: Hash): Hash {.inline.} = result = (h + 1) and maxHash template rawGetKnownHCImpl() {.dirty.} = - var h: THash = hc and high(t.data) # start with real hash value + var h: Hash = hc and high(t.data) # start with real hash value while isFilled(t.data[h].hcode): # Compare hc THEN key with boolean short circuit. This makes the common case # zero ==key's for missing (e.g.inserts) and exactly one ==key for present. - # It does slow down succeeding lookups by one extra THash cmp&and..usually + # It does slow down succeeding lookups by one extra Hash cmp&and..usually # just a few clock cycles, generally worth it for any non-integer-like A. if t.data[h].hcode == hc and t.data[h].key == key: return h @@ -162,7 +162,7 @@ template rawGetDeepImpl() {.dirty.} = # Search algo for unconditional add hc = hash(key) if hc == 0: hc = 314159265 - var h: THash = hc and high(t.data) + var h: Hash = hc and high(t.data) while isFilled(t.data[h].hcode): h = nextTry(h, high(t.data)) result = h @@ -172,13 +172,13 @@ template rawInsertImpl() {.dirty.} = data[h].val = val data[h].hcode = hc -proc rawGetKnownHC[A, B](t: Table[A, B], key: A, hc: THash): int {.inline.} = +proc rawGetKnownHC[A, B](t: Table[A, B], key: A, hc: Hash): int {.inline.} = rawGetKnownHCImpl() -proc rawGetDeep[A, B](t: Table[A, B], key: A, hc: var THash): int {.inline.} = +proc rawGetDeep[A, B](t: Table[A, B], key: A, hc: var Hash): int {.inline.} = rawGetDeepImpl() -proc rawGet[A, B](t: Table[A, B], key: A, hc: var THash): int {.inline.} = +proc rawGet[A, B](t: Table[A, B], key: A, hc: var Hash): int {.inline.} = rawGetImpl() proc `[]`*[A, B](t: Table[A, B], key: A): B = @@ -186,14 +186,14 @@ proc `[]`*[A, B](t: Table[A, B], key: A): B = ## default empty value for the type `B` is returned ## and no exception is raised. One can check with ``hasKey`` whether the key ## exists. - var hc: THash + var hc: Hash var index = rawGet(t, key, hc) if index >= 0: result = t.data[index].val proc mget*[A, B](t: var Table[A, B], key: A): var B = ## retrieves the value at ``t[key]``. The value can be modified. ## If `key` is not in `t`, the ``KeyError`` exception is raised. - var hc: THash + var hc: Hash var index = rawGet(t, key, hc) if index >= 0: result = t.data[index].val else: @@ -204,7 +204,7 @@ proc mget*[A, B](t: var Table[A, B], key: A): var B = iterator allValues*[A, B](t: Table[A, B]; key: A): B = ## iterates over any value in the table `t` that belongs to the given `key`. - var h: THash = hash(key) and high(t.data) + var h: Hash = hash(key) and high(t.data) while isFilled(t.data[h].hcode): if t.data[h].key == key: yield t.data[h].val @@ -212,7 +212,7 @@ iterator allValues*[A, B](t: Table[A, B]; key: A): B = proc hasKey*[A, B](t: Table[A, B], key: A): bool = ## returns true iff `key` is in the table `t`. - var hc: THash + var hc: Hash result = rawGet(t, key, hc) >= 0 proc contains*[A, B](t: Table[A, B], key: A): bool = @@ -220,7 +220,7 @@ proc contains*[A, B](t: Table[A, B], key: A): bool = return hasKey[A, B](t, key) proc rawInsert[A, B](t: var Table[A, B], data: var KeyValuePairSeq[A, B], - key: A, val: B, hc: THash, h: THash) = + key: A, val: B, hc: Hash, h: Hash) = rawInsertImpl() proc enlarge[A, B](t: var Table[A, B]) = @@ -234,7 +234,7 @@ proc enlarge[A, B](t: var Table[A, B]) = template addImpl() {.dirty.} = if mustRehash(len(t.data), t.counter): enlarge(t) - var hc: THash + var hc: Hash var j = rawGetDeep(t, key, hc) rawInsert(t, t.data, key, val, hc, j) inc(t.counter) @@ -248,19 +248,19 @@ template maybeRehashPutImpl() {.dirty.} = inc(t.counter) template putImpl() {.dirty.} = - var hc: THash + var hc: Hash var index = rawGet(t, key, hc) if index >= 0: t.data[index].val = val else: maybeRehashPutImpl() template mgetOrPutImpl() {.dirty.} = - var hc: THash + var hc: Hash var index = rawGet(t, key, hc) if index < 0: maybeRehashPutImpl() # not present: insert (flipping index) result = t.data[index].val # either way return modifiable val template hasKeyOrPutImpl() {.dirty.} = - var hc: THash + var hc: Hash var index = rawGet(t, key, hc) if index < 0: result = false @@ -291,7 +291,7 @@ template doWhile(a: expr, b: stmt): stmt = proc del*[A, B](t: var Table[A, B], key: A) = ## deletes `key` from hash table `t`. - var hc: THash + var hc: Hash var i = rawGet(t, key, hc) let msk = high(t.data) if i >= 0: @@ -460,7 +460,7 @@ proc newTableFrom*[A, B, C](collection: A, index: proc(x: B): C): TableRef[C, B] type OrderedKeyValuePair[A, B] = tuple[ - hcode: THash, next: int, key: A, val: B] + hcode: Hash, next: int, key: A, val: B] OrderedKeyValuePairSeq[A, B] = seq[OrderedKeyValuePair[A, B]] OrderedTable* {. myShallow.}[A, B] = object ## table that remembers insertion order @@ -509,13 +509,13 @@ iterator mvalues*[A, B](t: var OrderedTable[A, B]): var B = forAllOrderedPairs: yield t.data[h].val -proc rawGetKnownHC[A, B](t: OrderedTable[A, B], key: A, hc: THash): int = +proc rawGetKnownHC[A, B](t: OrderedTable[A, B], key: A, hc: Hash): int = rawGetKnownHCImpl() -proc rawGetDeep[A, B](t: OrderedTable[A, B], key: A, hc: var THash): int {.inline.} = +proc rawGetDeep[A, B](t: OrderedTable[A, B], key: A, hc: var Hash): int {.inline.} = rawGetDeepImpl() -proc rawGet[A, B](t: OrderedTable[A, B], key: A, hc: var THash): int = +proc rawGet[A, B](t: OrderedTable[A, B], key: A, hc: var Hash): int = rawGetImpl() proc `[]`*[A, B](t: OrderedTable[A, B], key: A): B = @@ -523,21 +523,21 @@ proc `[]`*[A, B](t: OrderedTable[A, B], key: A): B = ## default empty value for the type `B` is returned ## and no exception is raised. One can check with ``hasKey`` whether the key ## exists. - var hc: THash + var hc: Hash var index = rawGet(t, key, hc) if index >= 0: result = t.data[index].val proc mget*[A, B](t: var OrderedTable[A, B], key: A): var B = ## retrieves the value at ``t[key]``. The value can be modified. ## If `key` is not in `t`, the ``EInvalidKey`` exception is raised. - var hc: THash + var hc: Hash var index = rawGet(t, key, hc) if index >= 0: result = t.data[index].val else: raise newException(KeyError, "key not found: " & $key) proc hasKey*[A, B](t: OrderedTable[A, B], key: A): bool = ## returns true iff `key` is in the table `t`. - var hc: THash + var hc: Hash result = rawGet(t, key, hc) >= 0 proc contains*[A, B](t: OrderedTable[A, B], key: A): bool = @@ -546,7 +546,7 @@ proc contains*[A, B](t: OrderedTable[A, B], key: A): bool = proc rawInsert[A, B](t: var OrderedTable[A, B], data: var OrderedKeyValuePairSeq[A, B], - key: A, val: B, hc: THash, h: THash) = + key: A, val: B, hc: Hash, h: Hash) = rawInsertImpl() data[h].next = -1 if t.first < 0: t.first = h @@ -796,7 +796,7 @@ iterator mvalues*[A](t: CountTable[A]): var int = if t.data[h].val != 0: yield t.data[h].val proc rawGet[A](t: CountTable[A], key: A): int = - var h: THash = hash(key) and high(t.data) # start with real hash value + var h: Hash = hash(key) and high(t.data) # start with real hash value while t.data[h].val != 0: if t.data[h].key == key: return h h = nextTry(h, high(t.data)) @@ -826,7 +826,7 @@ proc contains*[A](t: CountTable[A], key: A): bool = proc rawInsert[A](t: CountTable[A], data: var seq[tuple[key: A, val: int]], key: A, val: int) = - var h: THash = hash(key) and high(data) + var h: Hash = hash(key) and high(data) while data[h].val != 0: h = nextTry(h, high(data)) data[h].key = key data[h].val = val @@ -1032,7 +1032,7 @@ when isMainModule: Person = object firstName, lastName: string - proc hash(x: Person): THash = + proc hash(x: Person): Hash = ## Piggyback on the already available string hash proc. ## ## Without this proc nothing works! diff --git a/lib/pure/concurrency/cpuload.nim b/lib/pure/concurrency/cpuload.nim index 7ce5e01b7..22598b5c9 100644 --- a/lib/pure/concurrency/cpuload.nim +++ b/lib/pure/concurrency/cpuload.nim @@ -13,7 +13,7 @@ when defined(windows): import winlean, os, strutils, math - proc `-`(a, b: TFILETIME): int64 = a.rdFileTime - b.rdFileTime + proc `-`(a, b: FILETIME): int64 = a.rdFileTime - b.rdFileTime elif defined(linux): from cpuinfo import countProcessors @@ -25,16 +25,16 @@ type ThreadPoolState* = object when defined(windows): - prevSysKernel, prevSysUser, prevProcKernel, prevProcUser: TFILETIME + prevSysKernel, prevSysUser, prevProcKernel, prevProcUser: FILETIME calls*: int proc advice*(s: var ThreadPoolState): ThreadPoolAdvice = when defined(windows): var sysIdle, sysKernel, sysUser, - procCreation, procExit, procKernel, procUser: TFILETIME + procCreation, procExit, procKernel, procUser: FILETIME if getSystemTimes(sysIdle, sysKernel, sysUser) == 0 or - getProcessTimes(THandle(-1), procCreation, procExit, + getProcessTimes(Handle(-1), procCreation, procExit, procKernel, procUser) == 0: return doNothing if s.calls > 0: @@ -57,7 +57,7 @@ proc advice*(s: var ThreadPoolState): ThreadPoolAdvice = s.prevProcKernel = procKernel s.prevProcUser = procUser elif defined(linux): - proc fscanf(c: File, frmt: cstring) {.varargs, importc, + proc fscanf(c: File, frmt: cstring) {.varargs, importc, header: "<stdio.h>".} var f = open("/proc/loadavg") diff --git a/lib/pure/concurrency/threadpool.nim b/lib/pure/concurrency/threadpool.nim index a431691ad..749a2fa2d 100644 --- a/lib/pure/concurrency/threadpool.nim +++ b/lib/pure/concurrency/threadpool.nim @@ -18,8 +18,8 @@ import cpuinfo, cpuload, locks type Semaphore = object - c: TCond - L: TLock + c: Cond + L: Lock counter: int proc createSemaphore(): Semaphore = @@ -113,7 +113,7 @@ type ToFreeQueue = object len: int - lock: TLock + lock: Lock empty: Semaphore data: array[128, pointer] @@ -221,11 +221,17 @@ proc awaitAndThen*[T](fv: FlowVar[T]; action: proc (x: T) {.closure.}) = action(fv.blob) finished(fv) -proc `^`*[T](fv: FlowVar[ref T]): foreign ptr T = +proc unsafeRead*[T](fv: FlowVar[ref T]): foreign ptr T = ## blocks until the value is available and then returns this value. await(fv) result = cast[foreign ptr T](fv.data) +proc `^`*[T](fv: FlowVar[ref T]): ref T = + ## blocks until the value is available and then returns this value. + await(fv) + let src = cast[ref T](fv.data) + deepCopy result, src + proc `^`*[T](fv: FlowVar[T]): T = ## blocks until the value is available and then returns this value. await(fv) @@ -349,7 +355,7 @@ proc parallel*(body: stmt) {.magic: "Parallel".} var state: ThreadPoolState - stateLock: TLock + stateLock: Lock initLock stateLock diff --git a/lib/pure/encodings.nim b/lib/pure/encodings.nim index 78baec3de..e427b585d 100644 --- a/lib/pure/encodings.nim +++ b/lib/pure/encodings.nim @@ -211,12 +211,13 @@ when defined(windows): when false: # not needed yet: type - TCpInfo = object + CpInfo = object maxCharSize: int32 defaultChar: array[0..1, char] leadByte: array[0..12-1, char] + {.deprecated: [TCpInfo: CpInfo].} - proc getCPInfo(codePage: CodePage, lpCPInfo: var TCpInfo): int32 {. + proc getCPInfo(codePage: CodePage, lpCPInfo: var CpInfo): int32 {. stdcall, importc: "GetCPInfo", dynlib: "kernel32".} proc nameToCodePage(name: string): CodePage = diff --git a/lib/pure/etcpriv.nim b/lib/pure/etcpriv.nim new file mode 100644 index 000000000..e7a525e4d --- /dev/null +++ b/lib/pure/etcpriv.nim @@ -0,0 +1,23 @@ +# +# +# Nim's Runtime Library +# (c) Copyright 2015 Nim Authors +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## This module contains utils that are less then easy to categorize and +## don't really warrant a specific module. They are private to compiler +## and stdlib usage, and should not be used outside of that - they may +## change or disappear at any time. + + +# Used by pure/hashes.nim, and the compiler parsing +const magicIdentSeparatorRuneByteWidth* = 3 + +# Used by pure/hashes.nim, and the compiler parsing +proc isMagicIdentSeparatorRune*(cs: cstring, i: int): bool {. inline } = + result = cs[i] == '\226' and + cs[i + 1] == '\128' and + cs[i + 2] == '\147' # en-dash # 145 = nb-hyphen diff --git a/lib/pure/fsmonitor.nim b/lib/pure/fsmonitor.nim index 83779eb9c..229df80b5 100644 --- a/lib/pure/fsmonitor.nim +++ b/lib/pure/fsmonitor.nim @@ -108,7 +108,7 @@ proc del*(monitor: FSMonitor, wd: cint) = proc getEvent(m: FSMonitor, fd: cint): seq[MonitorEvent] = result = @[] - let size = (sizeof(TINotifyEvent)+2000)*MaxEvents + let size = (sizeof(INotifyEvent)+2000)*MaxEvents var buffer = newString(size) let le = read(fd, addr(buffer[0]), size) @@ -117,7 +117,7 @@ proc getEvent(m: FSMonitor, fd: cint): seq[MonitorEvent] = var i = 0 while i < le: - var event = cast[ptr TINotifyEvent](addr(buffer[i])) + var event = cast[ptr INotifyEvent](addr(buffer[i])) var mev: MonitorEvent mev.wd = event.wd if event.len.int != 0: @@ -129,7 +129,7 @@ proc getEvent(m: FSMonitor, fd: cint): seq[MonitorEvent] = if (event.mask.int and IN_MOVED_FROM) != 0: # Moved from event, add to m's collection movedFrom.add(event.cookie.cint, (mev.wd, mev.name)) - inc(i, sizeof(TINotifyEvent) + event.len.int) + inc(i, sizeof(INotifyEvent) + event.len.int) continue elif (event.mask.int and IN_MOVED_TO) != 0: mev.kind = MonitorMoved @@ -159,7 +159,7 @@ proc getEvent(m: FSMonitor, fd: cint): seq[MonitorEvent] = mev.fullname = "" result.add(mev) - inc(i, sizeof(TINotifyEvent) + event.len.int) + inc(i, sizeof(INotifyEvent) + event.len.int) # If movedFrom events have not been matched with a moveTo. File has # been moved to an unwatched location, emit a MonitorDelete. diff --git a/lib/pure/gentabs.nim b/lib/pure/gentabs.nim index 84d0a44de..e6a05ec63 100644 --- a/lib/pure/gentabs.nim +++ b/lib/pure/gentabs.nim @@ -18,20 +18,22 @@ import os, hashes, strutils type - TGenTableMode* = enum ## describes the table's key matching mode + GenTableMode* = enum ## describes the table's key matching mode modeCaseSensitive, ## case sensitive matching of keys modeCaseInsensitive, ## case insensitive matching of keys modeStyleInsensitive ## style sensitive matching of keys - TGenKeyValuePair[T] = tuple[key: string, val: T] - TGenKeyValuePairSeq[T] = seq[TGenKeyValuePair[T]] - TGenTable*[T] = object of RootObj + GenKeyValuePair[T] = tuple[key: string, val: T] + GenKeyValuePairSeq[T] = seq[GenKeyValuePair[T]] + GenTable*[T] = object of RootObj counter: int - data: TGenKeyValuePairSeq[T] - mode: TGenTableMode + data: GenKeyValuePairSeq[T] + mode: GenTableMode - PGenTable*[T] = ref TGenTable[T] ## use this type to declare hash tables + PGenTable*[T] = ref GenTable[T] ## use this type to declare hash tables +{.deprecated: [TGenTableMode: GenTableMode, TGenKeyValuePair: GenKeyValuePair, + TGenKeyValuePairSeq: GenKeyValuePairSeq, TGenTable: GenTable].} const growthFactor = 2 @@ -48,7 +50,7 @@ iterator pairs*[T](tbl: PGenTable[T]): tuple[key: string, value: T] = if not isNil(tbl.data[h].key): yield (tbl.data[h].key, tbl.data[h].val) -proc myhash[T](tbl: PGenTable[T], key: string): THash = +proc myhash[T](tbl: PGenTable[T], key: string): Hash = case tbl.mode of modeCaseSensitive: result = hashes.hash(key) of modeCaseInsensitive: result = hashes.hashIgnoreCase(key) @@ -64,18 +66,18 @@ proc mustRehash(length, counter: int): bool = assert(length > counter) result = (length * 2 < counter * 3) or (length - counter < 4) -proc newGenTable*[T](mode: TGenTableMode): PGenTable[T] = +proc newGenTable*[T](mode: GenTableMode): PGenTable[T] = ## creates a new generic hash table that is empty. new(result) result.mode = mode result.counter = 0 newSeq(result.data, startSize) -proc nextTry(h, maxHash: THash): THash {.inline.} = +proc nextTry(h, maxHash: Hash): Hash {.inline.} = result = ((5 * h) + 1) and maxHash proc rawGet[T](tbl: PGenTable[T], key: string): int = - var h: THash + var h: Hash h = myhash(tbl, key) and high(tbl.data) # start with real hash value while not isNil(tbl.data[h].key): if myCmp(tbl, tbl.data[h].key, key): @@ -83,9 +85,9 @@ proc rawGet[T](tbl: PGenTable[T], key: string): int = h = nextTry(h, high(tbl.data)) result = - 1 -proc rawInsert[T](tbl: PGenTable[T], data: var TGenKeyValuePairSeq[T], +proc rawInsert[T](tbl: PGenTable[T], data: var GenKeyValuePairSeq[T], key: string, val: T) = - var h: THash + var h: Hash h = myhash(tbl, key) and high(data) while not isNil(data[h].key): h = nextTry(h, high(data)) @@ -93,7 +95,7 @@ proc rawInsert[T](tbl: PGenTable[T], data: var TGenKeyValuePairSeq[T], data[h].val = val proc enlarge[T](tbl: PGenTable[T]) = - var n: TGenKeyValuePairSeq[T] + var n: GenKeyValuePairSeq[T] newSeq(n, len(tbl.data) * growthFactor) for i in countup(0, high(tbl.data)): if not isNil(tbl.data[i].key): @@ -146,19 +148,20 @@ when isMainModule: # Verify a table of user-defined types # type - TMyType = tuple[first, second: string] # a pair of strings + MyType = tuple[first, second: string] # a pair of strings + {.deprecated: [TMyType: MyType].} - var y = newGenTable[TMyType](modeCaseInsensitive) # hash table where each - # value is TMyType tuple + var y = newGenTable[MyType](modeCaseInsensitive) # hash table where each + # value is MyType tuple - #var junk: TMyType = ("OK", "Here") + #var junk: MyType = ("OK", "Here") #echo junk.first, " ", junk.second y["Hello"] = ("Hello", "World") y["Goodbye"] = ("Goodbye", "Everyone") - #y["Hello"] = TMyType( ("Hello", "World") ) - #y["Goodbye"] = TMyType( ("Goodbye", "Everyone") ) + #y["Hello"] = MyType( ("Hello", "World") ) + #y["Goodbye"] = MyType( ("Goodbye", "Everyone") ) assert( not isNil(y["Hello"].first) ) assert( y["Hello"].first == "Hello" ) diff --git a/lib/pure/hashes.nim b/lib/pure/hashes.nim index 2ce8ac796..c303c7b4b 100644 --- a/lib/pure/hashes.nim +++ b/lib/pure/hashes.nim @@ -15,9 +15,9 @@ ## code: ## ## .. code-block:: Nim -## proc hash(x: Something): THash = -## ## Computes a THash from `x`. -## var h: THash = 0 +## proc hash(x: Something): Hash = +## ## Computes a Hash from `x`. +## var h: Hash = 0 ## # Iterate over parts of `x`. ## for xAtom in x: ## # Mix the atom with the partial hash. @@ -30,38 +30,39 @@ ## together the hash value of the individual fields: ## ## .. code-block:: Nim -## proc hash(x: Something): THash = -## ## Computes a THash from `x`. -## var h: THash = 0 +## proc hash(x: Something): Hash = +## ## Computes a Hash from `x`. +## var h: Hash = 0 ## h = h !& hash(x.foo) ## h = h !& hash(x.bar) ## result = !$h import - strutils + strutils, etcpriv type - THash* = int ## a hash value; hash tables using these values should + Hash* = int ## a hash value; hash tables using these values should ## always have a size of a power of two and can use the ``and`` ## operator instead of ``mod`` for truncation of the hash value. +{.deprecated: [THash: Hash].} -proc `!&`*(h: THash, val: int): THash {.inline.} = +proc `!&`*(h: Hash, val: int): Hash {.inline.} = ## mixes a hash value `h` with `val` to produce a new hash value. This is ## only needed if you need to implement a hash proc for a new datatype. result = h +% val result = result +% result shl 10 result = result xor (result shr 6) -proc `!$`*(h: THash): THash {.inline.} = +proc `!$`*(h: Hash): Hash {.inline.} = ## finishes the computation of the hash value. This is ## only needed if you need to implement a hash proc for a new datatype. result = h +% h shl 3 result = result xor (result shr 11) result = result +% result shl 15 -proc hashData*(data: pointer, size: int): THash = +proc hashData*(data: pointer, size: int): Hash = ## hashes an array of bytes of size `size` - var h: THash = 0 + var h: Hash = 0 when defined(js): var p: cstring asm """`p` = `Data`;""" @@ -78,7 +79,7 @@ proc hashData*(data: pointer, size: int): THash = when defined(js): var objectID = 0 -proc hash*(x: pointer): THash {.inline.} = +proc hash*(x: pointer): Hash {.inline.} = ## efficient hashing of pointers when defined(js): asm """ @@ -92,50 +93,57 @@ proc hash*(x: pointer): THash {.inline.} = } """ else: - result = (cast[THash](x)) shr 3 # skip the alignment + result = (cast[Hash](x)) shr 3 # skip the alignment when not defined(booting): - proc hash*[T: proc](x: T): THash {.inline.} = + proc hash*[T: proc](x: T): Hash {.inline.} = ## efficient hashing of proc vars; closures are supported too. when T is "closure": result = hash(rawProc(x)) !& hash(rawEnv(x)) else: result = hash(pointer(x)) -proc hash*(x: int): THash {.inline.} = +proc hash*(x: int): Hash {.inline.} = ## efficient hashing of integers result = x -proc hash*(x: int64): THash {.inline.} = +proc hash*(x: int64): Hash {.inline.} = ## efficient hashing of integers result = toU32(x) -proc hash*(x: char): THash {.inline.} = +proc hash*(x: char): Hash {.inline.} = ## efficient hashing of characters result = ord(x) -proc hash*(x: string): THash = +proc hash*(x: string): Hash = ## efficient hashing of strings - var h: THash = 0 + var h: Hash = 0 for i in 0..x.len-1: h = h !& ord(x[i]) result = !$h -proc hashIgnoreStyle*(x: string): THash = +proc hashIgnoreStyle*(x: string): Hash = ## efficient hashing of strings; style is ignored - var h: THash = 0 - for i in 0..x.len-1: + var h: Hash = 0 + var i = 0 + let xLen = x.len + while i < xLen: var c = x[i] if c == '_': - continue # skip _ - if c in {'A'..'Z'}: - c = chr(ord(c) + (ord('a') - ord('A'))) # toLower() - h = h !& ord(c) + inc(i) + elif isMagicIdentSeparatorRune(cstring(x), i): + inc(i, magicIdentSeparatorRuneByteWidth) + else: + if c in {'A'..'Z'}: + c = chr(ord(c) + (ord('a') - ord('A'))) # toLower() + h = h !& ord(c) + inc(i) + result = !$h -proc hashIgnoreCase*(x: string): THash = +proc hashIgnoreCase*(x: string): Hash = ## efficient hashing of strings; case is ignored - var h: THash = 0 + var h: Hash = 0 for i in 0..x.len-1: var c = x[i] if c in {'A'..'Z'}: @@ -143,28 +151,28 @@ proc hashIgnoreCase*(x: string): THash = h = h !& ord(c) result = !$h -proc hash*(x: float): THash {.inline.} = +proc hash*(x: float): Hash {.inline.} = var y = x + 1.0 - result = cast[ptr THash](addr(y))[] + result = cast[ptr Hash](addr(y))[] # Forward declarations before methods that hash containers. This allows # containers to contain other containers -proc hash*[A](x: openArray[A]): THash -proc hash*[A](x: set[A]): THash +proc hash*[A](x: openArray[A]): Hash +proc hash*[A](x: set[A]): Hash -proc hash*[T: tuple](x: T): THash = +proc hash*[T: tuple](x: T): Hash = ## efficient hashing of tuples. for f in fields(x): result = result !& hash(f) result = !$result -proc hash*[A](x: openArray[A]): THash = +proc hash*[A](x: openArray[A]): Hash = for it in items(x): result = result !& hash(it) result = !$result -proc hash*[A](x: set[A]): THash = +proc hash*[A](x: set[A]): Hash = for it in items(x): result = result !& hash(it) result = !$result diff --git a/lib/pure/htmlparser.nim b/lib/pure/htmlparser.nim index 9719181b8..a0e2ecd9b 100644 --- a/lib/pure/htmlparser.nim +++ b/lib/pure/htmlparser.nim @@ -52,7 +52,7 @@ import strutils, streams, parsexml, xmltree, unicode, strtabs type - THtmlTag* = enum ## list of all supported HTML tags; order will always be + HtmlTag* = enum ## list of all supported HTML tags; order will always be ## alphabetically tagUnknown, ## unknown HTML element tagA, ## the HTML ``a`` element @@ -178,6 +178,7 @@ type tagVar, ## the HTML ``var`` element tagVideo, ## the HTML ``video`` element tagWbr ## the HTML ``wbr`` element +{.deprecated: [THtmlTag: HtmlTag].} const tagToStr* = [ @@ -295,7 +296,7 @@ proc allLower(s: string): bool = if c < 'a' or c > 'z': return false return true -proc toHtmlTag(s: string): THtmlTag = +proc toHtmlTag(s: string): HtmlTag = case s of "a": tagA of "abbr": tagAbbr @@ -422,14 +423,14 @@ proc toHtmlTag(s: string): THtmlTag = of "wbr": tagWbr else: tagUnknown -proc htmlTag*(n: XmlNode): THtmlTag = - ## gets `n`'s tag as a ``THtmlTag``. +proc htmlTag*(n: XmlNode): HtmlTag = + ## gets `n`'s tag as a ``HtmlTag``. if n.clientData == 0: n.clientData = toHtmlTag(n.tag).ord - result = THtmlTag(n.clientData) + result = HtmlTag(n.clientData) -proc htmlTag*(s: string): THtmlTag = - ## converts `s` to a ``THtmlTag``. If `s` is no HTML tag, ``tagUnknown`` is +proc htmlTag*(s: string): HtmlTag = + ## converts `s` to a ``HtmlTag``. If `s` is no HTML tag, ``tagUnknown`` is ## returned. let s = if allLower(s): s else: s.toLower result = toHtmlTag(s) diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim index e083d44ea..6a2913713 100644 --- a/lib/pure/httpclient.nim +++ b/lib/pure/httpclient.nim @@ -569,7 +569,7 @@ proc downloadFile*(url: string, outputFilename: string, fileError("Unable to open file") proc generateHeaders(r: Uri, httpMethod: string, - headers: StringTableRef): string = + headers: StringTableRef, body: string): string = # TODO: Use this in the blocking HttpClient once it supports proxies. result = substr(httpMethod, len("http")) # TODO: Proxies @@ -582,6 +582,8 @@ proc generateHeaders(r: Uri, httpMethod: string, add(result, "Host: " & r.hostname & "\c\L") add(result, "Connection: Keep-Alive\c\L") + if body.len > 0 and not headers.hasKey("Content-Length"): + add(result, "Content-Length: " & $body.len & "\c\L") for key, val in headers: add(result, key & ": " & val & "\c\L") @@ -786,7 +788,7 @@ proc request*(client: AsyncHttpClient, url: string, httpMethod: string, if not client.headers.hasKey("user-agent") and client.userAgent != "": client.headers["User-Agent"] = client.userAgent - var headers = generateHeaders(r, $httpMethod, client.headers) + var headers = generateHeaders(r, $httpMethod, client.headers, body) await client.socket.send(headers) if body != "": diff --git a/lib/pure/httpserver.nim b/lib/pure/httpserver.nim index dc76c9228..981891227 100644 --- a/lib/pure/httpserver.nim +++ b/lib/pure/httpserver.nim @@ -106,9 +106,10 @@ proc serveFile*(client: Socket, filename: string) = when false: # TODO: Fix this, or get rid of it. type - TRequestMethod = enum reqGet, reqPost + RequestMethod = enum reqGet, reqPost + {.deprecated: [TRequestMethod: RequestMethod].} - proc executeCgi(client: Socket, path, query: string, meth: TRequestMethod) = + proc executeCgi(client: Socket, path, query: string, meth: RequestMethod) = var env = newStringTable(modeCaseInsensitive) var contentLength = -1 case meth @@ -208,7 +209,7 @@ when false: executeCgi(client, path, query, meth) type - TServer* = object of RootObj ## contains the current server state + Server* = object of RootObj ## contains the current server state socket: Socket port: Port client*: Socket ## the socket to write the file data to @@ -218,11 +219,12 @@ type body*: string ## only set with POST requests ip*: string ## ip address of the requesting client - PAsyncHTTPServer* = ref TAsyncHTTPServer - TAsyncHTTPServer = object of TServer + PAsyncHTTPServer* = ref AsyncHTTPServer + AsyncHTTPServer = object of Server asyncSocket: AsyncSocket +{.deprecated: [TAsyncHTTPServer: AsyncHTTPServer, TServer: Server].} -proc open*(s: var TServer, port = Port(80), reuseAddr = false) = +proc open*(s: var Server, port = Port(80), reuseAddr = false) = ## creates a new server at port `port`. If ``port == 0`` a free port is ## acquired that can be accessed later by the ``port`` proc. s.socket = socket(AF_INET) @@ -243,11 +245,11 @@ proc open*(s: var TServer, port = Port(80), reuseAddr = false) = s.query = "" s.headers = {:}.newStringTable() -proc port*(s: var TServer): Port = +proc port*(s: var Server): Port = ## get the port number the server has acquired. result = s.port -proc next*(s: var TServer) = +proc next*(s: var Server) = ## proceed to the first/next request. var client: Socket new(client) @@ -354,7 +356,7 @@ proc next*(s: var TServer) = s.query = "" s.path = data.substr(i, last-1) -proc close*(s: TServer) = +proc close*(s: Server) = ## closes the server (and the socket the server uses). close(s.socket) @@ -362,7 +364,7 @@ proc run*(handleRequest: proc (client: Socket, path, query: string): bool {.closure.}, port = Port(80)) = ## encapsulates the server object and main loop - var s: TServer + var s: Server open(s, port, reuseAddr = true) #echo("httpserver running on port ", s.port) while true: @@ -517,7 +519,7 @@ proc close*(h: PAsyncHTTPServer) = when not defined(testing) and isMainModule: var counter = 0 - var s: TServer + var s: Server open(s, Port(0)) echo("httpserver running on port ", s.port) while true: diff --git a/lib/pure/json.nim b/lib/pure/json.nim index 0959bb221..49915b7e9 100644 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -68,7 +68,7 @@ type jsonArrayStart, ## start of an array: the ``[`` token jsonArrayEnd ## start of an array: the ``]`` token - TTokKind = enum # must be synchronized with TJsonEventKind! + TokKind = enum # must be synchronized with TJsonEventKind! tkError, tkEof, tkString, @@ -103,14 +103,14 @@ type JsonParser* = object of BaseLexer ## the parser object. a: string - tok: TTokKind + tok: TokKind kind: JsonEventKind err: JsonError state: seq[ParserState] filename: string {.deprecated: [TJsonEventKind: JsonEventKind, TJsonError: JsonError, - TJsonParser: JsonParser].} + TJsonParser: JsonParser, TTokKind: TokKind].} const errorMessages: array [JsonError, string] = [ @@ -126,7 +126,7 @@ const "EOF expected", "expression expected" ] - tokToStr: array [TTokKind, string] = [ + tokToStr: array [TokKind, string] = [ "invalid token", "EOF", "string literal", @@ -203,7 +203,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 JsonParser): TTokKind = +proc parseString(my: var JsonParser): TokKind = result = tkString var pos = my.bufpos + 1 var buf = my.buf @@ -359,7 +359,7 @@ proc parseName(my: var JsonParser) = inc(pos) my.bufpos = pos -proc getTok(my: var JsonParser): TTokKind = +proc getTok(my: var JsonParser): TokKind = setLen(my.a, 0) skip(my) # skip whitespace, comments case my.buf[my.bufpos] @@ -734,7 +734,7 @@ proc `==`* (a,b: JsonNode): bool = of JObject: a.fields == b.fields -proc hash* (n:JsonNode): THash = +proc hash* (n:JsonNode): Hash = ## Compute the hash for a JSON node case n.kind of JArray: @@ -1016,7 +1016,7 @@ iterator mpairs*(node: var JsonNode): var tuple[key: string, val: JsonNode] = for keyVal in mitems(node.fields): yield keyVal -proc eat(p: var JsonParser, tok: TTokKind) = +proc eat(p: var JsonParser, tok: TokKind) = if p.tok == tok: discard getTok(p) else: raiseParseErr(p, tokToStr[tok]) @@ -1091,8 +1091,10 @@ when not defined(js): else: from math import `mod` type - TJSObject = object - proc parseNativeJson(x: cstring): TJSObject {.importc: "JSON.parse".} + JSObject = object + {.deprecated: [TJSObject: JSObject].} + + proc parseNativeJson(x: cstring): JSObject {.importc: "JSON.parse".} proc getVarType(x): JsonNodeKind = result = JNull @@ -1111,25 +1113,25 @@ else: of "[object String]": return JString else: assert false - proc len(x: TJSObject): int = + proc len(x: JSObject): int = assert x.getVarType == JArray asm """ return `x`.length; """ - proc `[]`(x: TJSObject, y: string): TJSObject = + proc `[]`(x: JSObject, y: string): JSObject = assert x.getVarType == JObject asm """ return `x`[`y`]; """ - proc `[]`(x: TJSObject, y: int): TJSObject = + proc `[]`(x: JSObject, y: int): JSObject = assert x.getVarType == JArray asm """ return `x`[`y`]; """ - proc convertObject(x: TJSObject): JsonNode = + proc convertObject(x: JSObject): JsonNode = case getVarType(x) of JArray: result = newJArray() @@ -1141,7 +1143,7 @@ else: if (`x`.hasOwnProperty(property)) { """ var nimProperty: cstring - var nimValue: TJSObject + var nimValue: JSObject asm "`nimProperty` = property; `nimValue` = `x`[property];" result[$nimProperty] = nimValue.convertObject() asm "}}" diff --git a/lib/pure/lexbase.nim b/lib/pure/lexbase.nim index 23a87d9f8..585ba87f5 100644 --- a/lib/pure/lexbase.nim +++ b/lib/pure/lexbase.nim @@ -39,7 +39,7 @@ type {.deprecated: [TBaseLexer: BaseLexer].} proc open*(L: var BaseLexer, input: Stream, bufLen: int = 8192) - ## inits the TBaseLexer with a stream to read from + ## inits the BaseLexer with a stream to read from proc close*(L: var BaseLexer) ## closes the base lexer. This closes `L`'s associated stream too. diff --git a/lib/pure/logging.nim b/lib/pure/logging.nim index cc5340211..379c18e9d 100644 --- a/lib/pure/logging.nim +++ b/lib/pure/logging.nim @@ -82,6 +82,7 @@ type baseName: string # initial filename baseMode: FileMode # initial file mode logFiles: int # how many log files already created, e.g. basename.1, basename.2... + bufSize: int # size of output buffer (-1: use system defaults, 0: unbuffered, >0: fixed buffer size) {.deprecated: [TLevel: Level, PLogger: Logger, PConsoleLogger: ConsoleLogger, PFileLogger: FileLogger, PRollingFileLogger: RollingFileLogger].} @@ -112,27 +113,22 @@ proc substituteLog(frmt: string): string = of "appname": result.add(app.splitFile.name) else: discard -method log*(logger: Logger, level: Level, - frmt: string, args: varargs[string, `$`]) {. +method log*(logger: Logger, level: Level, args: varargs[string, `$`]) {. raises: [Exception], tags: [TimeEffect, WriteIOEffect, ReadIOEffect].} = ## Override this method in custom loggers. Default implementation does ## nothing. discard -method log*(logger: ConsoleLogger, level: Level, - frmt: string, args: varargs[string, `$`]) = +method log*(logger: ConsoleLogger, level: Level, args: varargs[string, `$`]) = ## Logs to the console using ``logger`` only. if level >= logger.levelThreshold: - writeln(stdout, LevelNames[level], " ", substituteLog(logger.fmtStr), - frmt % args) + writeln(stdout, LevelNames[level], " ", substituteLog(logger.fmtStr), args) -method log*(logger: FileLogger, level: Level, - frmt: string, args: varargs[string, `$`]) = +method log*(logger: FileLogger, level: Level, args: varargs[string, `$`]) = ## Logs to a file using ``logger`` only. if level >= logger.levelThreshold: - writeln(logger.f, LevelNames[level], " ", - substituteLog(logger.fmtStr), frmt % args) + writeln(logger.f, LevelNames[level], " ", substituteLog(logger.fmtStr), args) proc defaultFilename*(): string = ## Returns the default filename for a logger. @@ -148,11 +144,14 @@ proc newConsoleLogger*(levelThreshold = lvlAll, fmtStr = defaultFmtStr): Console proc newFileLogger*(filename = defaultFilename(), mode: FileMode = fmAppend, levelThreshold = lvlAll, - fmtStr = defaultFmtStr): FileLogger = + fmtStr = defaultFmtStr, + bufSize: int = -1): FileLogger = ## Creates a new file logger. This logger logs to a file. + ## Use ``bufSize`` as size of the output buffer when writing the file + ## (-1: use system defaults, 0: unbuffered, >0: fixed buffer size). new(result) result.levelThreshold = levelThreshold - result.f = open(filename, mode) + result.f = open(filename, mode, bufSize = bufSize) result.fmtStr = fmtStr # ------ @@ -181,14 +180,18 @@ proc newRollingFileLogger*(filename = defaultFilename(), mode: FileMode = fmReadWrite, levelThreshold = lvlAll, fmtStr = defaultFmtStr, - maxLines = 1000): RollingFileLogger = + maxLines = 1000, + bufSize: int = -1): RollingFileLogger = ## Creates a new rolling file logger. Once a file reaches ``maxLines`` lines ## a new log file will be started and the old will be renamed. + ## Use ``bufSize`` as size of the output buffer when writing the file + ## (-1: use system defaults, 0: unbuffered, >0: fixed buffer size). new(result) result.levelThreshold = levelThreshold result.fmtStr = fmtStr result.maxLines = maxLines - result.f = open(filename, mode) + result.bufSize = bufSize + result.f = open(filename, mode, bufSize=result.bufSize) result.curLine = 0 result.baseName = filename result.baseMode = mode @@ -206,8 +209,7 @@ proc rotate(logger: RollingFileLogger) = moveFile(dir / (name & ext & srcSuff), dir / (name & ext & ExtSep & $(i+1))) -method log*(logger: RollingFileLogger, level: Level, - frmt: string, args: varargs[string, `$`]) = +method log*(logger: RollingFileLogger, level: Level, args: varargs[string, `$`]) = ## Logs to a file using rolling ``logger`` only. if level >= logger.levelThreshold: if logger.curLine >= logger.maxLines: @@ -215,9 +217,9 @@ method log*(logger: RollingFileLogger, level: Level, rotate(logger) logger.logFiles.inc logger.curLine = 0 - logger.f = open(logger.baseName, logger.baseMode) + logger.f = open(logger.baseName, logger.baseMode, bufSize = logger.bufSize) - writeln(logger.f, LevelNames[level], " ",substituteLog(logger.fmtStr), frmt % args) + writeln(logger.f, LevelNames[level], " ", substituteLog(logger.fmtStr), args) logger.curLine.inc # -------- @@ -225,39 +227,39 @@ method log*(logger: RollingFileLogger, level: Level, var level {.threadvar.}: Level ## global log filter var handlers {.threadvar.}: seq[Logger] ## handlers with their own log levels -proc logLoop(level: Level, frmt: string, args: varargs[string, `$`]) = +proc logLoop(level: Level, args: varargs[string, `$`]) = for logger in items(handlers): if level >= logger.levelThreshold: - log(logger, level, frmt, args) + log(logger, level, args) -template log*(level: Level, frmt: string, args: varargs[string, `$`]) = +template log*(level: Level, args: varargs[string, `$`]) = ## Logs a message to all registered handlers at the given level. bind logLoop bind `%` bind logging.level if level >= logging.level: - logLoop(level, frmt, args) + logLoop(level, args) -template debug*(frmt: string, args: varargs[string, `$`]) = +template debug*(args: varargs[string, `$`]) = ## Logs a debug message to all registered handlers. - log(lvlDebug, frmt, args) + log(lvlDebug, args) -template info*(frmt: string, args: varargs[string, `$`]) = +template info*(args: varargs[string, `$`]) = ## Logs an info message to all registered handlers. - log(lvlInfo, frmt, args) + log(lvlInfo, args) -template warn*(frmt: string, args: varargs[string, `$`]) = +template warn*(args: varargs[string, `$`]) = ## Logs a warning message to all registered handlers. - log(lvlWarn, frmt, args) + log(lvlWarn, args) -template error*(frmt: string, args: varargs[string, `$`]) = +template error*(args: varargs[string, `$`]) = ## Logs an error message to all registered handlers. - log(lvlError, frmt, args) + log(lvlError, args) -template fatal*(frmt: string, args: varargs[string, `$`]) = +template fatal*(args: varargs[string, `$`]) = ## Logs a fatal error message to all registered handlers. - log(lvlFatal, frmt, args) + log(lvlFatal, args) proc addHandler*(handler: Logger) = ## Adds ``handler`` to the list of handlers. @@ -286,6 +288,4 @@ when not defined(testing) and isMainModule: addHandler(fL) addHandler(rL) for i in 0 .. 25: - info("hello" & $i, []) - - + info("hello", i) diff --git a/lib/pure/marshal.nim b/lib/pure/marshal.nim index e0092f314..49f049e46 100644 --- a/lib/pure/marshal.nim +++ b/lib/pure/marshal.nim @@ -17,13 +17,13 @@ ## .. code-block:: nim ## ## type -## TA = object -## TB = object of TA +## A = object +## B = object of A ## f: int ## ## var -## a: ref TA -## b: ref TB +## a: ref A +## b: ref B ## ## new(b) ## a = b @@ -36,7 +36,7 @@ import streams, typeinfo, json, intsets, tables proc ptrToInt(x: pointer): int {.inline.} = result = cast[int](x) # don't skip alignment -proc storeAny(s: Stream, a: TAny, stored: var IntSet) = +proc storeAny(s: Stream, a: Any, stored: var IntSet) = case a.kind of akNone: assert false of akBool: s.write($getBool(a)) @@ -96,7 +96,7 @@ proc storeAny(s: Stream, a: TAny, stored: var IntSet) = of akInt..akInt64, akUInt..akUInt64: s.write($getBiggestInt(a)) of akFloat..akFloat128: s.write($getBiggestFloat(a)) -proc loadAny(p: var JsonParser, a: TAny, t: var Table[BiggestInt, pointer]) = +proc loadAny(p: var JsonParser, a: Any, t: var Table[BiggestInt, pointer]) = case a.kind of akNone: assert false of akBool: @@ -222,7 +222,7 @@ proc loadAny(p: var JsonParser, a: TAny, t: var Table[BiggestInt, pointer]) = raiseParseErr(p, "float expected") of akRange: loadAny(p, a.skipRange, t) -proc loadAny(s: Stream, a: TAny, t: var Table[BiggestInt, pointer]) = +proc loadAny(s: Stream, a: Any, t: var Table[BiggestInt, pointer]) = var p: JsonParser open(p, s, "unknown file") next(p) @@ -278,10 +278,11 @@ when not defined(testing) and isMainModule: else: nil - PNode = ref TNode - TNode = object + PNode = ref Node + Node = object next, prev: PNode data: string + {.deprecated: [TNode: Node].} proc buildList(): PNode = new(result) @@ -317,14 +318,15 @@ when not defined(testing) and isMainModule: testit(test7) type - TA {.inheritable.} = object - TB = object of TA + A {.inheritable.} = object + B = object of A f: int var - a: ref TA - b: ref TB + a: ref A + b: ref B new(b) a = b echo($$a[]) # produces "{}", not "{f: 0}" + diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim index d49dfae9f..76ff6a8e1 100644 --- a/lib/pure/memfiles.nim +++ b/lib/pure/memfiles.nim @@ -196,7 +196,7 @@ proc open*(filename: string, mode: FileMode = fmRead, if mappedSize != -1: result.size = mappedSize else: - var stat: TStat + var stat: Stat if fstat(result.handle, stat) != -1: # XXX: Hmm, this could be unsafe # Why is mmap taking int anyway? diff --git a/lib/pure/net.nim b/lib/pure/net.nim index cf37c271e..9ce0669bc 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -86,7 +86,7 @@ type IPv6, ## IPv6 address IPv4 ## IPv4 address - TIpAddress* = object ## stores an arbitrary IP address + IpAddress* = object ## stores an arbitrary IP address case family*: IpAddressFamily ## the type of the IP address (IPv4 or IPv6) of IpAddressFamily.IPv6: address_v6*: array[0..15, uint8] ## Contains the IP address in bytes in @@ -94,9 +94,10 @@ type of IpAddressFamily.IPv4: address_v4*: array[0..3, uint8] ## Contains the IP address in bytes in ## case of IPv4 +{.deprecated: [TIpAddress: IpAddress].} proc isIpAddress*(address_str: string): bool {.tags: [].} -proc parseIpAddress*(address_str: string): TIpAddress +proc parseIpAddress*(address_str: string): IpAddress proc isDisconnectionError*(flags: set[SocketFlag], lastError: OSErrorCode): bool = @@ -118,13 +119,13 @@ proc toOSFlags*(socketFlags: set[SocketFlag]): cint = result = result or MSG_PEEK of SocketFlag.SafeDisconn: continue -proc newSocket(fd: SocketHandle, isBuff: bool): Socket = +proc newSocket*(fd: SocketHandle, buffered = true): Socket = ## Creates a new socket as specified by the params. assert fd != osInvalidSocket new(result) result.fd = fd - result.isBuffered = isBuff - if isBuff: + result.isBuffered = buffered + if buffered: result.currPos = 0 proc newSocket*(domain, typ, protocol: cint, buffered = true): Socket = @@ -395,7 +396,7 @@ proc acceptAddr*(server: Socket, client: var Socket, address: var string, when false: #defined(ssl): proc acceptAddrSSL*(server: Socket, client: var Socket, - address: var string): TSSLAcceptResult {. + address: var string): SSLAcceptResult {. tags: [ReadIOEffect].} = ## This procedure should only be used for non-blocking **SSL** sockets. ## It will immediately return with one of the following values: @@ -992,39 +993,39 @@ proc isSsl*(socket: Socket): bool = proc getFd*(socket: Socket): SocketHandle = return socket.fd ## Returns the socket's file descriptor -proc IPv4_any*(): TIpAddress = +proc IPv4_any*(): IpAddress = ## Returns the IPv4 any address, which can be used to listen on all available ## network adapters - result = TIpAddress( + result = IpAddress( family: IpAddressFamily.IPv4, address_v4: [0'u8, 0, 0, 0]) -proc IPv4_loopback*(): TIpAddress = +proc IPv4_loopback*(): IpAddress = ## Returns the IPv4 loopback address (127.0.0.1) - result = TIpAddress( + result = IpAddress( family: IpAddressFamily.IPv4, address_v4: [127'u8, 0, 0, 1]) -proc IPv4_broadcast*(): TIpAddress = +proc IPv4_broadcast*(): IpAddress = ## Returns the IPv4 broadcast address (255.255.255.255) - result = TIpAddress( + result = IpAddress( family: IpAddressFamily.IPv4, address_v4: [255'u8, 255, 255, 255]) -proc IPv6_any*(): TIpAddress = +proc IPv6_any*(): IpAddress = ## Returns the IPv6 any address (::0), which can be used ## to listen on all available network adapters - result = TIpAddress( + result = IpAddress( family: IpAddressFamily.IPv6, address_v6: [0'u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) -proc IPv6_loopback*(): TIpAddress = +proc IPv6_loopback*(): IpAddress = ## Returns the IPv6 loopback address (::1) - result = TIpAddress( + result = IpAddress( family: IpAddressFamily.IPv6, address_v6: [0'u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]) -proc `==`*(lhs, rhs: TIpAddress): bool = +proc `==`*(lhs, rhs: IpAddress): bool = ## Compares two IpAddresses for Equality. Returns two if the addresses are equal if lhs.family != rhs.family: return false if lhs.family == IpAddressFamily.IPv4: @@ -1035,8 +1036,8 @@ proc `==`*(lhs, rhs: TIpAddress): bool = if lhs.address_v6[i] != rhs.address_v6[i]: return false return true -proc `$`*(address: TIpAddress): string = - ## Converts an TIpAddress into the textual representation +proc `$`*(address: IpAddress): string = + ## Converts an IpAddress into the textual representation result = "" case address.family of IpAddressFamily.IPv4: @@ -1095,7 +1096,7 @@ proc `$`*(address: TIpAddress): string = mask = mask shr 4 printedLastGroup = true -proc parseIPv4Address(address_str: string): TIpAddress = +proc parseIPv4Address(address_str: string): IpAddress = ## Parses IPv4 adresses ## Raises EInvalidValue on errors var @@ -1129,7 +1130,7 @@ proc parseIPv4Address(address_str: string): TIpAddress = raise newException(ValueError, "Invalid IP Address") result.address_v4[byteCount] = cast[uint8](currentByte) -proc parseIPv6Address(address_str: string): TIpAddress = +proc parseIPv6Address(address_str: string): IpAddress = ## Parses IPv6 adresses ## Raises EInvalidValue on errors result.family = IpAddressFamily.IPv6 @@ -1250,7 +1251,7 @@ proc parseIPv6Address(address_str: string): TIpAddress = raise newException(ValueError, "Invalid IP Address. The address consists of too many groups") -proc parseIpAddress(address_str: string): TIpAddress = +proc parseIpAddress(address_str: string): IpAddress = ## Parses an IP address ## Raises EInvalidValue on error if address_str == nil: diff --git a/lib/pure/nimprof.nim b/lib/pure/nimprof.nim index cce2a20ae..765d1e341 100644 --- a/lib/pure/nimprof.nim +++ b/lib/pure/nimprof.nim @@ -26,17 +26,19 @@ const withThreads = compileOption("threads") tickCountCorrection = 50_000 -when not declared(system.TStackTrace): - type TStackTrace = array [0..20, cstring] +when not declared(system.StackTrace): + type StackTrace = array [0..20, cstring] + {.deprecated: [TStackTrace: StackTrace].} # We use a simple hash table of bounded size to keep track of the stack traces: type - TProfileEntry = object + ProfileEntry = object total: int - st: TStackTrace - TProfileData = array [0..64*1024-1, ptr TProfileEntry] + st: StackTrace + ProfileData = array [0..64*1024-1, ptr ProfileEntry] +{.deprecated: [TProfileEntry: ProfileEntry, TProfileData: ProfileData].} -proc `==`(a, b: TStackTrace): bool = +proc `==`(a, b: StackTrace): bool = for i in 0 .. high(a): if a[i] != b[i]: return false result = true @@ -44,13 +46,13 @@ proc `==`(a, b: TStackTrace): bool = # XXX extract this data structure; it is generally useful ;-) # However a chain length of over 3000 is suspicious... var - profileData: TProfileData + profileData: ProfileData emptySlots = profileData.len * 3 div 2 maxChainLen = 0 totalCalls = 0 when not defined(memProfiler): - var interval: TNanos = 5_000_000 - tickCountCorrection # 5ms + var interval: Nanos = 5_000_000 - tickCountCorrection # 5ms proc setSamplingFrequency*(intervalInUs: int) = ## set this to change the sampling frequency. Default value is 5ms. @@ -62,11 +64,11 @@ when not defined(memProfiler): when withThreads: import locks var - profilingLock: TLock + profilingLock: Lock initLock profilingLock -proc hookAux(st: TStackTrace, costs: int) = +proc hookAux(st: StackTrace, costs: int) = # this is quite performance sensitive! when withThreads: acquire profilingLock inc totalCalls @@ -94,8 +96,8 @@ proc hookAux(st: TStackTrace, costs: int) = var chain = 0 while true: if profileData[h] == nil: - profileData[h] = cast[ptr TProfileEntry]( - allocShared0(sizeof(TProfileEntry))) + profileData[h] = cast[ptr ProfileEntry]( + allocShared0(sizeof(ProfileEntry))) profileData[h].total = costs profileData[h].st = st dec emptySlots @@ -115,7 +117,7 @@ when defined(memProfiler): var gTicker {.threadvar.}: int - proc hook(st: TStackTrace, size: int) {.nimcall.} = + proc hook(st: StackTrace, size: int) {.nimcall.} = if gTicker == 0: gTicker = -1 when defined(ignoreAllocationSize): @@ -127,26 +129,26 @@ when defined(memProfiler): else: var - t0 {.threadvar.}: TTicks + t0 {.threadvar.}: Ticks - proc hook(st: TStackTrace) {.nimcall.} = + proc hook(st: StackTrace) {.nimcall.} = if interval == 0: hookAux(st, 1) elif int64(t0) == 0 or getTicks() - t0 > interval: hookAux(st, 1) t0 = getTicks() -proc getTotal(x: ptr TProfileEntry): int = +proc getTotal(x: ptr ProfileEntry): int = result = if isNil(x): 0 else: x.total -proc cmpEntries(a, b: ptr TProfileEntry): int = +proc cmpEntries(a, b: ptr ProfileEntry): int = result = b.getTotal - a.getTotal proc `//`(a, b: int): string = result = format("$1/$2 = $3%", a, b, formatFloat(a / b * 100.0, ffDefault, 2)) proc writeProfile() {.noconv.} = - when declared(system.TStackTrace): + when declared(system.StackTrace): system.profilerHook = nil const filename = "profile_results.txt" echo "writing " & filename & "..." @@ -161,7 +163,7 @@ proc writeProfile() {.noconv.} = var perProc = initCountTable[string]() for i in 0..entries-1: var dups = initSet[string]() - for ii in 0..high(TStackTrace): + for ii in 0..high(StackTrace): let procname = profileData[i].st[ii] if isNil(procname): break let p = $procname @@ -176,7 +178,7 @@ proc writeProfile() {.noconv.} = writeln(f, "Entry: ", i+1, "/", entries, " Calls: ", profileData[i].total // totalCalls, " [sum: ", sum, "; ", sum // totalCalls, "]") - for ii in 0..high(TStackTrace): + for ii in 0..high(StackTrace): let procname = profileData[i].st[ii] if isNil(procname): break writeln(f, " ", procname, " ", perProc[$procname] // totalCalls) @@ -189,16 +191,16 @@ var disabled: int proc disableProfiling*() = - when declared(system.TStackTrace): + when declared(system.StackTrace): atomicDec disabled system.profilerHook = nil proc enableProfiling*() = - when declared(system.TStackTrace): + when declared(system.StackTrace): if atomicInc(disabled) >= 0: system.profilerHook = hook -when declared(system.TStackTrace): +when declared(system.StackTrace): system.profilerHook = hook addQuitProc(writeProfile) diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 3a5bcbfa1..4deb79f86 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -41,7 +41,7 @@ type OSErrorCode* = distinct int32 ## Specifies an OS Error Code. -{.deprecated: [FReadEnv: ReadEnvEffect, FWriteEnv: WriteEnvEffect, +{.deprecated: [FReadEnv: ReadEnvEffect, FWriteEnv: WriteEnvEffect, FReadDir: ReadDirEffect, FWriteDir: WriteDirEffect, TOSErrorCode: OSErrorCode @@ -359,7 +359,7 @@ when defined(windows): template wrapBinary(varname, winApiProc, arg, arg2: expr) {.immediate.} = var varname = winApiProc(newWideCString(arg), arg2) - proc findFirstFile(a: string, b: var TWIN32_FIND_DATA): THandle = + proc findFirstFile(a: string, b: var WIN32_FIND_DATA): Handle = result = findFirstFileW(newWideCString(a), b) template findNextFile(a, b: expr): expr = findNextFileW(a, b) template getCommandLine(): expr = getCommandLineW() @@ -373,7 +373,7 @@ when defined(windows): template getFilename(f: expr): expr = $f.cFilename - proc skipFindData(f: TWIN32_FIND_DATA): bool {.inline.} = + proc skipFindData(f: WIN32_FIND_DATA): bool {.inline.} = # Note - takes advantage of null delimiter in the cstring const dot = ord('.') result = f.cFileName[0].int == dot and (f.cFileName[1].int == 0 or @@ -390,7 +390,7 @@ proc existsFile*(filename: string): bool {.rtl, extern: "nos$1", if a != -1'i32: result = (a and FILE_ATTRIBUTE_DIRECTORY) == 0'i32 else: - var res: TStat + var res: Stat return stat(filename, res) >= 0'i32 and S_ISREG(res.st_mode) proc existsDir*(dir: string): bool {.rtl, extern: "nos$1", tags: [ReadDirEffect].} = @@ -404,7 +404,7 @@ proc existsDir*(dir: string): bool {.rtl, extern: "nos$1", tags: [ReadDirEffect] if a != -1'i32: result = (a and FILE_ATTRIBUTE_DIRECTORY) != 0'i32 else: - var res: TStat + var res: Stat return stat(dir, res) >= 0'i32 and S_ISDIR(res.st_mode) proc symlinkExists*(link: string): bool {.rtl, extern: "nos$1", @@ -419,7 +419,7 @@ proc symlinkExists*(link: string): bool {.rtl, extern: "nos$1", if a != -1'i32: result = (a and FILE_ATTRIBUTE_REPARSE_POINT) != 0'i32 else: - var res: TStat + var res: Stat return lstat(link, res) >= 0'i32 and S_ISLNK(res.st_mode) proc fileExists*(filename: string): bool {.inline.} = @@ -433,11 +433,11 @@ proc dirExists*(dir: string): bool {.inline.} = proc getLastModificationTime*(file: string): Time {.rtl, extern: "nos$1".} = ## Returns the `file`'s last modification time. when defined(posix): - var res: TStat + var res: Stat if stat(file, res) < 0'i32: raiseOSError(osLastError()) return res.st_mtime else: - var f: TWIN32_FIND_DATA + var f: WIN32_FIND_DATA var h = findFirstFile(file, f) if h == -1'i32: raiseOSError(osLastError()) result = winTimeToUnixTime(rdFileTime(f.ftLastWriteTime)) @@ -446,11 +446,11 @@ proc getLastModificationTime*(file: string): Time {.rtl, extern: "nos$1".} = proc getLastAccessTime*(file: string): Time {.rtl, extern: "nos$1".} = ## Returns the `file`'s last read or write access time. when defined(posix): - var res: TStat + var res: Stat if stat(file, res) < 0'i32: raiseOSError(osLastError()) return res.st_atime else: - var f: TWIN32_FIND_DATA + var f: WIN32_FIND_DATA var h = findFirstFile(file, f) if h == -1'i32: raiseOSError(osLastError()) result = winTimeToUnixTime(rdFileTime(f.ftLastAccessTime)) @@ -461,11 +461,11 @@ proc getCreationTime*(file: string): Time {.rtl, extern: "nos$1".} = ## Note that under posix OS's, the returned time may actually be the time at ## which the file's attribute's were last modified. when defined(posix): - var res: TStat + var res: Stat if stat(file, res) < 0'i32: raiseOSError(osLastError()) return res.st_ctime else: - var f: TWIN32_FIND_DATA + var f: WIN32_FIND_DATA var h = findFirstFile(file, f) if h == -1'i32: raiseOSError(osLastError()) result = winTimeToUnixTime(rdFileTime(f.ftCreationTime)) @@ -794,20 +794,20 @@ proc isAbsolute*(path: string): bool {.rtl, noSideEffect, extern: "nos$1".} = result = path[0] == '/' when defined(Windows): - proc openHandle(path: string, followSymlink=true): THandle = + proc openHandle(path: string, followSymlink=true): Handle = var flags = FILE_FLAG_BACKUP_SEMANTICS or FILE_ATTRIBUTE_NORMAL if not followSymlink: flags = flags or FILE_FLAG_OPEN_REPARSE_POINT when useWinUnicode: result = createFileW( - newWideCString(path), 0'i32, + newWideCString(path), 0'i32, FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, flags, 0 ) else: result = createFileA( - path, 0'i32, + path, 0'i32, FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, flags, 0 ) @@ -827,7 +827,7 @@ proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1", var lastErr: OSErrorCode if f1 != INVALID_HANDLE_VALUE and f2 != INVALID_HANDLE_VALUE: - var fi1, fi2: TBY_HANDLE_FILE_INFORMATION + var fi1, fi2: BY_HANDLE_FILE_INFORMATION if getFileInformationByHandle(f1, addr(fi1)) != 0 and getFileInformationByHandle(f2, addr(fi2)) != 0: @@ -846,7 +846,7 @@ proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1", if not success: raiseOSError(lastErr) else: - var a, b: TStat + var a, b: Stat if stat(path1, a) < 0'i32 or stat(path2, b) < 0'i32: raiseOSError(osLastError()) else: @@ -903,7 +903,7 @@ proc getFilePermissions*(filename: string): set[FilePermission] {. ## an error. On Windows, only the ``readonly`` flag is checked, every other ## permission is available in any case. when defined(posix): - var a: TStat + var a: Stat if stat(filename, a) < 0'i32: raiseOSError(osLastError()) result = {} if (a.st_mode and S_IRUSR) != 0'i32: result.incl(fpUserRead) @@ -924,11 +924,11 @@ proc getFilePermissions*(filename: string): set[FilePermission] {. var res = getFileAttributesA(filename) if res == -1'i32: raiseOSError(osLastError()) if (res and FILE_ATTRIBUTE_READONLY) != 0'i32: - result = {fpUserExec, fpUserRead, fpGroupExec, fpGroupRead, + result = {fpUserExec, fpUserRead, fpGroupExec, fpGroupRead, fpOthersExec, fpOthersRead} else: result = {fpUserExec..fpOthersRead} - + proc setFilePermissions*(filename: string, permissions: set[FilePermission]) {. rtl, extern: "nos$1", tags: [WriteDirEffect].} = ## sets the file permissions for `filename`. `OSError` is raised in case of @@ -939,15 +939,15 @@ proc setFilePermissions*(filename: string, permissions: set[FilePermission]) {. if fpUserRead in permissions: p = p or S_IRUSR if fpUserWrite in permissions: p = p or S_IWUSR if fpUserExec in permissions: p = p or S_IXUSR - + if fpGroupRead in permissions: p = p or S_IRGRP if fpGroupWrite in permissions: p = p or S_IWGRP if fpGroupExec in permissions: p = p or S_IXGRP - + if fpOthersRead in permissions: p = p or S_IROTH if fpOthersWrite in permissions: p = p or S_IWOTH if fpOthersExec in permissions: p = p or S_IXOTH - + if chmod(filename, p) != 0: raiseOSError(osLastError()) else: when useWinUnicode: @@ -955,7 +955,7 @@ proc setFilePermissions*(filename: string, permissions: set[FilePermission]) {. else: var res = getFileAttributesA(filename) if res == -1'i32: raiseOSError(osLastError()) - if fpUserWrite in permissions: + if fpUserWrite in permissions: res = res and not FILE_ATTRIBUTE_READONLY else: res = res or FILE_ATTRIBUTE_READONLY @@ -1030,11 +1030,11 @@ when not declared(ENOENT) and not defined(Windows): when defined(Windows): when useWinUnicode: template deleteFile(file: expr): expr {.immediate.} = deleteFileW(file) - template setFileAttributes(file, attrs: expr): expr {.immediate.} = + template setFileAttributes(file, attrs: expr): expr {.immediate.} = setFileAttributesW(file, attrs) else: template deleteFile(file: expr): expr {.immediate.} = deleteFileA(file) - template setFileAttributes(file, attrs: expr): expr {.immediate.} = + template setFileAttributes(file, attrs: expr): expr {.immediate.} = setFileAttributesA(file, attrs) proc removeFile*(file: string) {.rtl, extern: "nos$1", tags: [WriteDirEffect].} = @@ -1047,7 +1047,7 @@ proc removeFile*(file: string) {.rtl, extern: "nos$1", tags: [WriteDirEffect].} else: let f = file if deleteFile(f) == 0: - if getLastError() == ERROR_ACCESS_DENIED: + if getLastError() == ERROR_ACCESS_DENIED: if setFileAttributes(f, FILE_ATTRIBUTE_NORMAL) == 0: raiseOSError(osLastError()) if deleteFile(f) == 0: @@ -1220,7 +1220,7 @@ iterator walkFiles*(pattern: string): string {.tags: [ReadDirEffect].} = ## notation is supported. when defined(windows): var - f: TWIN32_FIND_DATA + f: WIN32_FIND_DATA res: int res = findFirstFile(pattern, f) if res != -1: @@ -1232,7 +1232,7 @@ iterator walkFiles*(pattern: string): string {.tags: [ReadDirEffect].} = findClose(res) else: # here we use glob var - f: TGlob + f: Glob res: int f.gl_offs = 0 f.gl_pathc = 0 @@ -1276,7 +1276,7 @@ iterator walkDir*(dir: string): tuple[kind: PathComponent, path: string] {. ## dirA/fileA1.txt ## dirA/fileA2.txt when defined(windows): - var f: TWIN32_FIND_DATA + var f: WIN32_FIND_DATA var h = findFirstFile(dir / "*", f) if h != -1: while true: @@ -1297,7 +1297,7 @@ iterator walkDir*(dir: string): tuple[kind: PathComponent, path: string] {. if x == nil: break var y = $x.d_name if y != "." and y != "..": - var s: TStat + var s: Stat y = dir / y var k = pcFile @@ -1319,9 +1319,9 @@ iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string {. ## walks over the directory `dir` and yields for each file in `dir`. The ## full path for each file is returned. ## **Warning**: - ## Modifying the directory structure while the iterator - ## is traversing may result in undefined behavior! - ## + ## Modifying the directory structure while the iterator + ## is traversing may result in undefined behavior! + ## ## Walking is recursive. `filter` controls the behaviour of the iterator: ## ## --------------------- --------------------------------------------- @@ -1424,7 +1424,7 @@ proc createSymlink*(src, dest: string) = ## by `src`. On most operating systems, will fail if a lonk ## ## **Warning**: - ## Some OS's (such as Microsoft Windows) restrict the creation + ## Some OS's (such as Microsoft Windows) restrict the creation ## of symlinks to root users (administrators). when defined(Windows): let flag = dirExists(src).int32 @@ -1444,7 +1444,7 @@ proc createHardlink*(src, dest: string) = ## Create a hard link at `dest` which points to the item specified ## by `src`. ## - ## **Warning**: Most OS's restrict the creation of hard links to + ## **Warning**: Most OS's restrict the creation of hard links to ## root users (administrators) . when defined(Windows): when useWinUnicode: @@ -1548,7 +1548,7 @@ proc parseCmdLine*(c: string): seq[string] {. add(a, c[i]) inc(i) add(result, a) - + proc copyFileWithPermissions*(source, dest: string, ignorePermissionErrors = true) = ## Copies a file from `source` to `dest` preserving file permissions. @@ -1842,7 +1842,7 @@ proc sleep*(milsecs: int) {.rtl, extern: "nos$1", tags: [TimeEffect].} = when defined(windows): winlean.sleep(int32(milsecs)) else: - var a, b: Ttimespec + var a, b: Timespec a.tv_sec = Time(milsecs div 1000) a.tv_nsec = (milsecs mod 1000) * 1000 * 1000 discard posix.nanosleep(a, b) @@ -1851,7 +1851,7 @@ proc getFileSize*(file: string): BiggestInt {.rtl, extern: "nos$1", tags: [ReadIOEffect].} = ## returns the file size of `file`. Can raise ``OSError``. when defined(windows): - var a: TWIN32_FIND_DATA + var a: WIN32_FIND_DATA var resA = findFirstFile(file, a) if resA == -1: raiseOSError(osLastError()) result = rdFileSize(a) @@ -1907,8 +1907,8 @@ when defined(Windows): FileId* = int64 else: type - DeviceId* = TDev - FileId* = Tino + DeviceId* = Dev + FileId* = Ino type FileInfo* = object @@ -1925,7 +1925,7 @@ type template rawToFormalFileInfo(rawInfo, formalInfo): expr = ## Transforms the native file info structure into the one nim uses. ## 'rawInfo' is either a 'TBY_HANDLE_FILE_INFORMATION' structure on Windows, - ## or a 'TStat' structure on posix + ## or a 'Stat' structure on posix when defined(Windows): template toTime(e): expr = winTimeToUnixTime(rdFileTime(e)) template merge(a, b): expr = a or (b shl 32) @@ -1936,10 +1936,10 @@ template rawToFormalFileInfo(rawInfo, formalInfo): expr = formalInfo.lastAccessTime = toTime(rawInfo.ftLastAccessTime) formalInfo.lastWriteTime = toTime(rawInfo.ftLastWriteTime) formalInfo.creationTime = toTime(rawInfo.ftCreationTime) - + # Retrieve basic permissions if (rawInfo.dwFileAttributes and FILE_ATTRIBUTE_READONLY) != 0'i32: - formalInfo.permissions = {fpUserExec, fpUserRead, fpGroupExec, + formalInfo.permissions = {fpUserExec, fpUserRead, fpGroupExec, fpGroupRead, fpOthersExec, fpOthersRead} else: result.permissions = {fpUserExec..fpOthersRead} @@ -1953,7 +1953,7 @@ template rawToFormalFileInfo(rawInfo, formalInfo): expr = else: - template checkAndIncludeMode(rawMode, formalMode: expr) = + template checkAndIncludeMode(rawMode, formalMode: expr) = if (rawInfo.st_mode and rawMode) != 0'i32: formalInfo.permissions.incl(formalMode) formalInfo.id = (rawInfo.st_dev, rawInfo.st_ino) @@ -1988,7 +1988,7 @@ proc getFileInfo*(handle: FileHandle): FileInfo = ## is invalid, an error will be thrown. # Done: ID, Kind, Size, Permissions, Link Count when defined(Windows): - var rawInfo: TBY_HANDLE_FILE_INFORMATION + var rawInfo: BY_HANDLE_FILE_INFORMATION # We have to use the super special '_get_osfhandle' call (wrapped above) # To transform the C file descripter to a native file handle. var realHandle = get_osfhandle(handle) @@ -1996,7 +1996,7 @@ proc getFileInfo*(handle: FileHandle): FileInfo = raiseOSError(osLastError()) rawToFormalFileInfo(rawInfo, result) else: - var rawInfo: TStat + var rawInfo: Stat if fstat(handle, rawInfo) < 0'i32: raiseOSError(osLastError()) rawToFormalFileInfo(rawInfo, result) @@ -2008,22 +2008,22 @@ proc getFileInfo*(file: File): FileInfo = proc getFileInfo*(path: string, followSymlink = true): FileInfo = ## Retrieves file information for the file object pointed to by `path`. - ## + ## ## Due to intrinsic differences between operating systems, the information ## contained by the returned `FileInfo` structure will be slightly different ## across platforms, and in some cases, incomplete or inaccurate. - ## + ## ## When `followSymlink` is true, symlinks are followed and the information ## retrieved is information related to the symlink's target. Otherwise, ## information on the symlink itself is retrieved. - ## + ## ## If the information cannot be retrieved, such as when the path doesn't ## exist, or when permission restrictions prevent the program from retrieving ## file information, an error will be thrown. when defined(Windows): - var + var handle = openHandle(path, followSymlink) - rawInfo: TBY_HANDLE_FILE_INFORMATION + rawInfo: BY_HANDLE_FILE_INFORMATION if handle == INVALID_HANDLE_VALUE: raiseOSError(osLastError()) if getFileInformationByHandle(handle, addr rawInfo) == 0: @@ -2031,7 +2031,7 @@ proc getFileInfo*(path: string, followSymlink = true): FileInfo = rawToFormalFileInfo(rawInfo, result) discard closeHandle(handle) else: - var rawInfo: TStat + var rawInfo: Stat if followSymlink: if stat(path, rawInfo) < 0'i32: raiseOSError(osLastError()) @@ -2044,7 +2044,7 @@ proc isHidden*(path: string): bool = ## Determines whether a given path is hidden or not. Returns false if the ## file doesn't exist. The given path must be accessible from the current ## working directory of the program. - ## + ## ## On Windows, a file is hidden if the file's 'hidden' attribute is set. ## On Unix-like systems, a file is hidden if it starts with a '.' (period) ## and is not *just* '.' or '..' ' ." diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index dc6f21174..33f5419d5 100644 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -26,13 +26,13 @@ when defined(linux): type ProcessObj = object of RootObj when defined(windows): - fProcessHandle: THandle + fProcessHandle: Handle inHandle, outHandle, errHandle: FileHandle - id: THandle + id: Handle else: inHandle, outHandle, errHandle: FileHandle inStream, outStream, errStream: Stream - id: TPid + id: Pid exitCode: cint Process* = ref ProcessObj ## represents an operating system process @@ -334,10 +334,11 @@ when not defined(useNimRtl): when defined(Windows) and not defined(useNimRtl): # We need to implement a handle stream for Windows: type - PFileHandleStream = ref TFileHandleStream - TFileHandleStream = object of StreamObj - handle: THandle + PFileHandleStream = ref FileHandleStream + FileHandleStream = object of StreamObj + handle: Handle atTheEnd: bool + {.deprecated: [TFileHandleStream: FileHandleStream].} proc hsClose(s: Stream) = discard # nothing to do here proc hsAtEnd(s: Stream): bool = return PFileHandleStream(s).atTheEnd @@ -361,7 +362,7 @@ when defined(Windows) and not defined(useNimRtl): addr bytesWritten, nil) if a == 0: raiseOSError(osLastError()) - proc newFileHandleStream(handle: THandle): PFileHandleStream = + proc newFileHandleStream(handle: Handle): PFileHandleStream = new(result) result.handle = handle result.closeImpl = hsClose @@ -387,22 +388,22 @@ when defined(Windows) and not defined(useNimRtl): copyMem(addr(result[L]), cstring(x), x.len+1) # copy \0 inc(L, x.len+1) - #proc open_osfhandle(osh: THandle, mode: int): int {. + #proc open_osfhandle(osh: Handle, mode: int): int {. # importc: "_open_osfhandle", header: "<fcntl.h>".} #var # O_WRONLY {.importc: "_O_WRONLY", header: "<fcntl.h>".}: int # O_RDONLY {.importc: "_O_RDONLY", header: "<fcntl.h>".}: int - proc createPipeHandles(rdHandle, wrHandle: var THandle) = - var piInheritablePipe: TSECURITY_ATTRIBUTES - piInheritablePipe.nLength = sizeof(TSECURITY_ATTRIBUTES).cint + proc createPipeHandles(rdHandle, wrHandle: var Handle) = + var piInheritablePipe: SECURITY_ATTRIBUTES + piInheritablePipe.nLength = sizeof(SECURITY_ATTRIBUTES).cint piInheritablePipe.lpSecurityDescriptor = nil piInheritablePipe.bInheritHandle = 1 if createPipe(rdHandle, wrHandle, piInheritablePipe, 1024) == 0'i32: raiseOSError(osLastError()) - proc fileClose(h: THandle) {.inline.} = + proc fileClose(h: Handle) {.inline.} = if h > 4: discard closeHandle(h) proc startProcess(command: string, @@ -411,10 +412,10 @@ when defined(Windows) and not defined(useNimRtl): env: StringTableRef = nil, options: set[ProcessOption] = {poStdErrToStdOut}): Process = var - si: TSTARTUPINFO - procInfo: TPROCESS_INFORMATION + si: STARTUPINFO + procInfo: PROCESS_INFORMATION success: int - hi, ho, he: THandle + hi, ho, he: Handle new(result) si.cb = sizeof(si).cint if poParentStreams notin options: @@ -525,9 +526,9 @@ when defined(Windows) and not defined(useNimRtl): proc execCmd(command: string): int = var - si: TSTARTUPINFO - procInfo: TPROCESS_INFORMATION - process: THandle + si: STARTUPINFO + procInfo: PROCESS_INFORMATION + process: Handle L: int32 si.cb = sizeof(si).cint si.hStdError = getStdHandle(STD_ERROR_HANDLE) @@ -554,7 +555,7 @@ when defined(Windows) and not defined(useNimRtl): proc select(readfds: var seq[Process], timeout = 500): int = assert readfds.len <= MAXIMUM_WAIT_OBJECTS - var rfds: TWOHandleArray + var rfds: WOHandleArray for i in 0..readfds.len()-1: rfds[i] = readfds[i].fProcessHandle @@ -595,7 +596,7 @@ elif not defined(useNimRtl): copyMem(result[i], addr(x[0]), x.len+1) inc(i) - type TStartProcessData = object + type StartProcessData = object sysCommand: cstring sysArgs: cstringArray sysEnv: cstringArray @@ -604,14 +605,15 @@ elif not defined(useNimRtl): optionPoUsePath: bool optionPoParentStreams: bool optionPoStdErrToStdOut: bool + {.deprecated: [TStartProcessData: StartProcessData].} when not defined(useFork): - proc startProcessAuxSpawn(data: TStartProcessData): TPid {. + proc startProcessAuxSpawn(data: StartProcessData): Pid {. tags: [ExecIOEffect, ReadEnvEffect], gcsafe.} - proc startProcessAuxFork(data: TStartProcessData): TPid {. + proc startProcessAuxFork(data: StartProcessData): Pid {. tags: [ExecIOEffect, ReadEnvEffect], gcsafe.} {.push stacktrace: off, profiler: off.} - proc startProcessAfterFork(data: ptr TStartProcessData) {. + proc startProcessAfterFork(data: ptr StartProcessData) {. tags: [ExecIOEffect, ReadEnvEffect], cdecl, gcsafe.} {.pop.} @@ -641,7 +643,7 @@ elif not defined(useNimRtl): for arg in args.items: sysArgsRaw.add arg - var pid: TPid + var pid: Pid var sysArgs = allocCStringArray(sysArgsRaw) defer: deallocCStringArray(sysArgs) @@ -653,7 +655,7 @@ elif not defined(useNimRtl): defer: deallocCStringArray(sysEnv) - var data: TStartProcessData + var data: StartProcessData data.sysCommand = sysCommand data.sysArgs = sysArgs data.sysEnv = sysEnv @@ -698,7 +700,7 @@ elif not defined(useNimRtl): discard close(pStdout[writeIdx]) when not defined(useFork): - proc startProcessAuxSpawn(data: TStartProcessData): TPid = + proc startProcessAuxSpawn(data: StartProcessData): Pid = var attr: Tposix_spawnattr var fops: Tposix_spawn_file_actions @@ -708,7 +710,7 @@ elif not defined(useNimRtl): chck posix_spawn_file_actions_init(fops) chck posix_spawnattr_init(attr) - var mask: Tsigset + var mask: Sigset chck sigemptyset(mask) chck posix_spawnattr_setsigmask(attr, mask) chck posix_spawnattr_setpgroup(attr, 0'i32) @@ -732,7 +734,7 @@ elif not defined(useNimRtl): # FIXME: chdir is global to process if data.workingDir.len > 0: setCurrentDir($data.workingDir) - var pid: TPid + var pid: Pid if data.optionPoUsePath: res = posix_spawnp(pid, data.sysCommand, fops, attr, data.sysArgs, data.sysEnv) @@ -744,14 +746,14 @@ elif not defined(useNimRtl): chck res return pid - proc startProcessAuxFork(data: TStartProcessData): TPid = + proc startProcessAuxFork(data: StartProcessData): Pid = if pipe(data.pErrorPipe) != 0: raiseOSError(osLastError()) defer: discard close(data.pErrorPipe[readIdx]) - var pid: TPid + var pid: Pid var dataCopy = data when defined(useClone): @@ -781,7 +783,7 @@ elif not defined(useNimRtl): return pid {.push stacktrace: off, profiler: off.} - proc startProcessFail(data: ptr TStartProcessData) = + proc startProcessFail(data: ptr StartProcessData) = var error: cint = errno discard write(data.pErrorPipe[writeIdx], addr error, sizeof(error)) exitnow(1) @@ -789,7 +791,7 @@ elif not defined(useNimRtl): when defined(macosx) or defined(freebsd): var environ {.importc.}: cstringArray - proc startProcessAfterFork(data: ptr TStartProcessData) = + proc startProcessAfterFork(data: ptr StartProcessData) = # Warning: no GC here! # Or anything that touches global structures - all called nim procs # must be marked with stackTrace:off. Inspect C code after making changes. diff --git a/lib/pure/parseopt.nim b/lib/pure/parseopt.nim index 4c92a7cdf..e9d10b51a 100644 --- a/lib/pure/parseopt.nim +++ b/lib/pure/parseopt.nim @@ -133,7 +133,7 @@ proc cmdLineRest*(p: OptParser): TaintedString {.rtl, extern: "npo$1".} = when declared(initOptParser): 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: + ## This uses the OptParser object. Example: ## ## .. code-block:: nim ## var diff --git a/lib/pure/pegs.nim b/lib/pure/pegs.nim index 39f0bfa95..ce837d9d1 100644 --- a/lib/pure/pegs.nim +++ b/lib/pure/pegs.nim @@ -74,8 +74,8 @@ type line: int ## line the symbol has been declared/used in col: int ## column the symbol has been declared/used in flags: set[NonTerminalFlag] ## the nonterminal's flags - rule: TNode ## the rule that the symbol refers to - TNode {.shallow.} = object + rule: Node ## the rule that the symbol refers to + Node {.shallow.} = object case kind: PegKind of pkEmpty..pkWhitespace: nil of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle: term: string @@ -83,12 +83,12 @@ type of pkCharChoice, pkGreedyRepSet: charChoice: ref set[char] of pkNonTerminal: nt: NonTerminal of pkBackRef..pkBackRefIgnoreStyle: index: range[0..MaxSubpatterns] - else: sons: seq[TNode] + else: sons: seq[Node] NonTerminal* = ref NonTerminalObj - Peg* = TNode ## type that represents a PEG + Peg* = Node ## type that represents a PEG -{.deprecated: [TPeg: Peg].} +{.deprecated: [TPeg: Peg, TNode: Node].} proc term*(t: string): Peg {.nosideEffect, rtl, extern: "npegs$1Str".} = ## constructs a PEG from a terminal string @@ -1014,12 +1014,12 @@ proc split*(s: string, sep: Peg): seq[string] {. # ------------------- scanner ------------------------------------------------- type - TModifier = enum + Modifier = enum modNone, modVerbatim, modIgnoreCase, modIgnoreStyle - TTokKind = enum ## enumeration of all tokens + TokKind = enum ## enumeration of all tokens tkInvalid, ## invalid token tkEof, ## end of file reached tkAny, ## . @@ -1046,9 +1046,9 @@ type tkDollar, ## '$' tkHat ## '^' - TToken {.final.} = object ## a token - kind: TTokKind ## the type of the token - modifier: TModifier + Token {.final.} = object ## a token + kind: TokKind ## the type of the token + modifier: Modifier literal: string ## the parsed (string) literal charset: set[char] ## if kind == tkCharSet index: int ## if kind == tkBackref @@ -1060,9 +1060,10 @@ type lineStart: int ## index of last line start in buffer colOffset: int ## column to add filename: string +{.deprecated: [TTokKind: TokKind, TToken: Token, TModifier: Modifier].} const - tokKindToStr: array[TTokKind, string] = [ + tokKindToStr: array[TokKind, string] = [ "invalid", "[EOF]", ".", "_", "identifier", "string literal", "character set", "(", ")", "{", "}", "{@}", "<-", "/", "*", "+", "&", "!", "?", @@ -1114,7 +1115,7 @@ proc handleHexChar(c: var PegLexer, xi: var int) = inc(c.bufpos) else: discard -proc getEscapedChar(c: var PegLexer, tok: var TToken) = +proc getEscapedChar(c: var PegLexer, tok: var Token) = inc(c.bufpos) case c.buf[c.bufpos] of 'r', 'R', 'c', 'C': @@ -1185,7 +1186,7 @@ proc skip(c: var PegLexer) = break # EndOfFile also leaves the loop c.bufpos = pos -proc getString(c: var PegLexer, tok: var TToken) = +proc getString(c: var PegLexer, tok: var Token) = tok.kind = tkStringLit var pos = c.bufpos + 1 var buf = c.buf @@ -1207,7 +1208,7 @@ proc getString(c: var PegLexer, tok: var TToken) = inc(pos) c.bufpos = pos -proc getDollar(c: var PegLexer, tok: var TToken) = +proc getDollar(c: var PegLexer, tok: var Token) = var pos = c.bufpos + 1 var buf = c.buf if buf[pos] in {'0'..'9'}: @@ -1220,7 +1221,7 @@ proc getDollar(c: var PegLexer, tok: var TToken) = tok.kind = tkDollar c.bufpos = pos -proc getCharSet(c: var PegLexer, tok: var TToken) = +proc getCharSet(c: var PegLexer, tok: var Token) = tok.kind = tkCharSet tok.charset = {} var pos = c.bufpos + 1 @@ -1271,7 +1272,7 @@ proc getCharSet(c: var PegLexer, tok: var TToken) = c.bufpos = pos if caret: tok.charset = {'\1'..'\xFF'} - tok.charset -proc getSymbol(c: var PegLexer, tok: var TToken) = +proc getSymbol(c: var PegLexer, tok: var Token) = var pos = c.bufpos var buf = c.buf while true: @@ -1281,7 +1282,7 @@ proc getSymbol(c: var PegLexer, tok: var TToken) = c.bufpos = pos tok.kind = tkIdentifier -proc getBuiltin(c: var PegLexer, tok: var TToken) = +proc getBuiltin(c: var PegLexer, tok: var Token) = if c.buf[c.bufpos+1] in strutils.Letters: inc(c.bufpos) getSymbol(c, tok) @@ -1290,7 +1291,7 @@ proc getBuiltin(c: var PegLexer, tok: var TToken) = tok.kind = tkEscaped getEscapedChar(c, tok) # may set tok.kind to tkInvalid -proc getTok(c: var PegLexer, tok: var TToken) = +proc getTok(c: var PegLexer, tok: var Token) = tok.kind = tkInvalid tok.modifier = modNone setLen(tok.literal, 0) @@ -1408,9 +1409,9 @@ type EInvalidPeg* = object of ValueError ## raised if an invalid ## PEG has been detected PegParser = object of PegLexer ## the PEG parser object - tok: TToken + tok: Token nonterms: seq[NonTerminal] - modifier: TModifier + modifier: Modifier captures: int identIsVerbatim: bool skip: Peg @@ -1425,7 +1426,7 @@ proc getTok(p: var PegParser) = getTok(p, p.tok) if p.tok.kind == tkInvalid: pegError(p, "invalid token") -proc eat(p: var PegParser, kind: TTokKind) = +proc eat(p: var PegParser, kind: TokKind) = if p.tok.kind == kind: getTok(p) else: pegError(p, tokKindToStr[kind] & " expected") @@ -1439,13 +1440,13 @@ proc getNonTerminal(p: var PegParser, name: string): NonTerminal = result = newNonTerminal(name, getLine(p), getColumn(p)) add(p.nonterms, result) -proc modifiedTerm(s: string, m: TModifier): Peg = +proc modifiedTerm(s: string, m: Modifier): 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): Peg = +proc modifiedBackref(s: int, m: Modifier): Peg = case m of modNone, modVerbatim: result = backref(s) of modIgnoreCase: result = backrefIgnoreCase(s) diff --git a/lib/pure/rationals.nim b/lib/pure/rationals.nim index 3b68a2381..8e1dbe464 100644 --- a/lib/pure/rationals.nim +++ b/lib/pure/rationals.nim @@ -206,13 +206,13 @@ proc abs*[T](x: Rational[T]): Rational[T] = result.num = abs x.num result.den = abs x.den -proc hash*[T](x: Rational[T]): THash = +proc hash*[T](x: Rational[T]): Hash = ## Computes hash for rational `x` # reduce first so that hash(x) == hash(y) for x == y var copy = x reduce(copy) - var h: THash = 0 + var h: Hash = 0 h = h !& hash(copy.num) h = h !& hash(copy.den) result = !$h diff --git a/lib/pure/rawsockets.nim b/lib/pure/rawsockets.nim index d08c5b769..6d656c983 100644 --- a/lib/pure/rawsockets.nim +++ b/lib/pure/rawsockets.nim @@ -106,13 +106,13 @@ proc `$`*(p: Port): string {.borrow.} ## returns the port number as a string proc toInt*(domain: Domain): cint - ## Converts the TDomain enum to a platform-dependent ``cint``. + ## Converts the Domain enum to a platform-dependent ``cint``. proc toInt*(typ: SockType): cint - ## Converts the TType enum to a platform-dependent ``cint``. + ## Converts the SockType enum to a platform-dependent ``cint``. proc toInt*(p: Protocol): cint - ## Converts the TProtocol enum to a platform-dependent ``cint``. + ## Converts the Protocol enum to a platform-dependent ``cint``. when not useWinVersion: proc toInt(domain: Domain): cint = diff --git a/lib/pure/redis.nim b/lib/pure/redis.nim index aa2e0f9bd..b738e4094 100644 --- a/lib/pure/redis.nim +++ b/lib/pure/redis.nim @@ -10,8 +10,8 @@ ## This module implements a redis client. It allows you to connect to a ## redis-server instance, send commands and receive replies. ## -## **Beware**: Most (if not all) functions that return a ``TRedisString`` may -## return ``redisNil``, and functions which return a ``TRedisList`` +## **Beware**: Most (if not all) functions that return a ``RedisString`` may +## return ``redisNil``, and functions which return a ``RedisList`` ## may return ``nil``. import sockets, os, strutils, parseutils @@ -843,27 +843,27 @@ proc pfmerge*(r: Redis, destination: string, sources: varargs[string]) = # TODO: pub/sub -- I don't think this will work synchronously. discard """ -proc psubscribe*(r: TRedis, pattern: openarray[string]): ???? = +proc psubscribe*(r: Redis, pattern: openarray[string]): ???? = ## Listen for messages published to channels matching the given patterns r.socket.send("PSUBSCRIBE $#\c\L" % pattern) return ??? -proc publish*(r: TRedis, channel: string, message: string): TRedisInteger = +proc publish*(r: Redis, channel: string, message: string): RedisInteger = ## Post a message to a channel r.socket.send("PUBLISH $# $#\c\L" % [channel, message]) return r.readInteger() -proc punsubscribe*(r: TRedis, [pattern: openarray[string], : string): ???? = +proc punsubscribe*(r: Redis, [pattern: openarray[string], : string): ???? = ## Stop listening for messages posted to channels matching the given patterns r.socket.send("PUNSUBSCRIBE $# $#\c\L" % [[pattern.join(), ]) return ??? -proc subscribe*(r: TRedis, channel: openarray[string]): ???? = +proc subscribe*(r: Redis, channel: openarray[string]): ???? = ## Listen for messages published to the given channels r.socket.send("SUBSCRIBE $#\c\L" % channel.join) return ??? -proc unsubscribe*(r: TRedis, [channel: openarray[string], : string): ???? = +proc unsubscribe*(r: Redis, [channel: openarray[string], : string): ???? = ## Stop listening for messages posted to the given channels r.socket.send("UNSUBSCRIBE $# $#\c\L" % [[channel.join(), ]) return ??? @@ -991,7 +991,7 @@ proc lastsave*(r: Redis): RedisInteger = return r.readInteger() discard """ -proc monitor*(r: TRedis) = +proc monitor*(r: Redis) = ## Listen for all requests received by the server in real time r.socket.send("MONITOR\c\L") raiseNoOK(r.readStatus(), r.pipeline.enabled) diff --git a/lib/pure/selectors.nim b/lib/pure/selectors.nim index 6901ecf58..e44b87051 100644 --- a/lib/pure/selectors.nim +++ b/lib/pure/selectors.nim @@ -18,7 +18,7 @@ elif defined(windows): else: import posix -proc hash*(x: SocketHandle): THash {.borrow.} +proc hash*(x: SocketHandle): Hash {.borrow.} proc `$`*(x: SocketHandle): string {.borrow.} type @@ -41,7 +41,7 @@ when defined(nimdoc): 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 + ## Registers file descriptor ``fd`` to selector ``s`` with a set of Event ## ``events``. proc update*(s: Selector, fd: SocketHandle, diff --git a/lib/pure/sexp.nim b/lib/pure/sexp.nim deleted file mode 100644 index 3c9fbc150..000000000 --- a/lib/pure/sexp.nim +++ /dev/null @@ -1,697 +0,0 @@ -# -# -# Nim's Runtime Library -# (c) Copyright 2015 Andreas Rumpf, Dominik Picheta -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -import - hashes, strutils, lexbase, streams, unicode, macros - -type - SexpEventKind* = enum ## enumeration of all events that may occur when parsing - sexpError, ## an error occurred during parsing - sexpEof, ## end of file reached - sexpString, ## a string literal - sexpSymbol, ## a symbol - sexpInt, ## an integer literal - sexpFloat, ## a float literal - sexpNil, ## the value ``nil`` - sexpDot, ## the dot to separate car/cdr - sexpListStart, ## start of a list: the ``(`` token - sexpListEnd, ## end of a list: the ``)`` token - - TTokKind = enum # must be synchronized with SexpEventKind! - tkError, - tkEof, - tkString, - tkSymbol, - tkInt, - tkFloat, - tkNil, - tkDot, - tkParensLe, - tkParensRi - tkSpace - - SexpError* = enum ## enumeration that lists all errors that can occur - errNone, ## no error - errInvalidToken, ## invalid token - errParensRiExpected, ## ``)`` expected - errQuoteExpected, ## ``"`` expected - errEofExpected, ## EOF expected - - SexpParser* = object of BaseLexer ## the parser object. - a: string - tok: TTokKind - kind: SexpEventKind - err: SexpError - -const - errorMessages: array [SexpError, string] = [ - "no error", - "invalid token", - "')' expected", - "'\"' or \"'\" expected", - "EOF expected", - ] - tokToStr: array [TTokKind, string] = [ - "invalid token", - "EOF", - "string literal", - "symbol", - "int literal", - "float literal", - "nil", - ".", - "(", ")", "space" - ] - -proc close*(my: var SexpParser) {.inline.} = - ## closes the parser `my` and its associated input stream. - lexbase.close(my) - -proc str*(my: SexpParser): string {.inline.} = - ## returns the character data for the events: ``sexpInt``, ``sexpFloat``, - ## ``sexpString`` - assert(my.kind in {sexpInt, sexpFloat, sexpString}) - result = my.a - -proc getInt*(my: SexpParser): BiggestInt {.inline.} = - ## returns the number for the event: ``sexpInt`` - assert(my.kind == sexpInt) - result = parseBiggestInt(my.a) - -proc getFloat*(my: SexpParser): float {.inline.} = - ## returns the number for the event: ``sexpFloat`` - assert(my.kind == sexpFloat) - result = parseFloat(my.a) - -proc kind*(my: SexpParser): SexpEventKind {.inline.} = - ## returns the current event type for the SEXP parser - result = my.kind - -proc getColumn*(my: SexpParser): int {.inline.} = - ## get the current column the parser has arrived at. - result = getColNumber(my, my.bufpos) - -proc getLine*(my: SexpParser): int {.inline.} = - ## get the current line the parser has arrived at. - result = my.lineNumber - -proc errorMsg*(my: SexpParser): string = - ## returns a helpful error message for the event ``sexpError`` - assert(my.kind == sexpError) - result = "($1, $2) Error: $3" % [$getLine(my), $getColumn(my), errorMessages[my.err]] - -proc errorMsgExpected*(my: SexpParser, e: string): string = - ## returns an error message "`e` expected" in the same format as the - ## other error messages - result = "($1, $2) Error: $3" % [$getLine(my), $getColumn(my), e & " expected"] - -proc handleHexChar(c: char, x: var int): bool = - result = true # Success - case c - of '0'..'9': x = (x shl 4) or (ord(c) - ord('0')) - of 'a'..'f': x = (x shl 4) or (ord(c) - ord('a') + 10) - of 'A'..'F': x = (x shl 4) or (ord(c) - ord('A') + 10) - else: result = false # error - -proc parseString(my: var SexpParser): TTokKind = - result = tkString - var pos = my.bufpos + 1 - var buf = my.buf - while true: - case buf[pos] - of '\0': - my.err = errQuoteExpected - result = tkError - break - of '"': - inc(pos) - break - of '\\': - case buf[pos+1] - of '\\', '"', '\'', '/': - add(my.a, buf[pos+1]) - inc(pos, 2) - of 'b': - add(my.a, '\b') - inc(pos, 2) - of 'f': - add(my.a, '\f') - inc(pos, 2) - of 'n': - add(my.a, '\L') - inc(pos, 2) - of 'r': - add(my.a, '\C') - inc(pos, 2) - of 't': - add(my.a, '\t') - inc(pos, 2) - of 'u': - inc(pos, 2) - var r: int - if handleHexChar(buf[pos], r): inc(pos) - if handleHexChar(buf[pos], r): inc(pos) - if handleHexChar(buf[pos], r): inc(pos) - if handleHexChar(buf[pos], r): inc(pos) - add(my.a, toUTF8(Rune(r))) - else: - # don't bother with the error - add(my.a, buf[pos]) - inc(pos) - of '\c': - pos = lexbase.handleCR(my, pos) - buf = my.buf - add(my.a, '\c') - of '\L': - pos = lexbase.handleLF(my, pos) - buf = my.buf - add(my.a, '\L') - else: - add(my.a, buf[pos]) - inc(pos) - my.bufpos = pos # store back - -proc parseNumber(my: var SexpParser) = - var pos = my.bufpos - var buf = my.buf - if buf[pos] == '-': - add(my.a, '-') - inc(pos) - if buf[pos] == '.': - add(my.a, "0.") - inc(pos) - else: - while buf[pos] in Digits: - add(my.a, buf[pos]) - inc(pos) - if buf[pos] == '.': - add(my.a, '.') - inc(pos) - # digits after the dot: - while buf[pos] in Digits: - add(my.a, buf[pos]) - inc(pos) - if buf[pos] in {'E', 'e'}: - add(my.a, buf[pos]) - inc(pos) - if buf[pos] in {'+', '-'}: - add(my.a, buf[pos]) - inc(pos) - while buf[pos] in Digits: - add(my.a, buf[pos]) - inc(pos) - my.bufpos = pos - -proc parseSymbol(my: var SexpParser) = - var pos = my.bufpos - var buf = my.buf - if buf[pos] in IdentStartChars: - while buf[pos] in IdentChars: - add(my.a, buf[pos]) - inc(pos) - my.bufpos = pos - -proc getTok(my: var SexpParser): TTokKind = - setLen(my.a, 0) - case my.buf[my.bufpos] - of '-', '0'..'9': # numbers that start with a . are not parsed - # correctly. - parseNumber(my) - if {'.', 'e', 'E'} in my.a: - result = tkFloat - else: - result = tkInt - of '"': #" # gotta fix nim-mode - result = parseString(my) - of '(': - inc(my.bufpos) - result = tkParensLe - of ')': - inc(my.bufpos) - result = tkParensRi - of '\0': - result = tkEof - of 'a'..'z', 'A'..'Z', '_': - parseSymbol(my) - if my.a == "nil": - result = tkNil - else: - result = tkSymbol - of ' ': - result = tkSpace - inc(my.bufpos) - of '.': - result = tkDot - inc(my.bufpos) - else: - inc(my.bufpos) - result = tkError - my.tok = result - -# ------------- higher level interface --------------------------------------- - -type - SexpNodeKind* = enum ## possible SEXP node types - SNil, - SInt, - SFloat, - SString, - SSymbol, - SList, - SCons - - SexpNode* = ref SexpNodeObj ## SEXP node - SexpNodeObj* {.acyclic.} = object - case kind*: SexpNodeKind - of SString: - str*: string - of SSymbol: - symbol*: string - of SInt: - num*: BiggestInt - of SFloat: - fnum*: float - of SList: - elems*: seq[SexpNode] - of SCons: - car: SexpNode - cdr: SexpNode - of SNil: - discard - - Cons = tuple[car: SexpNode, cdr: SexpNode] - - SexpParsingError* = object of ValueError ## is raised for a SEXP error - -proc raiseParseErr*(p: SexpParser, msg: string) {.noinline, noreturn.} = - ## raises an `ESexpParsingError` exception. - raise newException(SexpParsingError, errorMsgExpected(p, msg)) - -proc newSString*(s: string): SexpNode {.procvar.}= - ## Creates a new `SString SexpNode`. - new(result) - result.kind = SString - result.str = s - -proc newSStringMove(s: string): SexpNode = - new(result) - result.kind = SString - shallowCopy(result.str, s) - -proc newSInt*(n: BiggestInt): SexpNode {.procvar.} = - ## Creates a new `SInt SexpNode`. - new(result) - result.kind = SInt - result.num = n - -proc newSFloat*(n: float): SexpNode {.procvar.} = - ## Creates a new `SFloat SexpNode`. - new(result) - result.kind = SFloat - result.fnum = n - -proc newSNil*(): SexpNode {.procvar.} = - ## Creates a new `SNil SexpNode`. - new(result) - -proc newSCons*(car, cdr: SexpNode): SexpNode {.procvar.} = - ## Creates a new `SCons SexpNode` - new(result) - result.kind = SCons - result.car = car - result.cdr = cdr - -proc newSList*(): SexpNode {.procvar.} = - ## Creates a new `SList SexpNode` - new(result) - result.kind = SList - result.elems = @[] - -proc newSSymbol*(s: string): SexpNode {.procvar.} = - new(result) - result.kind = SSymbol - result.symbol = s - -proc newSSymbolMove(s: string): SexpNode = - new(result) - result.kind = SSymbol - shallowCopy(result.symbol, s) - -proc getStr*(n: SexpNode, default: string = ""): string = - ## Retrieves the string value of a `SString SexpNode`. - ## - ## Returns ``default`` if ``n`` is not a ``SString``. - if n.kind != SString: return default - else: return n.str - -proc getNum*(n: SexpNode, default: BiggestInt = 0): BiggestInt = - ## Retrieves the int value of a `SInt SexpNode`. - ## - ## Returns ``default`` if ``n`` is not a ``SInt``. - if n.kind != SInt: return default - else: return n.num - -proc getFNum*(n: SexpNode, default: float = 0.0): float = - ## Retrieves the float value of a `SFloat SexpNode`. - ## - ## Returns ``default`` if ``n`` is not a ``SFloat``. - if n.kind != SFloat: return default - else: return n.fnum - -proc getSymbol*(n: SexpNode, default: string = ""): string = - ## Retrieves the int value of a `SList SexpNode`. - ## - ## Returns ``default`` if ``n`` is not a ``SList``. - if n.kind != SSymbol: return default - else: return n.symbol - -proc getElems*(n: SexpNode, default: seq[SexpNode] = @[]): seq[SexpNode] = - ## Retrieves the int value of a `SList SexpNode`. - ## - ## Returns ``default`` if ``n`` is not a ``SList``. - if n.kind == SNil: return @[] - elif n.kind != SList: return default - else: return n.elems - -proc getCons*(n: SexpNode, defaults: Cons = (newSNil(), newSNil())): Cons = - ## Retrieves the cons value of a `SList SexpNode`. - ## - ## Returns ``default`` if ``n`` is not a ``SList``. - if n.kind == SCons: return (n.car, n.cdr) - elif n.kind == SList: return (n.elems[0], n.elems[1]) - else: return defaults - -proc sexp*(s: string): SexpNode = - ## Generic constructor for SEXP data. Creates a new `SString SexpNode`. - new(result) - result.kind = SString - result.str = s - -proc sexp*(n: BiggestInt): SexpNode = - ## Generic constructor for SEXP data. Creates a new `SInt SexpNode`. - new(result) - result.kind = SInt - result.num = n - -proc sexp*(n: float): SexpNode = - ## Generic constructor for SEXP data. Creates a new `SFloat SexpNode`. - new(result) - result.kind = SFloat - result.fnum = n - -proc sexp*(b: bool): SexpNode = - ## Generic constructor for SEXP data. Creates a new `SSymbol - ## SexpNode` with value t or `SNil SexpNode`. - new(result) - if b: - result.kind = SSymbol - result.symbol = "t" - else: - result.kind = SNil - -proc sexp*(elements: openArray[SexpNode]): SexpNode = - ## Generic constructor for SEXP data. Creates a new `SList SexpNode` - new(result) - result.kind = SList - newSeq(result.elems, elements.len) - for i, p in pairs(elements): result.elems[i] = p - -proc sexp*(s: SexpNode): SexpNode = - result = s - -proc toSexp(x: NimNode): NimNode {.compiletime.} = - case x.kind - of nnkBracket: - result = newNimNode(nnkBracket) - for i in 0 .. <x.len: - result.add(toSexp(x[i])) - - else: - result = x - - result = prefix(result, "sexp") - -macro convertSexp*(x: expr): expr = - ## Convert an expression to a SexpNode directly, without having to specify - ## `%` for every element. - result = toSexp(x) - -proc `==`* (a,b: SexpNode): bool = - ## Check two nodes for equality - if a.isNil: - if b.isNil: return true - return false - elif b.isNil or a.kind != b.kind: - return false - else: - return case a.kind - of SString: - a.str == b.str - of SInt: - a.num == b.num - of SFloat: - a.fnum == b.fnum - of SNil: - true - of SList: - a.elems == b.elems - of SSymbol: - a.symbol == b.symbol - of SCons: - a.car == b.car and a.cdr == b.cdr - -proc hash* (n:SexpNode): THash = - ## Compute the hash for a SEXP node - case n.kind - of SList: - result = hash(n.elems) - of SInt: - result = hash(n.num) - of SFloat: - result = hash(n.fnum) - of SString: - result = hash(n.str) - of SNil: - result = hash(0) - of SSymbol: - result = hash(n.symbol) - of SCons: - result = hash(n.car) !& hash(n.cdr) - -proc len*(n: SexpNode): int = - ## If `n` is a `SList`, it returns the number of elements. - ## If `n` is a `JObject`, it returns the number of pairs. - ## Else it returns 0. - case n.kind - of SList: result = n.elems.len - else: discard - -proc `[]`*(node: SexpNode, index: int): SexpNode = - ## Gets the node at `index` in a List. Result is undefined if `index` - ## is out of bounds - assert(not isNil(node)) - assert(node.kind == SList) - return node.elems[index] - -proc add*(father, child: SexpNode) = - ## Adds `child` to a SList node `father`. - assert father.kind == SList - father.elems.add(child) - -# ------------- pretty printing ---------------------------------------------- - -proc indent(s: var string, i: int) = - s.add(spaces(i)) - -proc newIndent(curr, indent: int, ml: bool): int = - if ml: return curr + indent - else: return indent - -proc nl(s: var string, ml: bool) = - if ml: s.add("\n") - -proc escapeJson*(s: string): string = - ## Converts a string `s` to its JSON representation. - result = newStringOfCap(s.len + s.len shr 3) - result.add("\"") - for x in runes(s): - var r = int(x) - if r >= 32 and r <= 127: - var c = chr(r) - case c - of '"': result.add("\\\"") #" # gotta fix nim-mode - of '\\': result.add("\\\\") - else: result.add(c) - else: - result.add("\\u") - result.add(toHex(r, 4)) - result.add("\"") - -proc copy*(p: SexpNode): SexpNode = - ## Performs a deep copy of `a`. - case p.kind - of SString: - result = newSString(p.str) - of SInt: - result = newSInt(p.num) - of SFloat: - result = newSFloat(p.fnum) - of SNil: - result = newSNil() - of SSymbol: - result = newSSymbol(p.symbol) - of SList: - result = newSList() - for i in items(p.elems): - result.elems.add(copy(i)) - of SCons: - result = newSCons(copy(p.car), copy(p.cdr)) - -proc toPretty(result: var string, node: SexpNode, indent = 2, ml = true, - lstArr = false, currIndent = 0) = - case node.kind - of SString: - if lstArr: result.indent(currIndent) - result.add(escapeJson(node.str)) - of SInt: - if lstArr: result.indent(currIndent) - result.add($node.num) - of SFloat: - if lstArr: result.indent(currIndent) - result.add($node.fnum) - of SNil: - if lstArr: result.indent(currIndent) - result.add("nil") - of SSymbol: - if lstArr: result.indent(currIndent) - result.add($node.symbol) - of SList: - if lstArr: result.indent(currIndent) - if len(node.elems) != 0: - result.add("(") - result.nl(ml) - for i in 0..len(node.elems)-1: - if i > 0: - result.add(" ") - result.nl(ml) # New Line - toPretty(result, node.elems[i], indent, ml, - true, newIndent(currIndent, indent, ml)) - result.nl(ml) - result.indent(currIndent) - result.add(")") - else: result.add("nil") - of SCons: - if lstArr: result.indent(currIndent) - result.add("(") - toPretty(result, node.car, indent, ml, - true, newIndent(currIndent, indent, ml)) - result.add(" . ") - toPretty(result, node.cdr, indent, ml, - true, newIndent(currIndent, indent, ml)) - result.add(")") - -proc pretty*(node: SexpNode, indent = 2): string = - ## Converts `node` to its Sexp Representation, with indentation and - ## on multiple lines. - result = "" - toPretty(result, node, indent) - -proc `$`*(node: SexpNode): string = - ## Converts `node` to its SEXP Representation on one line. - result = "" - toPretty(result, node, 0, false) - -iterator items*(node: SexpNode): SexpNode = - ## Iterator for the items of `node`. `node` has to be a SList. - assert node.kind == SList - for i in items(node.elems): - yield i - -iterator mitems*(node: var SexpNode): var SexpNode = - ## Iterator for the items of `node`. `node` has to be a SList. Items can be - ## modified. - assert node.kind == SList - for i in mitems(node.elems): - yield i - -proc eat(p: var SexpParser, tok: TTokKind) = - if p.tok == tok: discard getTok(p) - else: raiseParseErr(p, tokToStr[tok]) - -proc parseSexp(p: var SexpParser): SexpNode = - ## Parses SEXP from a SEXP Parser `p`. - case p.tok - of tkString: - # we capture 'p.a' here, so we need to give it a fresh buffer afterwards: - result = newSStringMove(p.a) - p.a = "" - discard getTok(p) - of tkInt: - result = newSInt(parseBiggestInt(p.a)) - discard getTok(p) - of tkFloat: - result = newSFloat(parseFloat(p.a)) - discard getTok(p) - of tkNil: - result = newSNil() - discard getTok(p) - of tkSymbol: - result = newSSymbolMove(p.a) - p.a = "" - discard getTok(p) - of tkParensLe: - result = newSList() - discard getTok(p) - while p.tok notin {tkParensRi, tkDot}: - result.add(parseSexp(p)) - if p.tok != tkSpace: break - discard getTok(p) - if p.tok == tkDot: - eat(p, tkDot) - eat(p, tkSpace) - result.add(parseSexp(p)) - result = newSCons(result[0], result[1]) - eat(p, tkParensRi) - of tkSpace, tkDot, tkError, tkParensRi, tkEof: - raiseParseErr(p, "(") - -proc open*(my: var SexpParser, input: Stream) = - ## initializes the parser with an input stream. - lexbase.open(my, input) - my.kind = sexpError - my.a = "" - -proc parseSexp*(s: Stream): SexpNode = - ## Parses from a buffer `s` into a `SexpNode`. - var p: SexpParser - p.open(s) - discard getTok(p) # read first token - result = p.parseSexp() - p.close() - -proc parseSexp*(buffer: string): SexpNode = - ## Parses Sexp from `buffer`. - result = parseSexp(newStringStream(buffer)) - -when isMainModule: - let testSexp = parseSexp("""(1 (98 2) nil (2) foobar "foo" 9.234)""") - assert(testSexp[0].getNum == 1) - assert(testSexp[1][0].getNum == 98) - assert(testSexp[2].getElems == @[]) - assert(testSexp[4].getSymbol == "foobar") - assert(testSexp[5].getStr == "foo") - - let alist = parseSexp("""((1 . 2) (2 . "foo"))""") - assert(alist[0].getCons.car.getNum == 1) - assert(alist[0].getCons.cdr.getNum == 2) - assert(alist[1].getCons.cdr.getStr == "foo") - - # Generator: - var j = convertSexp([true, false, "foobar", [1, 2, "baz"]]) - assert($j == """(t nil "foobar" (1 2 "baz"))""") diff --git a/lib/pure/sockets.nim b/lib/pure/sockets.nim index 64e2cdcd3..a10255e5b 100644 --- a/lib/pure/sockets.nim +++ b/lib/pure/sockets.nim @@ -75,7 +75,7 @@ const BufferSize*: int = 4000 ## size of a buffered socket's buffer type - TSocketImpl = object ## socket type + SocketImpl = object ## socket type fd: SocketHandle case isBuffered: bool # determines whether this socket is buffered. of true: @@ -94,7 +94,7 @@ type of false: nil nonblocking: bool - Socket* = ref TSocketImpl + Socket* = ref SocketImpl Port* = distinct uint16 ## port type @@ -146,8 +146,9 @@ type {.deprecated: [TSocket: Socket, TType: SockType, TPort: Port, TDomain: Domain, TProtocol: Protocol, TServent: Servent, THostent: Hostent, - TSOBool: SOBool, TRecvLineResult: RecvLineResult, - TReadLineResult: ReadLineResult, ETimeout: TimeoutError].} + TSOBool: SOBool, TRecvLineResult: RecvLineResult, + TReadLineResult: ReadLineResult, ETimeout: TimeoutError, + TSocketImpl: SocketImpl].} when defined(booting): let invalidSocket*: Socket = nil ## invalid socket diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim index c85a09bad..50b5c219a 100644 --- a/lib/pure/streams.nim +++ b/lib/pure/streams.nim @@ -279,7 +279,7 @@ proc ssAtEnd(s: Stream): bool = proc ssSetPosition(s: Stream, pos: int) = var s = StringStream(s) - s.pos = clamp(pos, 0, s.data.high) + s.pos = clamp(pos, 0, s.data.len) proc ssGetPosition(s: Stream): int = var s = StringStream(s) @@ -327,7 +327,7 @@ proc newStringStream*(s: string = ""): StringStream = when not defined(js): type - FileStream* = ref FileStreamObj ## a stream that encapsulates a `TFile` + FileStream* = ref FileStreamObj ## a stream that encapsulates a `File` FileStreamObj* = object of Stream f: File {.deprecated: [PFileStream: FileStream, TFileStream: FileStreamObj].} diff --git a/lib/pure/strtabs.nim b/lib/pure/strtabs.nim index 7fdd994f2..86f81aa43 100644 --- a/lib/pure/strtabs.nim +++ b/lib/pure/strtabs.nim @@ -74,7 +74,7 @@ const growthFactor = 2 startSize = 64 -proc myhash(t: StringTableRef, key: string): THash = +proc myhash(t: StringTableRef, key: string): Hash = case t.mode of modeCaseSensitive: result = hashes.hash(key) of modeCaseInsensitive: result = hashes.hashIgnoreCase(key) @@ -90,11 +90,11 @@ proc mustRehash(length, counter: int): bool = assert(length > counter) result = (length * 2 < counter * 3) or (length - counter < 4) -proc nextTry(h, maxHash: THash): THash {.inline.} = +proc nextTry(h, maxHash: Hash): Hash {.inline.} = result = ((5 * h) + 1) and maxHash proc rawGet(t: StringTableRef, key: string): int = - var h: THash = myhash(t, key) and high(t.data) # start with real hash value + var h: Hash = myhash(t, key) and high(t.data) # start with real hash value while not isNil(t.data[h].key): if myCmp(t, t.data[h].key, key): return h @@ -122,7 +122,7 @@ proc hasKey*(t: StringTableRef, key: string): bool {.rtl, extern: "nst$1".} = result = rawGet(t, key) >= 0 proc rawInsert(t: StringTableRef, data: var KeyValuePairSeq, key, val: string) = - var h: THash = myhash(t, key) and high(data) + var h: Hash = myhash(t, key) and high(data) while not isNil(data[h].key): h = nextTry(h, high(data)) data[h].key = key diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index eb4be719a..317da9a0a 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -23,7 +23,8 @@ import parseutils include "system/inclrtl" type - TCharSet* {.deprecated.} = set[char] # for compatibility with Nim + CharSet* {.deprecated.} = set[char] # for compatibility with Nim +{.deprecated: [TCharSet: CharSet].} const Whitespace* = {' ', '\t', '\v', '\r', '\l', '\f'} diff --git a/lib/pure/subexes.nim b/lib/pure/subexes.nim index d213c99e6..46824645d 100644 --- a/lib/pure/subexes.nim +++ b/lib/pure/subexes.nim @@ -37,13 +37,14 @@ proc raiseInvalidFormat(msg: string) {.noinline.} = raise newException(SubexError, "invalid format string: " & msg) type - TFormatParser = object {.pure, final.} + FormatParser = object {.pure, final.} when defined(js): f: string # we rely on the '\0' terminator # which JS's native string doesn't have else: f: cstring num, i, lineLen: int +{.deprecated: [TFormatParser: FormatParser].} template call(x: stmt) {.immediate.} = p.i = i @@ -57,7 +58,7 @@ template callNoLineLenTracking(x: stmt) {.immediate.} = i = p.i p.lineLen = oldLineLen -proc getFormatArg(p: var TFormatParser, a: openArray[string]): int = +proc getFormatArg(p: var FormatParser, a: openArray[string]): int = const PatternChars = {'a'..'z', 'A'..'Z', '0'..'9', '\128'..'\255', '_'} var i = p.i var f = p.f @@ -90,22 +91,22 @@ proc getFormatArg(p: var TFormatParser, a: openArray[string]): int = if result >=% a.len: raiseInvalidFormat("index out of bounds: " & $result) p.i = i -proc scanDollar(p: var TFormatParser, a: openarray[string], s: var string) {. +proc scanDollar(p: var FormatParser, a: openarray[string], s: var string) {. noSideEffect.} -proc emitChar(p: var TFormatParser, x: var string, ch: char) {.inline.} = +proc emitChar(p: var FormatParser, x: var string, ch: char) {.inline.} = x.add(ch) if ch == '\L': p.lineLen = 0 else: inc p.lineLen -proc emitStrLinear(p: var TFormatParser, x: var string, y: string) {.inline.} = +proc emitStrLinear(p: var FormatParser, x: var string, y: string) {.inline.} = for ch in items(y): emitChar(p, x, ch) -proc emitStr(p: var TFormatParser, x: var string, y: string) {.inline.} = +proc emitStr(p: var FormatParser, x: var string, y: string) {.inline.} = x.add(y) inc p.lineLen, y.len -proc scanQuote(p: var TFormatParser, x: var string, toAdd: bool) = +proc scanQuote(p: var FormatParser, x: var string, toAdd: bool) = var i = p.i+1 var f = p.f while true: @@ -120,7 +121,7 @@ proc scanQuote(p: var TFormatParser, x: var string, toAdd: bool) = inc i p.i = i -proc scanBranch(p: var TFormatParser, a: openArray[string], +proc scanBranch(p: var FormatParser, a: openArray[string], x: var string, choice: int) = var i = p.i var f = p.f @@ -167,7 +168,7 @@ proc scanBranch(p: var TFormatParser, a: openArray[string], i = last p.i = i+1 -proc scanSlice(p: var TFormatParser, a: openarray[string]): tuple[x, y: int] = +proc scanSlice(p: var FormatParser, a: openarray[string]): tuple[x, y: int] = var slice = false var i = p.i var f = p.f @@ -193,7 +194,7 @@ proc scanSlice(p: var TFormatParser, a: openarray[string]): tuple[x, y: int] = inc i p.i = i -proc scanDollar(p: var TFormatParser, a: openarray[string], s: var string) = +proc scanDollar(p: var FormatParser, a: openarray[string], s: var string) = var i = p.i var f = p.f case f[i] @@ -312,7 +313,7 @@ proc subex*(s: string): Subex = 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 + var p: FormatParser p.f = formatstr.string var i = 0 while i < len(formatstr.string): @@ -386,10 +387,10 @@ when isMainModule: longishA, longish)""" - assert "type TMyEnum* = enum\n $', '2i'\n '{..}" % ["fieldA", + assert "type MyEnum* = enum\n $', '2i'\n '{..}" % ["fieldA", "fieldB", "FiledClkad", "fieldD", "fieldE", "longishFieldName"] == strutils.unindent """ - type TMyEnum* = enum + type MyEnum* = enum fieldA, fieldB, FiledClkad, fieldD, fieldE, longishFieldName""" @@ -400,11 +401,11 @@ when isMainModule: doAssert subex"$['''|'|''''|']']#" % "0" == "'|" - assert subex("type\n TEnum = enum\n $', '40c'\n '{..}") % [ + assert subex("type\n Enum = enum\n $', '40c'\n '{..}") % [ "fieldNameA", "fieldNameB", "fieldNameC", "fieldNameD"] == strutils.unindent """ type - TEnum = enum + Enum = enum fieldNameA, fieldNameB, fieldNameC, fieldNameD""" diff --git a/lib/pure/terminal.nim b/lib/pure/terminal.nim index 7b4d548fe..1e9c40f06 100644 --- a/lib/pure/terminal.nim +++ b/lib/pure/terminal.nim @@ -20,7 +20,7 @@ when defined(windows): import windows, os var - conHandle: THandle + conHandle: Handle # = createFile("CONOUT$", GENERIC_WRITE, 0, nil, OPEN_ALWAYS, 0, 0) block: @@ -30,13 +30,13 @@ when defined(windows): raiseOSError(osLastError()) proc getCursorPos(): tuple [x,y: int] = - var c: TCONSOLESCREENBUFFERINFO + var c: CONSOLESCREENBUFFERINFO if GetConsoleScreenBufferInfo(conHandle, addr(c)) == 0: raiseOSError(osLastError()) return (int(c.dwCursorPosition.X), int(c.dwCursorPosition.Y)) proc getAttributes(): int16 = - var c: TCONSOLESCREENBUFFERINFO + var c: CONSOLESCREENBUFFERINFO # workaround Windows bugs: try several times if GetConsoleScreenBufferInfo(conHandle, addr(c)) != 0: return c.wAttributes @@ -51,11 +51,11 @@ else: proc setRaw(fd: FileHandle, time: cint = TCSAFLUSH) = var mode: Termios discard fd.tcgetattr(addr mode) - mode.c_iflag = mode.c_iflag and not Tcflag(BRKINT or ICRNL or INPCK or + mode.c_iflag = mode.c_iflag and not Cflag(BRKINT or ICRNL or INPCK or ISTRIP or IXON) - mode.c_oflag = mode.c_oflag and not Tcflag(OPOST) - mode.c_cflag = (mode.c_cflag and not Tcflag(CSIZE or PARENB)) or CS8 - mode.c_lflag = mode.c_lflag and not Tcflag(ECHO or ICANON or IEXTEN or ISIG) + mode.c_oflag = mode.c_oflag and not Cflag(OPOST) + mode.c_cflag = (mode.c_cflag and not Cflag(CSIZE or PARENB)) or CS8 + mode.c_lflag = mode.c_lflag and not Cflag(ECHO or ICANON or IEXTEN or ISIG) mode.c_cc[VMIN] = 1.cuchar mode.c_cc[VTIME] = 0.cuchar discard fd.tcsetattr(time, addr mode) @@ -64,7 +64,7 @@ proc setCursorPos*(x, y: int) = ## sets the terminal's cursor to the (x,y) position. (0,0) is the ## upper left of the screen. when defined(windows): - var c: TCOORD + var c: COORD c.X = int16(x) c.Y = int16(y) if SetConsoleCursorPosition(conHandle, c) == 0: raiseOSError(osLastError()) @@ -75,7 +75,7 @@ proc setCursorXPos*(x: int) = ## sets the terminal's cursor to the x position. The y position is ## not changed. when defined(windows): - var scrbuf: TCONSOLESCREENBUFFERINFO + var scrbuf: CONSOLESCREENBUFFERINFO var hStdout = conHandle if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: raiseOSError(osLastError()) @@ -91,7 +91,7 @@ when defined(windows): ## sets the terminal's cursor to the y position. The x position is ## not changed. **Warning**: This is not supported on UNIX! when defined(windows): - var scrbuf: TCONSOLESCREENBUFFERINFO + var scrbuf: CONSOLESCREENBUFFERINFO var hStdout = conHandle if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: raiseOSError(osLastError()) @@ -172,7 +172,7 @@ else: proc eraseLine* = ## Erases the entire current line. when defined(windows): - var scrbuf: TCONSOLESCREENBUFFERINFO + var scrbuf: CONSOLESCREENBUFFERINFO var numwrote: DWORD var hStdout = conHandle if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: @@ -196,9 +196,9 @@ proc eraseLine* = proc eraseScreen* = ## Erases the screen with the background colour and moves the cursor to home. when defined(windows): - var scrbuf: TCONSOLESCREENBUFFERINFO + var scrbuf: CONSOLESCREENBUFFERINFO var numwrote: DWORD - var origin: TCOORD # is inititalized to 0, 0 + var origin: COORD # is inititalized to 0, 0 var hStdout = conHandle if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: diff --git a/lib/pure/times.nim b/lib/pure/times.nim index b8836c15b..597488782 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -470,7 +470,7 @@ when not defined(JS): posix_gettimeofday(a) result = toFloat(a.tv_sec) + toFloat(a.tv_usec)*0.00_0001 elif defined(windows): - var f: winlean.TFILETIME + var f: winlean.FILETIME getSystemTimeAsFileTime(f) var i64 = rdFileTime(f) - epochDiff var secs = i64 div rateDiff diff --git a/lib/pure/unicode.nim b/lib/pure/unicode.nim index 5fd3c2418..4446eaa0c 100644 --- a/lib/pure/unicode.nim +++ b/lib/pure/unicode.nim @@ -372,11 +372,17 @@ const 0xfe74] # spaceRanges = [ - 0x0009, 0x000a, # tab and newline + 0x0009, 0x000d, # tab and newline 0x0020, 0x0020, # space + 0x0085, 0x0085, # next line 0x00a0, 0x00a0, # - 0x2000, 0x200b, # - + 0x1680, 0x1680, # Ogham space mark + 0x2000, 0x200b, # en dash .. zero-width space + 0x200e, 0x200f, # LTR mark .. RTL mark (pattern whitespace) 0x2028, 0x2029, # - 0x3000, 0x3000, # + 0x202f, 0x202f, # narrow no-break space + 0x205f, 0x205f, # medium mathematical space + 0x3000, 0x3000, # ideographic space 0xfeff, 0xfeff] # toupperRanges = [ diff --git a/lib/pure/unittest.nim b/lib/pure/unittest.nim index 092b1fba2..dbbd3cabc 100644 --- a/lib/pure/unittest.nim +++ b/lib/pure/unittest.nim @@ -99,8 +99,9 @@ template test*(name: expr, body: stmt): stmt {.immediate, dirty.} = body except: - checkpoint("Unhandled exception: " & getCurrentExceptionMsg()) - echo getCurrentException().getStackTrace() + when not defined(js): + checkpoint("Unhandled exception: " & getCurrentExceptionMsg()) + echo getCurrentException().getStackTrace() fail() finally: @@ -114,9 +115,7 @@ proc checkpoint*(msg: string) = template fail* = bind checkpoints for msg in items(checkpoints): - # this used to be 'echo' which now breaks due to a bug. XXX will revisit - # this issue later. - stdout.writeln msg + echo msg when not defined(ECMAScript): if abortOnError: quit(1) |