From 9b5b2546200c15541bff38b9f22eb7682e68d70a Mon Sep 17 00:00:00 2001 From: Adam Strzelecki Date: Wed, 30 Sep 2015 12:20:56 +0200 Subject: [PATCH 01/17] rawsockets: Fix getaddrinfo on FreeBSD Currently due bug in FreeBSD passing AI_V4MAPPED to addrinfo.ai_flags causes getaddrinfo to fail with EAI_BADFLAGS ("Invalid value for ai_flags"). That's why we should disable this flag for now on FreeBSD. https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=198092 --- lib/pure/rawsockets.nim | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/pure/rawsockets.nim b/lib/pure/rawsockets.nim index f5860ef282..2d7b0e5ea1 100644 --- a/lib/pure/rawsockets.nim +++ b/lib/pure/rawsockets.nim @@ -201,7 +201,9 @@ proc getAddrInfo*(address: string, port: Port, domain: Domain = AF_INET, hints.ai_family = toInt(domain) hints.ai_socktype = toInt(sockType) hints.ai_protocol = toInt(protocol) - hints.ai_flags = AI_V4MAPPED + # https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=198092 + when not defined(freebsd): + hints.ai_flags = AI_V4MAPPED var gaiResult = getaddrinfo(address, $port, addr(hints), result) if gaiResult != 0'i32: when useWinVersion: From 144dc8f8ad209ebcb6591e0adc1bc4cb73528f3a Mon Sep 17 00:00:00 2001 From: Adam Strzelecki Date: Tue, 29 Sep 2015 22:34:57 +0200 Subject: [PATCH 02/17] Move deprecated modules into lib/deprecated/ This gives clear indication what modules are now deprecated and reduce clutter in non-deprecated module directories. --- compiler/installer.ini | 3 +++ config/nim.cfg | 2 ++ lib/{ => deprecated}/core/unsigned.nim | 0 lib/{ => deprecated}/pure/actors.nim | 0 lib/{ => deprecated}/pure/actors.nim.cfg | 0 lib/{ => deprecated}/pure/asyncio.nim | 0 lib/{ => deprecated}/pure/ftpclient.nim | 0 lib/{ => deprecated}/pure/parseopt.nim | 0 lib/{ => deprecated}/pure/parseurl.nim | 0 lib/{ => deprecated}/pure/sockets.nim | 0 10 files changed, 5 insertions(+) rename lib/{ => deprecated}/core/unsigned.nim (100%) rename lib/{ => deprecated}/pure/actors.nim (100%) rename lib/{ => deprecated}/pure/actors.nim.cfg (100%) rename lib/{ => deprecated}/pure/asyncio.nim (100%) rename lib/{ => deprecated}/pure/ftpclient.nim (100%) rename lib/{ => deprecated}/pure/parseopt.nim (100%) rename lib/{ => deprecated}/pure/parseurl.nim (100%) rename lib/{ => deprecated}/pure/sockets.nim (100%) diff --git a/compiler/installer.ini b/compiler/installer.ini index c8af388865..729c135037 100644 --- a/compiler/installer.ini +++ b/compiler/installer.ini @@ -115,6 +115,9 @@ Files: "lib/posix/*.nim" Files: "lib/js/*.nim" Files: "lib/packages/docutils/*.nim" +Files: "lib/deprecated/core/*.nim" +Files: "lib/deprecated/pure/*.nim" +Files: "lib/deprecated/pure/*.cfg" [Other] Files: "examples/*.nim" diff --git a/config/nim.cfg b/config/nim.cfg index bf78c35cc7..b8608b3ce0 100644 --- a/config/nim.cfg +++ b/config/nim.cfg @@ -27,6 +27,8 @@ mips.linux.gcc.linkerexe = "mips-openwrt-linux-gcc" cs:partial @end +path="$lib/deprecated/core" +path="$lib/deprecated/pure" path="$lib/pure/collections" path="$lib/pure/concurrency" path="$lib/impure" diff --git a/lib/core/unsigned.nim b/lib/deprecated/core/unsigned.nim similarity index 100% rename from lib/core/unsigned.nim rename to lib/deprecated/core/unsigned.nim diff --git a/lib/pure/actors.nim b/lib/deprecated/pure/actors.nim similarity index 100% rename from lib/pure/actors.nim rename to lib/deprecated/pure/actors.nim diff --git a/lib/pure/actors.nim.cfg b/lib/deprecated/pure/actors.nim.cfg similarity index 100% rename from lib/pure/actors.nim.cfg rename to lib/deprecated/pure/actors.nim.cfg diff --git a/lib/pure/asyncio.nim b/lib/deprecated/pure/asyncio.nim similarity index 100% rename from lib/pure/asyncio.nim rename to lib/deprecated/pure/asyncio.nim diff --git a/lib/pure/ftpclient.nim b/lib/deprecated/pure/ftpclient.nim similarity index 100% rename from lib/pure/ftpclient.nim rename to lib/deprecated/pure/ftpclient.nim diff --git a/lib/pure/parseopt.nim b/lib/deprecated/pure/parseopt.nim similarity index 100% rename from lib/pure/parseopt.nim rename to lib/deprecated/pure/parseopt.nim diff --git a/lib/pure/parseurl.nim b/lib/deprecated/pure/parseurl.nim similarity index 100% rename from lib/pure/parseurl.nim rename to lib/deprecated/pure/parseurl.nim diff --git a/lib/pure/sockets.nim b/lib/deprecated/pure/sockets.nim similarity index 100% rename from lib/pure/sockets.nim rename to lib/deprecated/pure/sockets.nim From 4d2486c85854315e5d3de5627c0749f753d6e6fa Mon Sep 17 00:00:00 2001 From: Adam Strzelecki Date: Tue, 29 Sep 2015 22:49:21 +0200 Subject: [PATCH 03/17] doc: Move deprecated modules into separate section --- doc/lib.txt | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/doc/lib.txt b/doc/lib.txt index 868adde89b..5b2648b2fa 100644 --- a/doc/lib.txt +++ b/doc/lib.txt @@ -201,12 +201,6 @@ Internet Protocols and Support * `scgi `_ This module implements helpers for SCGI applications. -* `sockets `_ - This module implements a simple portable type-safe sockets layer. - -* `asyncio `_ - This module implements an asynchronous event loop for sockets. - * `browsers `_ This module implements procs for opening URLs with the user's default browser. @@ -220,9 +214,6 @@ Internet Protocols and Support * `smtp `_ This module implement a simple SMTP client. -* `ftpclient `_ - This module implements an FTP client. - * `cookies `_ This module contains helper procs for parsing and generating cookies. @@ -397,6 +388,27 @@ Modules for JS backend Declaration of the Document Object Model for the JS backend. +Deprecated modules +------------------ + +* `asyncio `_ + This module implements an asynchronous event loop for sockets. + **Deprecated since version 0.11.2:** + Use the `asyncnet `_ together with the + `asyncdispatch `_ module instead. + +* `ftpclient `_ + This module implements an FTP client. + **Deprecated since version 0.11.3:** + Use the `asyncftpclient `_ module instead. + +* `sockets `_ + This module implements a simple portable type-safe sockets layer. + **Deprecated since version 0.11.2:** + Use the `net `_ or the `rawsockets `_ module + instead. + + Impure libraries ================ From e9f5c256d78ca38885eac1d245992dd75df09380 Mon Sep 17 00:00:00 2001 From: Adam Strzelecki Date: Wed, 30 Sep 2015 12:28:41 +0200 Subject: [PATCH 04/17] parseopt: This module is no longer deprecated Remove depreciation notice from doc/lib.txt. --- doc/lib.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/lib.txt b/doc/lib.txt index 5b2648b2fa..7c71e8ae57 100644 --- a/doc/lib.txt +++ b/doc/lib.txt @@ -256,8 +256,6 @@ Parsers * `parseopt `_ The ``parseopt`` module implements a command line option parser. - **Deprecated since version 0.9.3:** Use the `parseopt2 - `_ module instead. * `parseopt2 `_ The ``parseopt2`` module implements a command line option parser. This From be991ed413d57ec90b4494f4be945d11c85365f4 Mon Sep 17 00:00:00 2001 From: Adam Strzelecki Date: Wed, 30 Sep 2015 13:36:43 +0200 Subject: [PATCH 05/17] Rename rawsockets module to nativesockets This change was done to avoid confusion with TCP/IP raw sockets. Native sockets module represents handling native system low level socket API in general and is not just limited anyhow to TCP/IP raw sockets. A stub lib/deprecated/pure/rawsockets.nim module has been added as compatibility layer for old code using rawsockets, so this change will not break existing code. --- doc/lib.txt | 6 ++- lib/deprecated/pure/ftpclient.nim | 4 +- lib/deprecated/pure/rawsockets.nim | 14 ++++++ lib/deprecated/pure/sockets.nim | 2 +- lib/pure/asyncdispatch.nim | 34 +++++++------- lib/pure/asyncnet.nim | 11 +++-- lib/pure/httpclient.nim | 8 ++-- .../{rawsockets.nim => nativesockets.nim} | 46 ++++++++++--------- lib/pure/net.nim | 8 ++-- tests/async/tasyncawait.nim | 6 +-- tests/async/tasyncconnect.nim | 2 +- tests/async/tasynceverror.nim | 4 +- .../{trawsockets.nim => tnativesockets.nim} | 2 +- tests/macros/tgensym.nim | 4 +- tests/modules/texport.nim | 2 +- web/news.txt | 3 ++ 16 files changed, 91 insertions(+), 65 deletions(-) create mode 100644 lib/deprecated/pure/rawsockets.nim rename lib/pure/{rawsockets.nim => nativesockets.nim} (94%) rename tests/cpp/{trawsockets.nim => tnativesockets.nim} (65%) diff --git a/doc/lib.txt b/doc/lib.txt index 7c71e8ae57..3dc58eebfa 100644 --- a/doc/lib.txt +++ b/doc/lib.txt @@ -244,7 +244,7 @@ Internet Protocols and Support This module implements a high-level sockets API. It will replace the ``sockets`` module in the future. -* `rawsockets `_ +* `nativesockets `_ This module implements a low-level sockets API. * `selectors `_ @@ -406,6 +406,10 @@ Deprecated modules Use the `net `_ or the `rawsockets `_ module instead. +* `rawsockets `_ + **Deprecated since version 0.11.4:** + This module has been renamed to `nativesockets `_. + Impure libraries ================ diff --git a/lib/deprecated/pure/ftpclient.nim b/lib/deprecated/pure/ftpclient.nim index 229fe4b511..1188c0795f 100644 --- a/lib/deprecated/pure/ftpclient.nim +++ b/lib/deprecated/pure/ftpclient.nim @@ -11,7 +11,7 @@ include "system/inclrtl" import sockets, strutils, parseutils, times, os, asyncio from asyncnet import nil -from rawsockets import nil +from nativesockets import nil from asyncdispatch import PFuture ## **Note**: This module is deprecated since version 0.11.3. ## You should use the async version of this module @@ -55,7 +55,7 @@ type user*, pass*: string address*: string when SockType is asyncnet.AsyncSocket: - port*: rawsockets.Port + port*: nativesockets.Port else: port*: Port diff --git a/lib/deprecated/pure/rawsockets.nim b/lib/deprecated/pure/rawsockets.nim new file mode 100644 index 0000000000..ee77b232e5 --- /dev/null +++ b/lib/deprecated/pure/rawsockets.nim @@ -0,0 +1,14 @@ +import nativesockets +export nativesockets + +{.warning: "rawsockets module is deprecated, use nativesockets instead".} + +template newRawSocket*(domain, sockType, protocol: cint): expr = + {.warning: "newRawSocket is deprecated, use newNativeSocket instead".} + newNativeSocket(domain, sockType, protocol) + +template newRawSocket*(domain: Domain = AF_INET, + sockType: SockType = SOCK_STREAM, + protocol: Protocol = IPPROTO_TCP): expr = + {.warning: "newRawSocket is deprecated, use newNativeSocket instead".} + newNativeSocket(domain, sockType, protocol) diff --git a/lib/deprecated/pure/sockets.nim b/lib/deprecated/pure/sockets.nim index 8fa69256be..5d6fa00787 100644 --- a/lib/deprecated/pure/sockets.nim +++ b/lib/deprecated/pure/sockets.nim @@ -9,7 +9,7 @@ ## **Warning:** Since version 0.10.2 this module is deprecated. ## Use the `net `_ or the -## `rawsockets `_ module instead. +## `nativesockets `_ module instead. ## ## This module implements portable sockets, it supports a mix of different types ## of sockets. Sockets are buffered by default meaning that data will be diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index 110bc6d741..7bba6bd898 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -11,7 +11,7 @@ include "system/inclrtl" import os, oids, tables, strutils, macros, times -import rawsockets, net +import nativesockets, net export Port, SocketFlag @@ -475,7 +475,7 @@ when defined(windows) or defined(nimdoc): addr bytesRet, nil, nil) == 0 proc initAll() = - let dummySock = newRawSocket() + let dummySock = newNativeSocket() if not initPointer(dummySock, connectExPtr, WSAID_CONNECTEX): raiseOSError(osLastError()) if not initPointer(dummySock, acceptExPtr, WSAID_ACCEPTEX): @@ -528,7 +528,7 @@ when defined(windows) or defined(nimdoc): RemoteSockaddr, RemoteSockaddrLength) proc connect*(socket: AsyncFD, address: string, port: Port, - domain = rawsockets.AF_INET): Future[void] = + domain = nativesockets.AF_INET): Future[void] = ## Connects ``socket`` to server at ``address:port``. ## ## Returns a ``Future`` which will complete when the connection succeeds @@ -827,7 +827,7 @@ when defined(windows) or defined(nimdoc): verifyPresence(socket) var retFuture = newFuture[tuple[address: string, client: AsyncFD]]("acceptAddr") - var clientSock = newRawSocket() + var clientSock = newNativeSocket() if clientSock == osInvalidSocket: raiseOSError(osLastError()) const lpOutputLen = 1024 @@ -900,17 +900,17 @@ when defined(windows) or defined(nimdoc): return retFuture - proc newAsyncRawSocket*(domain, sockType, protocol: cint): AsyncFD = + proc newAsyncNativeSocket*(domain, sockType, protocol: cint): AsyncFD = ## Creates a new socket and registers it with the dispatcher implicitly. - result = newRawSocket(domain, sockType, protocol).AsyncFD + result = newNativeSocket(domain, sockType, protocol).AsyncFD result.SocketHandle.setBlocking(false) register(result) - proc newAsyncRawSocket*(domain: Domain = rawsockets.AF_INET, - sockType: SockType = SOCK_STREAM, - protocol: Protocol = IPPROTO_TCP): AsyncFD = + proc newAsyncNativeSocket*(domain: Domain = nativesockets.AF_INET, + sockType: SockType = SOCK_STREAM, + protocol: Protocol = IPPROTO_TCP): AsyncFD = ## Creates a new socket and registers it with the dispatcher implicitly. - result = newRawSocket(domain, sockType, protocol).AsyncFD + result = newNativeSocket(domain, sockType, protocol).AsyncFD result.SocketHandle.setBlocking(false) register(result) @@ -973,18 +973,18 @@ else: var data = PData(fd: fd, readCBs: @[], writeCBs: @[]) p.selector.register(fd.SocketHandle, {}, data.RootRef) - proc newAsyncRawSocket*(domain: cint, sockType: cint, - protocol: cint): AsyncFD = - result = newRawSocket(domain, sockType, protocol).AsyncFD + proc newAsyncNativeSocket*(domain: cint, sockType: cint, + protocol: cint): AsyncFD = + result = newNativeSocket(domain, sockType, protocol).AsyncFD result.SocketHandle.setBlocking(false) when defined(macosx): result.SocketHandle.setSockOptInt(SOL_SOCKET, SO_NOSIGPIPE, 1) register(result) - proc newAsyncRawSocket*(domain: Domain = AF_INET, - sockType: SockType = SOCK_STREAM, - protocol: Protocol = IPPROTO_TCP): AsyncFD = - result = newRawSocket(domain, sockType, protocol).AsyncFD + proc newAsyncNativeSocket*(domain: Domain = AF_INET, + sockType: SockType = SOCK_STREAM, + protocol: Protocol = IPPROTO_TCP): AsyncFD = + result = newNativeSocket(domain, sockType, protocol).AsyncFD result.SocketHandle.setBlocking(false) when defined(macosx): result.SocketHandle.setSockOptInt(SOL_SOCKET, SO_NOSIGPIPE, 1) diff --git a/lib/pure/asyncnet.nim b/lib/pure/asyncnet.nim index d7a8c30945..6b19a48be0 100644 --- a/lib/pure/asyncnet.nim +++ b/lib/pure/asyncnet.nim @@ -56,7 +56,7 @@ ## import asyncdispatch -import rawsockets +import nativesockets import net import os @@ -112,8 +112,8 @@ proc newAsyncSocket*(domain: Domain = AF_INET, sockType: SockType = SOCK_STREAM, ## ## This procedure will also create a brand new file descriptor for ## this socket. - result = newAsyncSocket(newAsyncRawSocket(domain, sockType, protocol), domain, - sockType, protocol, buffered) + result = newAsyncSocket(newAsyncNativeSocket(domain, sockType, protocol), + domain, sockType, protocol, buffered) proc newAsyncSocket*(domain, sockType, protocol: cint, buffered = true): AsyncSocket = @@ -121,8 +121,9 @@ proc newAsyncSocket*(domain, sockType, protocol: cint, ## ## This procedure will also create a brand new file descriptor for ## this socket. - result = newAsyncSocket(newAsyncRawSocket(domain, sockType, protocol), - Domain(domain), SockType(sockType), Protocol(protocol), buffered) + result = newAsyncSocket(newAsyncNativeSocket(domain, sockType, protocol), + Domain(domain), SockType(sockType), + Protocol(protocol), buffered) when defined(ssl): proc getSslError(handle: SslPtr, err: cint): cint = diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim index 30b838b7e3..a5d4ec1a10 100644 --- a/lib/pure/httpclient.nim +++ b/lib/pure/httpclient.nim @@ -81,7 +81,7 @@ import net, strutils, uri, parseutils, strtabs, base64, os, mimetypes, math import asyncnet, asyncdispatch -import rawsockets +import nativesockets type Response* = tuple[ @@ -764,10 +764,10 @@ proc newConnection(client: AsyncHttpClient, url: Uri) {.async.} = let port = if url.port == "": if url.scheme.toLower() == "https": - rawsockets.Port(443) + nativesockets.Port(443) else: - rawsockets.Port(80) - else: rawsockets.Port(url.port.parseInt) + nativesockets.Port(80) + else: nativesockets.Port(url.port.parseInt) if url.scheme.toLower() == "https": when defined(ssl): diff --git a/lib/pure/rawsockets.nim b/lib/pure/nativesockets.nim similarity index 94% rename from lib/pure/rawsockets.nim rename to lib/pure/nativesockets.nim index 2d7b0e5ea1..b5661c4d34 100644 --- a/lib/pure/rawsockets.nim +++ b/lib/pure/nativesockets.nim @@ -93,8 +93,8 @@ when useWinVersion: IOC_IN* = int(-2147483648) FIONBIO* = IOC_IN.int32 or ((sizeof(int32) and IOCPARM_MASK) shl 16) or (102 shl 8) or 126 - rawAfInet = winlean.AF_INET - rawAfInet6 = winlean.AF_INET6 + nativeAfInet = winlean.AF_INET + nativeAfInet6 = winlean.AF_INET6 proc ioctlsocket*(s: SocketHandle, cmd: clong, argptr: ptr clong): cint {. @@ -102,8 +102,8 @@ when useWinVersion: else: let osInvalidSocket* = posix.INVALID_SOCKET - rawAfInet = posix.AF_INET - rawAfInet6 = posix.AF_INET6 + nativeAfInet = posix.AF_INET + nativeAfInet6 = posix.AF_INET6 proc `==`*(a, b: Port): bool {.borrow.} ## ``==`` for ports. @@ -157,12 +157,14 @@ else: result = cint(ord(p)) -proc newRawSocket*(domain: Domain = AF_INET, sockType: SockType = SOCK_STREAM, - protocol: Protocol = IPPROTO_TCP): SocketHandle = +proc newNativeSocket*(domain: Domain = AF_INET, + sockType: SockType = SOCK_STREAM, + protocol: Protocol = IPPROTO_TCP): SocketHandle = ## Creates a new socket; returns `InvalidSocket` if an error occurs. socket(toInt(domain), toInt(sockType), toInt(protocol)) -proc newRawSocket*(domain: cint, sockType: cint, protocol: cint): SocketHandle = +proc newNativeSocket*(domain: cint, sockType: cint, + protocol: cint): SocketHandle = ## Creates a new socket; returns `InvalidSocket` if an error occurs. ## ## Use this overload if one of the enums specified above does @@ -231,17 +233,17 @@ proc ntohs*(x: int16): int16 = when cpuEndian == bigEndian: result = x else: result = (x shr 8'i16) or (x shl 8'i16) -proc htonl*(x: int32): int32 = +template htonl*(x: int32): expr = ## Converts 32-bit integers from host to network byte order. On machines ## where the host byte order is the same as network byte order, this is ## a no-op; otherwise, it performs a 4-byte swap operation. - result = rawsockets.ntohl(x) + nativesockets.ntohl(x) -proc htons*(x: int16): int16 = +template htons*(x: int16): expr = ## Converts 16-bit positive integers from host to network byte order. ## On machines where the host byte order is the same as network byte ## order, this is a no-op; otherwise, it performs a 2-byte swap operation. - result = rawsockets.ntohs(x) + nativesockets.ntohs(x) proc getServByName*(name, proto: string): Servent {.tags: [ReadIOEffect].} = ## Searches the database from the beginning and finds the first entry for @@ -282,7 +284,7 @@ proc getHostByAddr*(ip: string): Hostent {.tags: [ReadIOEffect].} = when useWinVersion: var s = winlean.gethostbyaddr(addr(myaddr), sizeof(myaddr).cuint, - cint(rawsockets.AF_INET)) + cint(AF_INET)) if s == nil: raiseOSError(osLastError()) else: var s = posix.gethostbyaddr(addr(myaddr), sizeof(myaddr).Socklen, @@ -332,9 +334,9 @@ proc getSockDomain*(socket: SocketHandle): Domain = if getsockname(socket, cast[ptr SockAddr](addr(name)), addr(namelen)) == -1'i32: raiseOSError(osLastError()) - if name.sa_family == rawAfInet: + if name.sa_family == nativeAfInet: result = AF_INET - elif name.sa_family == rawAfInet6: + elif name.sa_family == nativeAfInet6: result = AF_INET6 else: raiseOSError(osLastError(), "unknown socket family in getSockFamily") @@ -342,9 +344,9 @@ proc getSockDomain*(socket: SocketHandle): Domain = proc getAddrString*(sockAddr: ptr SockAddr): string = ## return the string representation of address within sockAddr - if sockAddr.sa_family == rawAfInet: + if sockAddr.sa_family == nativeAfInet: result = $inet_ntoa(cast[ptr Sockaddr_in](sockAddr).sin_addr) - elif sockAddr.sa_family == rawAfInet6: + elif sockAddr.sa_family == nativeAfInet6: when not useWinVersion: # TODO: Windows var v6addr = cast[ptr Sockaddr_in6](sockAddr).sin6_addr @@ -371,7 +373,7 @@ proc getSockName*(socket: SocketHandle): Port = if getsockname(socket, cast[ptr SockAddr](addr(name)), addr(namelen)) == -1'i32: raiseOSError(osLastError()) - result = Port(rawsockets.ntohs(name.sin_port)) + result = Port(nativesockets.ntohs(name.sin_port)) proc getLocalAddr*(socket: SocketHandle, domain: Domain): (string, Port) = ## returns the socket's local address and port number. @@ -388,7 +390,8 @@ proc getLocalAddr*(socket: SocketHandle, domain: Domain): (string, Port) = if getsockname(socket, cast[ptr SockAddr](addr(name)), addr(namelen)) == -1'i32: raiseOSError(osLastError()) - result = ($inet_ntoa(name.sin_addr), Port(rawsockets.ntohs(name.sin_port))) + result = ($inet_ntoa(name.sin_addr), + Port(nativesockets.ntohs(name.sin_port))) of AF_INET6: var name: Sockaddr_in6 when useWinVersion: @@ -404,7 +407,7 @@ proc getLocalAddr*(socket: SocketHandle, domain: Domain): (string, Port) = if inet_ntop(name.sin6_family.cint, addr name, buf.cstring, sizeof(buf).int32).isNil: raiseOSError(osLastError()) - result = ($buf, Port(rawsockets.ntohs(name.sin6_port))) + result = ($buf, Port(nativesockets.ntohs(name.sin6_port))) else: raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr") @@ -423,7 +426,8 @@ proc getPeerAddr*(socket: SocketHandle, domain: Domain): (string, Port) = if getpeername(socket, cast[ptr SockAddr](addr(name)), addr(namelen)) == -1'i32: raiseOSError(osLastError()) - result = ($inet_ntoa(name.sin_addr), Port(rawsockets.ntohs(name.sin_port))) + result = ($inet_ntoa(name.sin_addr), + Port(nativesockets.ntohs(name.sin_port))) of AF_INET6: var name: Sockaddr_in6 when useWinVersion: @@ -439,7 +443,7 @@ proc getPeerAddr*(socket: SocketHandle, domain: Domain): (string, Port) = if inet_ntop(name.sin6_family.cint, addr name, buf.cstring, sizeof(buf).int32).isNil: raiseOSError(osLastError()) - result = ($buf, Port(rawsockets.ntohs(name.sin6_port))) + result = ($buf, Port(nativesockets.ntohs(name.sin6_port))) else: raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr") diff --git a/lib/pure/net.nim b/lib/pure/net.nim index 00a6c0c921..d1016011e4 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -10,7 +10,7 @@ ## This module implements a high-level cross-platform sockets interface. {.deadCodeElim: on.} -import rawsockets, os, strutils, unsigned, parseutils, times +import nativesockets, os, strutils, unsigned, parseutils, times export Port, `$`, `==` const useWinVersion = defined(Windows) or defined(nimdoc) @@ -145,7 +145,7 @@ proc newSocket*(domain, sockType, protocol: cint, buffered = true): Socket = ## Creates a new socket. ## ## If an error occurs EOS will be raised. - let fd = newRawSocket(domain, sockType, protocol) + let fd = newNativeSocket(domain, sockType, protocol) if fd == osInvalidSocket: raiseOSError(osLastError()) result = newSocket(fd, domain.Domain, sockType.SockType, protocol.Protocol, @@ -156,7 +156,7 @@ proc newSocket*(domain: Domain = AF_INET, sockType: SockType = SOCK_STREAM, ## Creates a new socket. ## ## If an error occurs EOS will be raised. - let fd = newRawSocket(domain, sockType, protocol) + let fd = newNativeSocket(domain, sockType, protocol) if fd == osInvalidSocket: raiseOSError(osLastError()) result = newSocket(fd, domain, sockType, protocol, buffered) @@ -354,7 +354,7 @@ proc listen*(socket: Socket, backlog = SOMAXCONN) {.tags: [ReadIOEffect].} = ## queue of pending connections. ## ## Raises an EOS error upon failure. - if rawsockets.listen(socket.fd, backlog) < 0'i32: + if nativesockets.listen(socket.fd, backlog) < 0'i32: raiseOSError(osLastError()) proc bindAddr*(socket: Socket, port = Port(0), address = "") {. diff --git a/tests/async/tasyncawait.nim b/tests/async/tasyncawait.nim index e5895abe17..443f769cd0 100644 --- a/tests/async/tasyncawait.nim +++ b/tests/async/tasyncawait.nim @@ -2,7 +2,7 @@ discard """ file: "tasyncawait.nim" output: "5000" """ -import asyncdispatch, rawsockets, net, strutils, os +import asyncdispatch, nativesockets, net, strutils, os var msgCount = 0 @@ -18,7 +18,7 @@ proc sendMessages(client: TAsyncFD) {.async.} = proc launchSwarm(port: TPort) {.async.} = for i in 0 .. Date: Thu, 1 Oct 2015 00:17:13 +0200 Subject: [PATCH 06/17] koch: Add geninstall generating just ./install.sh In opposite to `install` which generates ./install.sh and then calls it. --- koch.nim | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/koch.nim b/koch.nim index 8992271bfd..3d1a22b9cc 100644 --- a/koch.nim +++ b/koch.nim @@ -41,6 +41,7 @@ Options: Possible Commands: boot [options] bootstraps with given command line options install [bindir] installs to given directory; Unix only! + geninstall generate ./install.sh; Unix only! clean cleans Nim project; removes generated files web [options] generates the website and the full documentation website [options] generates only the website @@ -127,9 +128,12 @@ proc nsis(args: string) = exec(("tools" / "niminst" / "niminst --var:version=$# --var:mingw=mingw$#" & " nsis compiler/installer.ini") % [VersionAsString, $(sizeof(pointer)*8)]) +proc geninstall(args="") = + exec("$# cc -r $# --var:version=$# --var:mingw=none --main:compiler/nim.nim scripts compiler/installer.ini $#" % + [findNim(), compileNimInst, VersionAsString, args]) + proc install(args: string) = - exec("$# cc -r $# --var:version=$# --var:mingw=none --main:compiler/nim.nim scripts compiler/installer.ini" % - [findNim(), compileNimInst, VersionAsString]) + geninstall() exec("sh ./install.sh $#" % args) proc web(args: string) = @@ -373,6 +377,7 @@ of cmdArgument: of "zip": zip(op.cmdLineRest) of "xz": xz(op.cmdLineRest) of "nsis": nsis(op.cmdLineRest) + of "geninstall": geninstall(op.cmdLineRest) of "install": install(op.cmdLineRest) of "test", "tests": tests(op.cmdLineRest) of "update": From 6cc98539354607306e213ac90b2dac7cb3e86f73 Mon Sep 17 00:00:00 2001 From: Adam Strzelecki Date: Thu, 1 Oct 2015 00:18:32 +0200 Subject: [PATCH 07/17] bootstrap: Generate final install.sh during build This solves problem where bootstrap was simply copying ./install.sh.template into ./install.sh. Then first call of ./install.sh was calling ./koch install that was running extra compilation and overwriting ./install.sh with new content. This was overcomplicated, and also caused first `sudo ./install.sh DIR` to run compilation under root account, leaving root owned files in working directory. Now bootstrap calls `./koch geninstall` that just generates ./install.sh without calling it. This ./install.sh is FINAL one, and running it does not generate any files aside passed DIR. This makes whole process simpler. --- bootstrap.sh | 7 +++++-- install.sh.template | 9 --------- 2 files changed, 5 insertions(+), 11 deletions(-) delete mode 100644 install.sh.template diff --git a/bootstrap.sh b/bootstrap.sh index ade74a9aa4..7f19c24406 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -12,8 +12,11 @@ cd ".." ./bin/nim c koch ./koch boot -d:release +./koch geninstall -cp -f install.sh.template install.sh -chmod +x install.sh +set +x + +echo +echo 'Install Nim using "./install.sh " or "sudo ./install.sh ".' exit 0 diff --git a/install.sh.template b/install.sh.template deleted file mode 100644 index 1292abdab5..0000000000 --- a/install.sh.template +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh -set -e -set -x - -if [ "$1" != "" ]; then - exec ./koch install "$1" -else - exec ./koch install -fi From 28b1340f9494e70e81ae186de872df0be727f857 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 1 Oct 2015 09:14:45 +0200 Subject: [PATCH 08/17] fixes 'line too long' warning --- lib/system/nimscript.nim | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/system/nimscript.nim b/lib/system/nimscript.nim index a93c65dd4f..22430348cd 100644 --- a/lib/system/nimscript.nim +++ b/lib/system/nimscript.nim @@ -31,7 +31,8 @@ proc moveFile(src, dest: string) {. tags: [ReadIOEffect, WriteIOEffect], raises: [OSError].} = builtin proc copyFile(src, dest: string) {. tags: [ReadIOEffect, WriteIOEffect], raises: [OSError].} = builtin -proc createDir(dir: string) {.tags: [WriteIOEffect], raises: [OSError].} = builtin +proc createDir(dir: string) {.tags: [WriteIOEffect], raises: [OSError].} = + builtin proc getOsError: string = builtin proc setCurrentDir(dir: string) = builtin proc getCurrentDir(): string = builtin From a2c040e3bd2a34bff889c22e4fb098b95b45fe53 Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 3 Oct 2015 23:19:02 +0200 Subject: [PATCH 09/17] added undocumented exportNims pragma for Nimscript support --- compiler/magicsys.nim | 38 ++++++++++++++++++++++---------------- compiler/modules.nim | 7 +++++++ compiler/pragmas.nim | 18 +++++++++++------- compiler/vm.nim | 25 +++++++++++++++++++++++++ compiler/wordrecg.nim | 5 +++-- 5 files changed, 68 insertions(+), 25 deletions(-) diff --git a/compiler/magicsys.nim b/compiler/magicsys.nim index 98a4b08bf3..40e0728ae4 100644 --- a/compiler/magicsys.nim +++ b/compiler/magicsys.nim @@ -14,22 +14,14 @@ import var systemModule*: PSym -proc registerSysType*(t: PType) - # magic symbols in the system module: -proc getSysType*(kind: TTypeKind): PType -proc getCompilerProc*(name: string): PSym -proc registerCompilerProc*(s: PSym) -proc finishSystem*(tab: TStrTable) -proc getSysSym*(name: string): PSym -# implementation - var gSysTypes: array[TTypeKind, PType] compilerprocs: TStrTable + exposed: TStrTable proc nilOrSysInt*: PType = gSysTypes[tyInt] -proc registerSysType(t: PType) = +proc registerSysType*(t: PType) = if gSysTypes[t.kind] == nil: gSysTypes[t.kind] = t proc newSysType(kind: TTypeKind, size: int): PType = @@ -37,7 +29,7 @@ proc newSysType(kind: TTypeKind, size: int): PType = result.size = size result.align = size.int16 -proc getSysSym(name: string): PSym = +proc getSysSym*(name: string): PSym = result = strTableGet(systemModule.tab, getIdent(name)) if result == nil: rawMessage(errSystemNeeds, name) @@ -61,7 +53,7 @@ proc getSysMagic*(name: string, m: TMagic): PSym = proc sysTypeFromName*(name: string): PType = result = getSysSym(name).typ -proc getSysType(kind: TTypeKind): PType = +proc getSysType*(kind: TTypeKind): PType = result = gSysTypes[kind] if result == nil: case kind @@ -97,6 +89,7 @@ var proc resetSysTypes* = systemModule = nil initStrTable(compilerprocs) + initStrTable(exposed) for i in low(gSysTypes)..high(gSysTypes): gSysTypes[i] = nil @@ -163,8 +156,8 @@ proc setIntLitType*(result: PNode) = result.typ = getSysType(tyInt64) else: internalError(result.info, "invalid int size") -proc getCompilerProc(name: string): PSym = - var ident = getIdent(name, hashIgnoreStyle(name)) +proc getCompilerProc*(name: string): PSym = + let ident = getIdent(name) result = strTableGet(compilerprocs, ident) if result == nil: result = strTableGet(rodCompilerprocs, ident) @@ -173,9 +166,22 @@ proc getCompilerProc(name: string): PSym = if result.kind == skStub: loadStub(result) if result.kind == skAlias: result = result.owner -proc registerCompilerProc(s: PSym) = +proc registerCompilerProc*(s: PSym) = strTableAdd(compilerprocs, s) -proc finishSystem(tab: TStrTable) = discard +proc registerNimScriptSymbol*(s: PSym) = + # Nimscript symbols must be al unique: + let conflict = strTableGet(exposed, s.name) + if conflict == nil: + strTableAdd(exposed, s) + else: + localError(s.info, "symbol conflicts with other .exportNims symbol at: " & + $conflict.info) + +proc getNimScriptSymbol*(name: string): PSym = + strTableGet(exposed, getIdent(name)) + +proc resetNimScriptSymbols*() = initStrTable(exposed) initStrTable(compilerprocs) +initStrTable(exposed) diff --git a/compiler/modules.nim b/compiler/modules.nim index 85c99c4ecd..3893d377e9 100644 --- a/compiler/modules.nim +++ b/compiler/modules.nim @@ -78,6 +78,13 @@ proc resetModule*(fileIdx: int32) = if fileIdx <% cgendata.gModules.len: cgendata.gModules[fileIdx] = nil +proc resetModule*(module: PSym) = + let conflict = getModule(module.position.int32) + if conflict == nil: return + doAssert conflict == module + resetModule(module.position.int32) + initStrTable(module.tab) + proc resetAllModules* = for i in 0..gCompiledModules.high: if gCompiledModules[i] != nil: diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index ba05b2792a..79d7884fa7 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -25,18 +25,19 @@ const wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl, wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe, - wOverride, wConstructor} + wOverride, wConstructor, wExportNims} converterPragmas* = procPragmas methodPragmas* = procPragmas+{wBase} templatePragmas* = {wImmediate, wDeprecated, wError, wGensym, wInject, wDirty, - wDelegator} + wDelegator, wExportNims} macroPragmas* = {FirstCallConv..LastCallConv, wImmediate, wImportc, wExportc, wNodecl, wMagic, wNosideeffect, wCompilerproc, wDeprecated, wExtern, - wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wDelegator} + wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wDelegator, + wExportNims} iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideeffect, wSideeffect, wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern, wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises, - wTags, wLocks, wGcSafe} + wTags, wLocks, wGcSafe, wExportNims} exprPragmas* = {wLine, wLocks, wNoRewrite} stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, @@ -54,15 +55,15 @@ const wPure, wHeader, wCompilerproc, wFinal, wSize, wExtern, wShallow, wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef, wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked, - wBorrow, wGcSafe} + wBorrow, wGcSafe, wExportNims} fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern, wImportCpp, wImportObjC, wError, wGuard, wBitsize} varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl, wMagic, wHeader, wDeprecated, wCompilerproc, wDynlib, wExtern, wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal, - wGensym, wInject, wCodegenDecl, wGuard, wGoto} + wGensym, wInject, wCodegenDecl, wGuard, wGoto, wExportNims} constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl, - wExtern, wImportCpp, wImportObjC, wError, wGensym, wInject} + wExtern, wImportCpp, wImportObjC, wError, wGensym, wInject, wExportNims} letPragmas* = varPragmas procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideeffect, wThread, wRaises, wLocks, wTags, wGcSafe} @@ -859,6 +860,9 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, invalidPragma(it) else: sym.flags.incl sfGoto + of wExportNims: + if sym == nil: invalidPragma(it) + else: magicsys.registerNimScriptSymbol(sym) of wInjectStmt: if it.kind != nkExprColonExpr: localError(it.info, errExprExpected) diff --git a/compiler/vm.nim b/compiler/vm.nim index ad4aa1017f..ded66d3d0d 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -1411,6 +1411,31 @@ proc execute(c: PCtx, start: int): PNode = newSeq(tos.slots, c.prc.maxSlots) result = rawExecute(c, start, tos).regToNode +proc execProc*(c: PCtx; sym: PSym; args: openArray[PNode]): PNode = + if sym.kind in routineKinds: + if sym.typ.len-1 != args.len: + localError(sym.info, + "NimScript: expected $# arguments, but got $#" % [ + $(sym.typ.len-1), $args.len]) + else: + let start = genProc(c, sym) + + var tos = PStackFrame(prc: sym, comesFrom: 0, next: nil) + let maxSlots = sym.offset + newSeq(tos.slots, maxSlots) + + # setup parameters: + if not isEmptyType(sym.typ.sons[0]) or sym.kind == skMacro: + putIntoReg(tos.slots[0], getNullValue(sym.typ.sons[0], sym.info)) + # XXX We could perform some type checking here. + for i in 1.. Date: Sun, 4 Oct 2015 15:36:57 +1000 Subject: [PATCH 10/17] Add toRational(float) conversion from any float to closest approx for specified precision --- lib/pure/rationals.nim | 62 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/lib/pure/rationals.nim b/lib/pure/rationals.nim index 7d9241412a..72c64befce 100644 --- a/lib/pure/rationals.nim +++ b/lib/pure/rationals.nim @@ -39,6 +39,63 @@ proc toRational*[T:SomeInteger](x: T): Rational[T] = result.num = x result.den = 1 +proc toRationalSub(x: float, n: int): Rational[int] = + var + a = 0 + b, c, d = 1 + result = 0 // 1 # rational 0 + while b <= n and d <= n: + let ac = (a+c) + let bd = (b+d) + # scale by 1000 so not overflow for high precision + let mediant = (ac/1000) / (bd/1000) + if x == mediant: + if bd <= n: + result.num = ac + result.den = bd + return result + elif d > b: + result.num = c + result.den = d + return result + else: + result.num = a + result.den = b + return result + elif x > mediant: + a = ac + b = bd + else: + c = ac + d = bd + if (b > n): + return initRational(c, d) + return initRational(a, b) + +proc toRational*(x: float, n: int = high(int)): Rational[int] = + ## Calculate the best rational numerator and denominator + ## that approximates to `x`, where the denominator is + ## smaller than `n` (default is the largest possible + ## int to give maximum resolution) + ## + ## The algorithm is based on the Farey sequence named + ## after John Farey + ## + ## .. code-block:: Nim + ## import math, rationals + ## for i in 1..10: + ## let t = (10 ^ (i+3)).int + ## let x = toRational(PI, t) + ## let newPI = x.num / x.den + ## echo x, " ", newPI, " error: ", PI - newPI, " ", t + if x > 1: + result = toRationalSub(1.0/x, n) + swap(result.num, result.den) + elif x == 1.0: + result = 1 // 1 + else: + result = toRationalSub(x, n) + proc toFloat*[T](x: Rational[T]): float = ## Convert a rational number `x` to a float. x.num / x.den @@ -288,3 +345,8 @@ when isMainModule: assert toRational(5) == 5//1 assert abs(toFloat(y) - 0.4814814814814815) < 1.0e-7 assert toInt(z) == 0 + + assert toRational(0.98765432) == 12345679 // 12500000 + assert toRational(0.1, 1000000) == 1 // 10 + assert toRational(0.9, 1000000) == 9 // 10 + assert toRational(PI) == 80143857 // 25510582 From aead71cd67f17b781ad4f8a496fccc10a801efa2 Mon Sep 17 00:00:00 2001 From: JamesP Date: Mon, 5 Oct 2015 10:42:04 +1000 Subject: [PATCH 11/17] fix #3418 add example on openArray to types.txt --- doc/manual/types.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/manual/types.txt b/doc/manual/types.txt index c9ac6f0628..babf3286f2 100644 --- a/doc/manual/types.txt +++ b/doc/manual/types.txt @@ -490,6 +490,11 @@ to an open array parameter. The openarray type cannot be nested: multidimensional openarrays are not supported because this is seldom needed and cannot be done efficiently. +.. code-block:: nim + proc testOpenArray(x: openArray[int]) = echo repr(x) + + testOpenArray([1,2,3]) # array[] + testOpenArray(@[1,2,3]) # seq[] Varargs ------- From 87a6268d3c93fef26ca5f7a74a3ec78b6aae667a Mon Sep 17 00:00:00 2001 From: JamesP Date: Mon, 5 Oct 2015 15:16:43 +1000 Subject: [PATCH 12/17] bug fix #3416 add wrapper around `[]=` to account for changes in StringTableRef disabling inc of counter --- lib/pure/strtabs.nim | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/pure/strtabs.nim b/lib/pure/strtabs.nim index 86f81aa433..0a1cc61676 100644 --- a/lib/pure/strtabs.nim +++ b/lib/pure/strtabs.nim @@ -135,15 +135,18 @@ proc enlarge(t: StringTableRef) = if not isNil(t.data[i].key): rawInsert(t, n, t.data[i].key, t.data[i].val) swap(t.data, n) -proc `[]=`*(t: StringTableRef, key, val: string) {.rtl, extern: "nstPut".} = - ## puts a (key, value)-pair into `t`. +proc addVal(t: StringTableRef, key, val: string) = var index = rawGet(t, key) if index >= 0: t.data[index].val = val else: if mustRehash(len(t.data), t.counter): enlarge(t) rawInsert(t, t.data, key, val) - inc(t.counter) + +proc `[]=`*(t: StringTableRef, key, val: string) {.rtl, extern: "nstPut".} = + ## puts a (key, value)-pair into `t`. + t.addVal(key, val) + inc(t.counter) proc raiseFormatException(s: string) = var e: ref ValueError From 73821ad1c4b2f64a2885c60c3bc43e74cae5ee1d Mon Sep 17 00:00:00 2001 From: JamesP Date: Mon, 5 Oct 2015 15:19:56 +1000 Subject: [PATCH 13/17] add assert test to end of module --- lib/pure/strtabs.nim | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/pure/strtabs.nim b/lib/pure/strtabs.nim index 0a1cc61676..1ce9067a78 100644 --- a/lib/pure/strtabs.nim +++ b/lib/pure/strtabs.nim @@ -135,18 +135,15 @@ proc enlarge(t: StringTableRef) = if not isNil(t.data[i].key): rawInsert(t, n, t.data[i].key, t.data[i].val) swap(t.data, n) -proc addVal(t: StringTableRef, key, val: string) = +proc `[]=`*(t: StringTableRef, key, val: string) {.rtl, extern: "nstPut".} = + ## puts a (key, value)-pair into `t`. var index = rawGet(t, key) if index >= 0: t.data[index].val = val else: if mustRehash(len(t.data), t.counter): enlarge(t) rawInsert(t, t.data, key, val) - -proc `[]=`*(t: StringTableRef, key, val: string) {.rtl, extern: "nstPut".} = - ## puts a (key, value)-pair into `t`. - t.addVal(key, val) - inc(t.counter) + inc(t.counter) proc raiseFormatException(s: string) = var e: ref ValueError @@ -176,6 +173,9 @@ proc clear*(s: StringTableRef, mode: StringTableMode) = s.mode = mode s.counter = 0 s.data.setLen(startSize) + for i in 0.. Date: Sun, 4 Oct 2015 10:17:17 +0200 Subject: [PATCH 14/17] strutils: wrap too long lines --- lib/pure/strutils.nim | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index d1c09f43d5..eacea72e4f 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -169,7 +169,8 @@ proc cmpIgnoreStyle*(a, b: string): int {.noSideEffect, inc(j) -proc strip*(s: string, leading = true, trailing = true, chars: set[char] = Whitespace): string +proc strip*(s: string, leading = true, trailing = true, + chars: set[char] = Whitespace): string {.noSideEffect, rtl, extern: "nsuStrip".} = ## Strips `chars` from `s` and returns the resulting string. ## @@ -504,7 +505,8 @@ proc repeat*(c: char, count: Natural): string {.noSideEffect, ## ## .. code-block:: nim ## proc tabexpand(indent: int, text: string, tabsize: int = 4) = - ## echo '\t'.repeat(indent div tabsize), ' '.repeat(indent mod tabsize), text + ## echo '\t'.repeat(indent div tabsize), ' '.repeat(indent mod tabsize), + ## text ## ## tabexpand(4, "At four") ## tabexpand(5, "At five") @@ -533,11 +535,13 @@ template spaces*(n: Natural): string = repeat(' ',n) ## echo text1 & spaces(max(0, width - text1.len)) & "|" ## echo text2 & spaces(max(0, width - text2.len)) & "|" -proc repeatChar*(count: Natural, c: char = ' '): string {.deprecated.} = repeat(c, count) +proc repeatChar*(count: Natural, c: char = ' '): string {.deprecated.} = ## deprecated: use repeat() or spaces() + repeat(c, count) -proc repeatStr*(count: Natural, s: string): string {.deprecated.} = repeat(s, count) +proc repeatStr*(count: Natural, s: string): string {.deprecated.} = ## deprecated: use repeat(string, count) or string.repeat(count) + repeat(s, count) proc align*(s: string, count: Natural, padding = ' '): string {. noSideEffect, rtl, extern: "nsuAlignString".} = @@ -850,8 +854,8 @@ proc rfind*(s: string, sub: char, start: int = -1): int {.noSideEffect, if sub == s[i]: return i return -1 -proc count*(s: string, sub: string, overlapping: bool = false): int {.noSideEffect, - rtl, extern: "nsuCountString".} = +proc count*(s: string, sub: string, overlapping: bool = false): int {. + noSideEffect, rtl, extern: "nsuCountString".} = ## Count the occurrences of a substring `sub` in the string `s`. ## Overlapping occurrences of `sub` only count when `overlapping` ## is set to true. @@ -1449,7 +1453,8 @@ proc removeSuffix*(s: var string, chars: set[char] = Newlines) {. s.setLen(last + 1) -proc removeSuffix*(s: var string, c: char) {.rtl, extern: "nsuRemoveSuffixChar".} = +proc removeSuffix*(s: var string, c: char) {. + rtl, extern: "nsuRemoveSuffixChar".} = ## Removes a single character (in-place) from a string. ## .. code-block:: nim ## var @@ -1515,7 +1520,8 @@ when isMainModule: doAssert strip("sfoofoofoos", chars = {'s'}) == "foofoofoo" doAssert strip("barfoofoofoobar", chars = {'b', 'a', 'r'}) == "foofoofoo" doAssert strip("stripme but don't strip this stripme", - chars = {'s', 't', 'r', 'i', 'p', 'm', 'e'}) == " but don't strip this " + chars = {'s', 't', 'r', 'i', 'p', 'm', 'e'}) == + " but don't strip this " doAssert strip("sfoofoofoos", leading = false, chars = {'s'}) == "sfoofoofoo" doAssert strip("sfoofoofoos", trailing = false, chars = {'s'}) == "foofoofoos" From 732bdd54a09c2a7a1724a80ffbc6fbe09c697886 Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 6 Oct 2015 10:58:00 +0200 Subject: [PATCH 15/17] added critbits.inc proc --- lib/pure/collections/critbits.nim | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/pure/collections/critbits.nim b/lib/pure/collections/critbits.nim index 424bcdcca7..09b20fd450 100644 --- a/lib/pure/collections/critbits.nim +++ b/lib/pure/collections/critbits.nim @@ -123,6 +123,14 @@ proc containsOrIncl*(c: var CritBitTree[void], key: string): bool = var n = rawInsert(c, key) result = c.count == oldCount +proc inc*(c: var CritBitTree[int]; key: string) = + ## counts the 'key'. + let oldCount = c.count + var n = rawInsert(c, key) + if c.count == oldCount: + # not a new key: + inc n.val + proc incl*(c: var CritBitTree[void], key: string) = ## includes `key` in `c`. discard rawInsert(c, key) From 8507f95d68e097f714000f2baa4271ba09f5699e Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 6 Oct 2015 15:49:36 +0200 Subject: [PATCH 16/17] fixes #2637 --- compiler/ccgexprs.nim | 68 +++++++++------------ tests/ccgbugs/twrong_discriminant_check.nim | 30 +++++++++ 2 files changed, 60 insertions(+), 38 deletions(-) create mode 100644 tests/ccgbugs/twrong_discriminant_check.nim diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 32fc76470b..6d69dafa55 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -747,6 +747,17 @@ proc genTupleElem(p: BProc, e: PNode, d: var TLoc) = addf(r, ".Field$1", [rope(i)]) putIntoDest(p, d, ty.sons[i], r, a.s) +proc lookupFieldAgain(p: BProc, ty: PType; field: PSym; r: var Rope): PSym = + var ty = ty + assert r != nil + while ty != nil: + assert(ty.kind in {tyTuple, tyObject}) + result = lookupInRecord(ty.n, field.name) + if result != nil: break + if not p.module.compileToCpp: add(r, ".Sup") + ty = getUniqueType(ty.sons[0]) + if result == nil: internalError(field.info, "genCheckedRecordField") + proc genRecordField(p: BProc, e: PNode, d: var TLoc) = var a: TLoc var ty = genRecordFieldAux(p, e, d, a) @@ -758,15 +769,7 @@ proc genRecordField(p: BProc, e: PNode, d: var TLoc) = addf(r, ".Field$1", [rope(f.position)]) putIntoDest(p, d, f.typ, r, a.s) else: - var field: PSym = nil - while ty != nil: - if ty.kind notin {tyTuple, tyObject}: - internalError(e.info, "genRecordField") - field = lookupInRecord(ty.n, f.name) - if field != nil: break - if not p.module.compileToCpp: add(r, ".Sup") - ty = getUniqueType(ty.sons[0]) - if field == nil: internalError(e.info, "genRecordField 2 ") + let field = lookupFieldAgain(p, ty, f, r) if field.loc.r == nil: internalError(e.info, "genRecordField 3") addf(r, ".$1", [field.loc.r]) putIntoDest(p, d, field.typ, r, a.s) @@ -774,7 +777,8 @@ proc genRecordField(p: BProc, e: PNode, d: var TLoc) = proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc) -proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym) = +proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym; + origTy: PType) = var test, u, v: TLoc for i in countup(1, sonsLen(e) - 1): var it = e.sons[i] @@ -786,8 +790,12 @@ proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym) = assert(disc.kind == nkSym) initLoc(test, locNone, it.typ, OnStack) initLocExpr(p, it.sons[1], u) - initLoc(v, locExpr, disc.typ, OnUnknown) - v.r = "$1.$2" % [obj, disc.sym.loc.r] + var o = obj + let d = lookupFieldAgain(p, origTy, disc.sym, o) + initLoc(v, locExpr, d.typ, OnUnknown) + v.r = o + v.r.add(".") + v.r.add(d.loc.r) genInExprAux(p, it, u, v, test) let id = nodeTableTestOrSet(p.module.dataCache, newStrNode(nkStrLit, field.name.s), gBackendId) @@ -804,25 +812,14 @@ proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym) = proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) = if optFieldCheck in p.options: - var - a: TLoc - f, field: PSym - ty: PType - r: Rope - ty = genRecordFieldAux(p, e.sons[0], d, a) - r = rdLoc(a) - f = e.sons[0].sons[1].sym - field = nil - while ty != nil: - assert(ty.kind in {tyTuple, tyObject}) - field = lookupInRecord(ty.n, f.name) - if field != nil: break - if not p.module.compileToCpp: add(r, ".Sup") - ty = getUniqueType(ty.sons[0]) - if field == nil: internalError(e.info, "genCheckedRecordField") + var a: TLoc + let ty = genRecordFieldAux(p, e.sons[0], d, a) + var r = rdLoc(a) + let f = e.sons[0].sons[1].sym + let field = lookupFieldAgain(p, ty, f, r) if field.loc.r == nil: internalError(e.info, "genCheckedRecordField") # generate the checks: - genFieldCheck(p, e, r, field) + genFieldCheck(p, e, r, field, ty) add(r, rfmt(nil, ".$1", field.loc.r)) putIntoDest(p, d, field.typ, r, a.s) else: @@ -1150,20 +1147,15 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) = else: constructLoc(p, tmp) discard getTypeDesc(p.module, t) + let ty = getUniqueType(t) for i in 1 .. Date: Tue, 6 Oct 2015 16:15:51 +0200 Subject: [PATCH 17/17] fixes #3383 --- lib/windows/winlean.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim index e6a119e15f..89d86c62ac 100644 --- a/lib/windows/winlean.nim +++ b/lib/windows/winlean.nim @@ -18,7 +18,7 @@ const type Handle* = int LONG* = int32 - ULONG* = int + ULONG* = int32 PULONG* = ptr int WINBOOL* = int32 DWORD* = int32