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/compiler/extccomp.nim b/compiler/extccomp.nim
index 29aa03c94c..3882bdd036 100644
--- a/compiler/extccomp.nim
+++ b/compiler/extccomp.nim
@@ -14,7 +14,7 @@
import
lists, ropes, os, strutils, osproc, platform, condsyms, options, msgs,
- securehash
+ securehash, streams
type
TSystemCC* = enum
@@ -672,6 +672,12 @@ proc callCCompiler*(projectfile: string) =
var prettyCmds: TStringSeq = @[]
let prettyCb = proc (idx: int) =
echo prettyCmds[idx]
+ let runCb = proc (idx: int, p: Process) =
+ let exitCode = p.peekExitCode
+ if exitCode != 0:
+ rawMessage(errGenerated, "execution of an external compiler program '" &
+ cmds[idx] & "' failed with exit code: " & $exitCode & "\n\n" &
+ p.outputStream.readAll.strip)
compileCFile(toCompile, script, cmds, prettyCmds, false)
compileCFile(externalToCompile, script, cmds, prettyCmds, true)
if optCompileOnly notin gGlobalOptions:
@@ -682,22 +688,17 @@ proc callCCompiler*(projectfile: string) =
res = execWithEcho(cmds[i])
if res != 0: rawMessage(errExecutionOfProgramFailed, cmds[i])
elif optListCmd in gGlobalOptions or gVerbosity > 1:
- res = execProcesses(cmds, {poEchoCmd, poUsePath, poParentStreams},
- gNumberOfProcessors)
+ res = execProcesses(cmds, {poEchoCmd, poStdErrToStdOut, poUsePath, poParentStreams},
+ gNumberOfProcessors, afterRunEvent=runCb)
elif gVerbosity == 1:
- res = execProcesses(cmds, {poUsePath, poParentStreams},
- gNumberOfProcessors, prettyCb)
+ res = execProcesses(cmds, {poStdErrToStdOut, poUsePath, poParentStreams},
+ gNumberOfProcessors, prettyCb, afterRunEvent=runCb)
else:
- res = execProcesses(cmds, {poUsePath, poParentStreams},
- gNumberOfProcessors)
+ res = execProcesses(cmds, {poStdErrToStdOut, poUsePath, poParentStreams},
+ gNumberOfProcessors, afterRunEvent=runCb)
if res != 0:
if gNumberOfProcessors <= 1:
rawMessage(errExecutionOfProgramFailed, cmds.join())
- else:
- rawMessage(errGenerated,
- " execution of an external compiler program failed: " &
- cmds.join() & "; " &
- "rerun with --parallelBuild:1 to see the error message")
if optNoLinking notin gGlobalOptions:
# call the linker:
var it = PStrEntry(toLink.head)
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/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.. `_
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.
@@ -253,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 `_
@@ -265,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
@@ -397,6 +386,31 @@ 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.
+
+* `rawsockets `_
+ **Deprecated since version 0.11.4:**
+ This module has been renamed to `nativesockets `_.
+
+
Impure libraries
================
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
-------
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
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":
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 99%
rename from lib/pure/ftpclient.nim
rename to lib/deprecated/pure/ftpclient.nim
index 229fe4b511..1188c0795f 100644
--- a/lib/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/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/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/pure/sockets.nim b/lib/deprecated/pure/sockets.nim
similarity index 99%
rename from lib/pure/sockets.nim
rename to lib/deprecated/pure/sockets.nim
index 8fa69256be..5d6fa00787 100644
--- a/lib/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 93%
rename from lib/pure/rawsockets.nim
rename to lib/pure/nativesockets.nim
index f5860ef282..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
@@ -201,7 +203,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:
@@ -229,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
@@ -280,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,
@@ -330,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")
@@ -340,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
@@ -369,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.
@@ -386,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:
@@ -402,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")
@@ -421,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:
@@ -437,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/lib/pure/ospaths.nim b/lib/pure/ospaths.nim
index 99f6bcd4de..dcc7101939 100644
--- a/lib/pure/ospaths.nim
+++ b/lib/pure/ospaths.nim
@@ -496,7 +496,7 @@ when defined(nimdoc) and not declared(os):
proc existsFile(x: string): bool = discard
when declared(getEnv) or defined(nimscript):
- proc getHomeDir*(): string {.rtl, extern: "nos$1", tags: [ReadEnvEffect].} =
+ proc getHomeDir*(): string {.rtl, extern: "nos$1", tags: [ReadEnvEffect, ReadIOEffect].} =
## Returns the home directory of the current user.
##
## This proc is wrapped by the expandTilde proc for the convenience of
@@ -504,7 +504,7 @@ when declared(getEnv) or defined(nimscript):
when defined(windows): return string(getEnv("USERPROFILE")) & "\\"
else: return string(getEnv("HOME")) & "/"
- proc getConfigDir*(): string {.rtl, extern: "nos$1", tags: [ReadEnvEffect].} =
+ proc getConfigDir*(): string {.rtl, extern: "nos$1", tags: [ReadEnvEffect, ReadIOEffect].} =
## Returns the config directory of the current user for applications.
when defined(windows): return string(getEnv("APPDATA")) & "\\"
else: return string(getEnv("HOME")) & "/.config/"
@@ -515,7 +515,7 @@ when declared(getEnv) or defined(nimscript):
when defined(windows): return string(getEnv("TEMP")) & "\\"
else: return "/tmp/"
- proc expandTilde*(path: string): string {.tags: [ReadEnvEffect].} =
+ proc expandTilde*(path: string): string {.tags: [ReadEnvEffect, ReadIOEffect].} =
## Expands a path starting with ``~/`` to a full path.
##
## If `path` starts with the tilde character and is followed by `/` or `\\`
@@ -545,7 +545,7 @@ when declared(getEnv) or defined(nimscript):
yield substr(s, first, last-1)
inc(last)
- proc findExe*(exe: string): string {.tags: [ReadDirEffect, ReadEnvEffect].} =
+ proc findExe*(exe: string): string {.tags: [ReadDirEffect, ReadEnvEffect, ReadIOEffect].} =
## Searches for `exe` in the current working directory and then
## in directories listed in the ``PATH`` environment variable.
## Returns "" if the `exe` cannot be found. On DOS-like platforms, `exe`
diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim
index bc73f7119d..c23126be91 100644
--- a/lib/pure/osproc.nim
+++ b/lib/pure/osproc.nim
@@ -248,7 +248,8 @@ proc countProcessors*(): int {.rtl, extern: "nosp$1".} =
proc execProcesses*(cmds: openArray[string],
options = {poStdErrToStdOut, poParentStreams},
n = countProcessors(),
- beforeRunEvent: proc(idx: int) = nil): int
+ beforeRunEvent: proc(idx: int) = nil,
+ afterRunEvent: proc(idx: int, p: Process) = nil): int
{.rtl, extern: "nosp$1",
tags: [ExecIOEffect, TimeEffect, ReadEnvEffect, RootEffect]} =
## executes the commands `cmds` in parallel. Creates `n` processes
@@ -278,6 +279,7 @@ proc execProcesses*(cmds: openArray[string],
err.add("\n")
echo(err)
result = max(waitForExit(q[r]), result)
+ if afterRunEvent != nil: afterRunEvent(r, q[r])
if q[r] != nil: close(q[r])
if beforeRunEvent != nil:
beforeRunEvent(i)
@@ -291,6 +293,7 @@ proc execProcesses*(cmds: openArray[string],
if not running(q[r]):
#echo(outputStream(q[r]).readLine())
result = max(waitForExit(q[r]), result)
+ if afterRunEvent != nil: afterRunEvent(r, q[r])
if q[r] != nil: close(q[r])
if beforeRunEvent != nil:
beforeRunEvent(i)
@@ -299,6 +302,7 @@ proc execProcesses*(cmds: openArray[string],
if i > high(cmds): break
for j in 0..m-1:
result = max(waitForExit(q[j]), result)
+ if afterRunEvent != nil: afterRunEvent(j, q[j])
if q[j] != nil: close(q[j])
else:
for i in 0..high(cmds):
@@ -306,6 +310,7 @@ proc execProcesses*(cmds: openArray[string],
beforeRunEvent(i)
var p = startProcess(cmds[i], options=options + {poEvalCommand})
result = max(waitForExit(p), result)
+ if afterRunEvent != nil: afterRunEvent(i, p)
close(p)
proc select*(readfds: var seq[Process], timeout = 500): int {.benign.}
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
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
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 ..