Merge remote-tracking branch 'nim-lang/devel' into emscripten-support

This commit is contained in:
Andrey Sobolev 2015-10-06 10:55:52 +06:00
commit d1b67cb9bb
39 changed files with 294 additions and 133 deletions

View file

@ -12,8 +12,11 @@ cd ".."
./bin/nim c koch ./bin/nim c koch
./koch boot -d:release ./koch boot -d:release
./koch geninstall
cp -f install.sh.template install.sh set +x
chmod +x install.sh
echo
echo 'Install Nim using "./install.sh <dir>" or "sudo ./install.sh <dir>".'
exit 0 exit 0

View file

@ -14,7 +14,7 @@
import import
lists, ropes, os, strutils, osproc, platform, condsyms, options, msgs, lists, ropes, os, strutils, osproc, platform, condsyms, options, msgs,
securehash securehash, streams
type type
TSystemCC* = enum TSystemCC* = enum
@ -672,6 +672,12 @@ proc callCCompiler*(projectfile: string) =
var prettyCmds: TStringSeq = @[] var prettyCmds: TStringSeq = @[]
let prettyCb = proc (idx: int) = let prettyCb = proc (idx: int) =
echo prettyCmds[idx] 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(toCompile, script, cmds, prettyCmds, false)
compileCFile(externalToCompile, script, cmds, prettyCmds, true) compileCFile(externalToCompile, script, cmds, prettyCmds, true)
if optCompileOnly notin gGlobalOptions: if optCompileOnly notin gGlobalOptions:
@ -682,22 +688,17 @@ proc callCCompiler*(projectfile: string) =
res = execWithEcho(cmds[i]) res = execWithEcho(cmds[i])
if res != 0: rawMessage(errExecutionOfProgramFailed, cmds[i]) if res != 0: rawMessage(errExecutionOfProgramFailed, cmds[i])
elif optListCmd in gGlobalOptions or gVerbosity > 1: elif optListCmd in gGlobalOptions or gVerbosity > 1:
res = execProcesses(cmds, {poEchoCmd, poUsePath, poParentStreams}, res = execProcesses(cmds, {poEchoCmd, poStdErrToStdOut, poUsePath, poParentStreams},
gNumberOfProcessors) gNumberOfProcessors, afterRunEvent=runCb)
elif gVerbosity == 1: elif gVerbosity == 1:
res = execProcesses(cmds, {poUsePath, poParentStreams}, res = execProcesses(cmds, {poStdErrToStdOut, poUsePath, poParentStreams},
gNumberOfProcessors, prettyCb) gNumberOfProcessors, prettyCb, afterRunEvent=runCb)
else: else:
res = execProcesses(cmds, {poUsePath, poParentStreams}, res = execProcesses(cmds, {poStdErrToStdOut, poUsePath, poParentStreams},
gNumberOfProcessors) gNumberOfProcessors, afterRunEvent=runCb)
if res != 0: if res != 0:
if gNumberOfProcessors <= 1: if gNumberOfProcessors <= 1:
rawMessage(errExecutionOfProgramFailed, cmds.join()) 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: if optNoLinking notin gGlobalOptions:
# call the linker: # call the linker:
var it = PStrEntry(toLink.head) var it = PStrEntry(toLink.head)

View file

@ -115,6 +115,9 @@ Files: "lib/posix/*.nim"
Files: "lib/js/*.nim" Files: "lib/js/*.nim"
Files: "lib/packages/docutils/*.nim" Files: "lib/packages/docutils/*.nim"
Files: "lib/deprecated/core/*.nim"
Files: "lib/deprecated/pure/*.nim"
Files: "lib/deprecated/pure/*.cfg"
[Other] [Other]
Files: "examples/*.nim" Files: "examples/*.nim"

View file

@ -14,22 +14,14 @@ import
var systemModule*: PSym 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 var
gSysTypes: array[TTypeKind, PType] gSysTypes: array[TTypeKind, PType]
compilerprocs: TStrTable compilerprocs: TStrTable
exposed: TStrTable
proc nilOrSysInt*: PType = gSysTypes[tyInt] proc nilOrSysInt*: PType = gSysTypes[tyInt]
proc registerSysType(t: PType) = proc registerSysType*(t: PType) =
if gSysTypes[t.kind] == nil: gSysTypes[t.kind] = t if gSysTypes[t.kind] == nil: gSysTypes[t.kind] = t
proc newSysType(kind: TTypeKind, size: int): PType = proc newSysType(kind: TTypeKind, size: int): PType =
@ -37,7 +29,7 @@ proc newSysType(kind: TTypeKind, size: int): PType =
result.size = size result.size = size
result.align = size.int16 result.align = size.int16
proc getSysSym(name: string): PSym = proc getSysSym*(name: string): PSym =
result = strTableGet(systemModule.tab, getIdent(name)) result = strTableGet(systemModule.tab, getIdent(name))
if result == nil: if result == nil:
rawMessage(errSystemNeeds, name) rawMessage(errSystemNeeds, name)
@ -61,7 +53,7 @@ proc getSysMagic*(name: string, m: TMagic): PSym =
proc sysTypeFromName*(name: string): PType = proc sysTypeFromName*(name: string): PType =
result = getSysSym(name).typ result = getSysSym(name).typ
proc getSysType(kind: TTypeKind): PType = proc getSysType*(kind: TTypeKind): PType =
result = gSysTypes[kind] result = gSysTypes[kind]
if result == nil: if result == nil:
case kind case kind
@ -97,6 +89,7 @@ var
proc resetSysTypes* = proc resetSysTypes* =
systemModule = nil systemModule = nil
initStrTable(compilerprocs) initStrTable(compilerprocs)
initStrTable(exposed)
for i in low(gSysTypes)..high(gSysTypes): for i in low(gSysTypes)..high(gSysTypes):
gSysTypes[i] = nil gSysTypes[i] = nil
@ -163,8 +156,8 @@ proc setIntLitType*(result: PNode) =
result.typ = getSysType(tyInt64) result.typ = getSysType(tyInt64)
else: internalError(result.info, "invalid int size") else: internalError(result.info, "invalid int size")
proc getCompilerProc(name: string): PSym = proc getCompilerProc*(name: string): PSym =
var ident = getIdent(name, hashIgnoreStyle(name)) let ident = getIdent(name)
result = strTableGet(compilerprocs, ident) result = strTableGet(compilerprocs, ident)
if result == nil: if result == nil:
result = strTableGet(rodCompilerprocs, ident) result = strTableGet(rodCompilerprocs, ident)
@ -173,9 +166,22 @@ proc getCompilerProc(name: string): PSym =
if result.kind == skStub: loadStub(result) if result.kind == skStub: loadStub(result)
if result.kind == skAlias: result = result.owner if result.kind == skAlias: result = result.owner
proc registerCompilerProc(s: PSym) = proc registerCompilerProc*(s: PSym) =
strTableAdd(compilerprocs, s) 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(compilerprocs)
initStrTable(exposed)

View file

@ -78,6 +78,13 @@ proc resetModule*(fileIdx: int32) =
if fileIdx <% cgendata.gModules.len: if fileIdx <% cgendata.gModules.len:
cgendata.gModules[fileIdx] = nil 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* = proc resetAllModules* =
for i in 0..gCompiledModules.high: for i in 0..gCompiledModules.high:
if gCompiledModules[i] != nil: if gCompiledModules[i] != nil:

View file

@ -25,18 +25,19 @@ const
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC, wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl, wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe, wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe,
wOverride, wConstructor} wOverride, wConstructor, wExportNims}
converterPragmas* = procPragmas converterPragmas* = procPragmas
methodPragmas* = procPragmas+{wBase} methodPragmas* = procPragmas+{wBase}
templatePragmas* = {wImmediate, wDeprecated, wError, wGensym, wInject, wDirty, templatePragmas* = {wImmediate, wDeprecated, wError, wGensym, wInject, wDirty,
wDelegator} wDelegator, wExportNims}
macroPragmas* = {FirstCallConv..LastCallConv, wImmediate, wImportc, wExportc, macroPragmas* = {FirstCallConv..LastCallConv, wImmediate, wImportc, wExportc,
wNodecl, wMagic, wNosideeffect, wCompilerproc, wDeprecated, wExtern, 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, iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideeffect, wSideeffect,
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern, wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises, wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises,
wTags, wLocks, wGcSafe} wTags, wLocks, wGcSafe, wExportNims}
exprPragmas* = {wLine, wLocks, wNoRewrite} exprPragmas* = {wLine, wLocks, wNoRewrite}
stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks, stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks,
wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
@ -54,15 +55,15 @@ const
wPure, wHeader, wCompilerproc, wFinal, wSize, wExtern, wShallow, wPure, wHeader, wCompilerproc, wFinal, wSize, wExtern, wShallow,
wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef, wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef,
wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked, wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
wBorrow, wGcSafe} wBorrow, wGcSafe, wExportNims}
fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern, fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern,
wImportCpp, wImportObjC, wError, wGuard, wBitsize} wImportCpp, wImportObjC, wError, wGuard, wBitsize}
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl, varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
wMagic, wHeader, wDeprecated, wCompilerproc, wDynlib, wExtern, wMagic, wHeader, wDeprecated, wCompilerproc, wDynlib, wExtern,
wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal, wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal,
wGensym, wInject, wCodegenDecl, wGuard, wGoto} wGensym, wInject, wCodegenDecl, wGuard, wGoto, wExportNims}
constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl, constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
wExtern, wImportCpp, wImportObjC, wError, wGensym, wInject} wExtern, wImportCpp, wImportObjC, wError, wGensym, wInject, wExportNims}
letPragmas* = varPragmas letPragmas* = varPragmas
procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideeffect, procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideeffect,
wThread, wRaises, wLocks, wTags, wGcSafe} wThread, wRaises, wLocks, wTags, wGcSafe}
@ -859,6 +860,9 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
invalidPragma(it) invalidPragma(it)
else: else:
sym.flags.incl sfGoto sym.flags.incl sfGoto
of wExportNims:
if sym == nil: invalidPragma(it)
else: magicsys.registerNimScriptSymbol(sym)
of wInjectStmt: of wInjectStmt:
if it.kind != nkExprColonExpr: if it.kind != nkExprColonExpr:
localError(it.info, errExprExpected) localError(it.info, errExprExpected)

View file

@ -1411,6 +1411,31 @@ proc execute(c: PCtx, start: int): PNode =
newSeq(tos.slots, c.prc.maxSlots) newSeq(tos.slots, c.prc.maxSlots)
result = rawExecute(c, start, tos).regToNode 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.. <sym.typ.len:
putIntoReg(tos.slots[i], args[i-1])
result = rawExecute(c, start, tos).regToNode
else:
localError(sym.info,
"NimScript: attempt to call non-routine: " & sym.name.s)
proc evalStmt*(c: PCtx, n: PNode) = proc evalStmt*(c: PCtx, n: PNode) =
let n = transformExpr(c.module, n) let n = transformExpr(c.module, n)
let start = genStmt(c, n) let start = genStmt(c, n)

View file

@ -42,7 +42,7 @@ type
wImmediate, wConstructor, wDestructor, wDelegator, wOverride, wImmediate, wConstructor, wDestructor, wDelegator, wOverride,
wImportCpp, wImportObjC, wImportCpp, wImportObjC,
wImportCompilerProc, wImportCompilerProc,
wImportc, wExportc, wIncompleteStruct, wRequiresInit, wImportc, wExportc, wExportNims, wIncompleteStruct, wRequiresInit,
wAlign, wNodecl, wPure, wSideeffect, wHeader, wAlign, wNodecl, wPure, wSideeffect, wHeader,
wNosideeffect, wGcSafe, wNoreturn, wMerge, wLib, wDynlib, wNosideeffect, wGcSafe, wNoreturn, wMerge, wLib, wDynlib,
wCompilerproc, wProcVar, wBase, wCompilerproc, wProcVar, wBase,
@ -126,7 +126,8 @@ const
"immediate", "constructor", "destructor", "delegator", "override", "immediate", "constructor", "destructor", "delegator", "override",
"importcpp", "importobjc", "importcpp", "importobjc",
"importcompilerproc", "importc", "exportc", "incompletestruct", "importcompilerproc", "importc", "exportc", "exportnims",
"incompletestruct",
"requiresinit", "align", "nodecl", "pure", "sideeffect", "requiresinit", "align", "nodecl", "pure", "sideeffect",
"header", "nosideeffect", "gcsafe", "noreturn", "merge", "lib", "dynlib", "header", "nosideeffect", "gcsafe", "noreturn", "merge", "lib", "dynlib",
"compilerproc", "procvar", "base", "compilerproc", "procvar", "base",

View file

@ -27,6 +27,8 @@ mips.linux.gcc.linkerexe = "mips-openwrt-linux-gcc"
cs:partial cs:partial
@end @end
path="$lib/deprecated/core"
path="$lib/deprecated/pure"
path="$lib/pure/collections" path="$lib/pure/collections"
path="$lib/pure/concurrency" path="$lib/pure/concurrency"
path="$lib/impure" path="$lib/impure"

View file

@ -201,12 +201,6 @@ Internet Protocols and Support
* `scgi <scgi.html>`_ * `scgi <scgi.html>`_
This module implements helpers for SCGI applications. This module implements helpers for SCGI applications.
* `sockets <sockets.html>`_
This module implements a simple portable type-safe sockets layer.
* `asyncio <asyncio.html>`_
This module implements an asynchronous event loop for sockets.
* `browsers <browsers.html>`_ * `browsers <browsers.html>`_
This module implements procs for opening URLs with the user's default This module implements procs for opening URLs with the user's default
browser. browser.
@ -220,9 +214,6 @@ Internet Protocols and Support
* `smtp <smtp.html>`_ * `smtp <smtp.html>`_
This module implement a simple SMTP client. This module implement a simple SMTP client.
* `ftpclient <ftpclient.html>`_
This module implements an FTP client.
* `cookies <cookies.html>`_ * `cookies <cookies.html>`_
This module contains helper procs for parsing and generating 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 This module implements a high-level sockets API. It will replace the
``sockets`` module in the future. ``sockets`` module in the future.
* `rawsockets <rawsockets.html>`_ * `nativesockets <nativesockets.html>`_
This module implements a low-level sockets API. This module implements a low-level sockets API.
* `selectors <selectors.html>`_ * `selectors <selectors.html>`_
@ -265,8 +256,6 @@ Parsers
* `parseopt <parseopt.html>`_ * `parseopt <parseopt.html>`_
The ``parseopt`` module implements a command line option parser. The ``parseopt`` module implements a command line option parser.
**Deprecated since version 0.9.3:** Use the `parseopt2
<parseopt2.html>`_ module instead.
* `parseopt2 <parseopt2.html>`_ * `parseopt2 <parseopt2.html>`_
The ``parseopt2`` module implements a command line option parser. This 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. Declaration of the Document Object Model for the JS backend.
Deprecated modules
------------------
* `asyncio <asyncio.html>`_
This module implements an asynchronous event loop for sockets.
**Deprecated since version 0.11.2:**
Use the `asyncnet <asyncnet.html>`_ together with the
`asyncdispatch <asyncdispatch.html>`_ module instead.
* `ftpclient <ftpclient.html>`_
This module implements an FTP client.
**Deprecated since version 0.11.3:**
Use the `asyncftpclient <asyncftpclient.html>`_ module instead.
* `sockets <sockets.html>`_
This module implements a simple portable type-safe sockets layer.
**Deprecated since version 0.11.2:**
Use the `net <net.html>`_ or the `rawsockets <rawsockets.html>`_ module
instead.
* `rawsockets <rawsockets.html>`_
**Deprecated since version 0.11.4:**
This module has been renamed to `nativesockets <nativesockets.html>`_.
Impure libraries Impure libraries
================ ================

View file

@ -490,6 +490,11 @@ to an open array parameter.
The openarray type cannot be nested: multidimensional openarrays are not The openarray type cannot be nested: multidimensional openarrays are not
supported because this is seldom needed and cannot be done efficiently. 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 Varargs
------- -------

View file

@ -1,9 +0,0 @@
#!/bin/sh
set -e
set -x
if [ "$1" != "" ]; then
exec ./koch install "$1"
else
exec ./koch install
fi

View file

@ -41,6 +41,7 @@ Options:
Possible Commands: Possible Commands:
boot [options] bootstraps with given command line options boot [options] bootstraps with given command line options
install [bindir] installs to given directory; Unix only! install [bindir] installs to given directory; Unix only!
geninstall generate ./install.sh; Unix only!
clean cleans Nim project; removes generated files clean cleans Nim project; removes generated files
web [options] generates the website and the full documentation web [options] generates the website and the full documentation
website [options] generates only the website website [options] generates only the website
@ -127,9 +128,12 @@ proc nsis(args: string) =
exec(("tools" / "niminst" / "niminst --var:version=$# --var:mingw=mingw$#" & exec(("tools" / "niminst" / "niminst --var:version=$# --var:mingw=mingw$#" &
" nsis compiler/installer.ini") % [VersionAsString, $(sizeof(pointer)*8)]) " 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) = proc install(args: string) =
exec("$# cc -r $# --var:version=$# --var:mingw=none --main:compiler/nim.nim scripts compiler/installer.ini" % geninstall()
[findNim(), compileNimInst, VersionAsString])
exec("sh ./install.sh $#" % args) exec("sh ./install.sh $#" % args)
proc web(args: string) = proc web(args: string) =
@ -373,6 +377,7 @@ of cmdArgument:
of "zip": zip(op.cmdLineRest) of "zip": zip(op.cmdLineRest)
of "xz": xz(op.cmdLineRest) of "xz": xz(op.cmdLineRest)
of "nsis": nsis(op.cmdLineRest) of "nsis": nsis(op.cmdLineRest)
of "geninstall": geninstall(op.cmdLineRest)
of "install": install(op.cmdLineRest) of "install": install(op.cmdLineRest)
of "test", "tests": tests(op.cmdLineRest) of "test", "tests": tests(op.cmdLineRest)
of "update": of "update":

View file

@ -11,7 +11,7 @@ include "system/inclrtl"
import sockets, strutils, parseutils, times, os, asyncio import sockets, strutils, parseutils, times, os, asyncio
from asyncnet import nil from asyncnet import nil
from rawsockets import nil from nativesockets import nil
from asyncdispatch import PFuture from asyncdispatch import PFuture
## **Note**: This module is deprecated since version 0.11.3. ## **Note**: This module is deprecated since version 0.11.3.
## You should use the async version of this module ## You should use the async version of this module
@ -55,7 +55,7 @@ type
user*, pass*: string user*, pass*: string
address*: string address*: string
when SockType is asyncnet.AsyncSocket: when SockType is asyncnet.AsyncSocket:
port*: rawsockets.Port port*: nativesockets.Port
else: else:
port*: Port port*: Port

View file

@ -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)

View file

@ -9,7 +9,7 @@
## **Warning:** Since version 0.10.2 this module is deprecated. ## **Warning:** Since version 0.10.2 this module is deprecated.
## Use the `net <net.html>`_ or the ## Use the `net <net.html>`_ or the
## `rawsockets <rawsockets.html>`_ module instead. ## `nativesockets <nativesockets.html>`_ module instead.
## ##
## This module implements portable sockets, it supports a mix of different types ## This module implements portable sockets, it supports a mix of different types
## of sockets. Sockets are buffered by default meaning that data will be ## of sockets. Sockets are buffered by default meaning that data will be

View file

@ -11,7 +11,7 @@ include "system/inclrtl"
import os, oids, tables, strutils, macros, times import os, oids, tables, strutils, macros, times
import rawsockets, net import nativesockets, net
export Port, SocketFlag export Port, SocketFlag
@ -475,7 +475,7 @@ when defined(windows) or defined(nimdoc):
addr bytesRet, nil, nil) == 0 addr bytesRet, nil, nil) == 0
proc initAll() = proc initAll() =
let dummySock = newRawSocket() let dummySock = newNativeSocket()
if not initPointer(dummySock, connectExPtr, WSAID_CONNECTEX): if not initPointer(dummySock, connectExPtr, WSAID_CONNECTEX):
raiseOSError(osLastError()) raiseOSError(osLastError())
if not initPointer(dummySock, acceptExPtr, WSAID_ACCEPTEX): if not initPointer(dummySock, acceptExPtr, WSAID_ACCEPTEX):
@ -528,7 +528,7 @@ when defined(windows) or defined(nimdoc):
RemoteSockaddr, RemoteSockaddrLength) RemoteSockaddr, RemoteSockaddrLength)
proc connect*(socket: AsyncFD, address: string, port: Port, 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``. ## Connects ``socket`` to server at ``address:port``.
## ##
## Returns a ``Future`` which will complete when the connection succeeds ## Returns a ``Future`` which will complete when the connection succeeds
@ -827,7 +827,7 @@ when defined(windows) or defined(nimdoc):
verifyPresence(socket) verifyPresence(socket)
var retFuture = newFuture[tuple[address: string, client: AsyncFD]]("acceptAddr") var retFuture = newFuture[tuple[address: string, client: AsyncFD]]("acceptAddr")
var clientSock = newRawSocket() var clientSock = newNativeSocket()
if clientSock == osInvalidSocket: raiseOSError(osLastError()) if clientSock == osInvalidSocket: raiseOSError(osLastError())
const lpOutputLen = 1024 const lpOutputLen = 1024
@ -900,17 +900,17 @@ when defined(windows) or defined(nimdoc):
return retFuture 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. ## 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) result.SocketHandle.setBlocking(false)
register(result) register(result)
proc newAsyncRawSocket*(domain: Domain = rawsockets.AF_INET, proc newAsyncNativeSocket*(domain: Domain = nativesockets.AF_INET,
sockType: SockType = SOCK_STREAM, sockType: SockType = SOCK_STREAM,
protocol: Protocol = IPPROTO_TCP): AsyncFD = protocol: Protocol = IPPROTO_TCP): AsyncFD =
## Creates a new socket and registers it with the dispatcher implicitly. ## 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) result.SocketHandle.setBlocking(false)
register(result) register(result)
@ -973,18 +973,18 @@ else:
var data = PData(fd: fd, readCBs: @[], writeCBs: @[]) var data = PData(fd: fd, readCBs: @[], writeCBs: @[])
p.selector.register(fd.SocketHandle, {}, data.RootRef) p.selector.register(fd.SocketHandle, {}, data.RootRef)
proc newAsyncRawSocket*(domain: cint, sockType: cint, proc newAsyncNativeSocket*(domain: cint, sockType: cint,
protocol: cint): AsyncFD = protocol: cint): AsyncFD =
result = newRawSocket(domain, sockType, protocol).AsyncFD result = newNativeSocket(domain, sockType, protocol).AsyncFD
result.SocketHandle.setBlocking(false) result.SocketHandle.setBlocking(false)
when defined(macosx): when defined(macosx):
result.SocketHandle.setSockOptInt(SOL_SOCKET, SO_NOSIGPIPE, 1) result.SocketHandle.setSockOptInt(SOL_SOCKET, SO_NOSIGPIPE, 1)
register(result) register(result)
proc newAsyncRawSocket*(domain: Domain = AF_INET, proc newAsyncNativeSocket*(domain: Domain = AF_INET,
sockType: SockType = SOCK_STREAM, sockType: SockType = SOCK_STREAM,
protocol: Protocol = IPPROTO_TCP): AsyncFD = protocol: Protocol = IPPROTO_TCP): AsyncFD =
result = newRawSocket(domain, sockType, protocol).AsyncFD result = newNativeSocket(domain, sockType, protocol).AsyncFD
result.SocketHandle.setBlocking(false) result.SocketHandle.setBlocking(false)
when defined(macosx): when defined(macosx):
result.SocketHandle.setSockOptInt(SOL_SOCKET, SO_NOSIGPIPE, 1) result.SocketHandle.setSockOptInt(SOL_SOCKET, SO_NOSIGPIPE, 1)

View file

@ -56,7 +56,7 @@
## ##
import asyncdispatch import asyncdispatch
import rawsockets import nativesockets
import net import net
import os 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 procedure will also create a brand new file descriptor for
## this socket. ## this socket.
result = newAsyncSocket(newAsyncRawSocket(domain, sockType, protocol), domain, result = newAsyncSocket(newAsyncNativeSocket(domain, sockType, protocol),
sockType, protocol, buffered) domain, sockType, protocol, buffered)
proc newAsyncSocket*(domain, sockType, protocol: cint, proc newAsyncSocket*(domain, sockType, protocol: cint,
buffered = true): AsyncSocket = 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 procedure will also create a brand new file descriptor for
## this socket. ## this socket.
result = newAsyncSocket(newAsyncRawSocket(domain, sockType, protocol), result = newAsyncSocket(newAsyncNativeSocket(domain, sockType, protocol),
Domain(domain), SockType(sockType), Protocol(protocol), buffered) Domain(domain), SockType(sockType),
Protocol(protocol), buffered)
when defined(ssl): when defined(ssl):
proc getSslError(handle: SslPtr, err: cint): cint = proc getSslError(handle: SslPtr, err: cint): cint =

View file

@ -81,7 +81,7 @@
import net, strutils, uri, parseutils, strtabs, base64, os, mimetypes, math import net, strutils, uri, parseutils, strtabs, base64, os, mimetypes, math
import asyncnet, asyncdispatch import asyncnet, asyncdispatch
import rawsockets import nativesockets
type type
Response* = tuple[ Response* = tuple[
@ -764,10 +764,10 @@ proc newConnection(client: AsyncHttpClient, url: Uri) {.async.} =
let port = let port =
if url.port == "": if url.port == "":
if url.scheme.toLower() == "https": if url.scheme.toLower() == "https":
rawsockets.Port(443) nativesockets.Port(443)
else: else:
rawsockets.Port(80) nativesockets.Port(80)
else: rawsockets.Port(url.port.parseInt) else: nativesockets.Port(url.port.parseInt)
if url.scheme.toLower() == "https": if url.scheme.toLower() == "https":
when defined(ssl): when defined(ssl):

View file

@ -93,8 +93,8 @@ when useWinVersion:
IOC_IN* = int(-2147483648) IOC_IN* = int(-2147483648)
FIONBIO* = IOC_IN.int32 or ((sizeof(int32) and IOCPARM_MASK) shl 16) or FIONBIO* = IOC_IN.int32 or ((sizeof(int32) and IOCPARM_MASK) shl 16) or
(102 shl 8) or 126 (102 shl 8) or 126
rawAfInet = winlean.AF_INET nativeAfInet = winlean.AF_INET
rawAfInet6 = winlean.AF_INET6 nativeAfInet6 = winlean.AF_INET6
proc ioctlsocket*(s: SocketHandle, cmd: clong, proc ioctlsocket*(s: SocketHandle, cmd: clong,
argptr: ptr clong): cint {. argptr: ptr clong): cint {.
@ -102,8 +102,8 @@ when useWinVersion:
else: else:
let let
osInvalidSocket* = posix.INVALID_SOCKET osInvalidSocket* = posix.INVALID_SOCKET
rawAfInet = posix.AF_INET nativeAfInet = posix.AF_INET
rawAfInet6 = posix.AF_INET6 nativeAfInet6 = posix.AF_INET6
proc `==`*(a, b: Port): bool {.borrow.} proc `==`*(a, b: Port): bool {.borrow.}
## ``==`` for ports. ## ``==`` for ports.
@ -157,12 +157,14 @@ else:
result = cint(ord(p)) result = cint(ord(p))
proc newRawSocket*(domain: Domain = AF_INET, sockType: SockType = SOCK_STREAM, proc newNativeSocket*(domain: Domain = AF_INET,
sockType: SockType = SOCK_STREAM,
protocol: Protocol = IPPROTO_TCP): SocketHandle = protocol: Protocol = IPPROTO_TCP): SocketHandle =
## Creates a new socket; returns `InvalidSocket` if an error occurs. ## Creates a new socket; returns `InvalidSocket` if an error occurs.
socket(toInt(domain), toInt(sockType), toInt(protocol)) 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. ## Creates a new socket; returns `InvalidSocket` if an error occurs.
## ##
## Use this overload if one of the enums specified above does ## Use this overload if one of the enums specified above does
@ -201,6 +203,8 @@ proc getAddrInfo*(address: string, port: Port, domain: Domain = AF_INET,
hints.ai_family = toInt(domain) hints.ai_family = toInt(domain)
hints.ai_socktype = toInt(sockType) hints.ai_socktype = toInt(sockType)
hints.ai_protocol = toInt(protocol) hints.ai_protocol = toInt(protocol)
# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=198092
when not defined(freebsd):
hints.ai_flags = AI_V4MAPPED hints.ai_flags = AI_V4MAPPED
var gaiResult = getaddrinfo(address, $port, addr(hints), result) var gaiResult = getaddrinfo(address, $port, addr(hints), result)
if gaiResult != 0'i32: if gaiResult != 0'i32:
@ -229,17 +233,17 @@ proc ntohs*(x: int16): int16 =
when cpuEndian == bigEndian: result = x when cpuEndian == bigEndian: result = x
else: result = (x shr 8'i16) or (x shl 8'i16) 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 ## 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 ## 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. ## 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. ## Converts 16-bit positive integers from host to network byte order.
## On machines where the host byte order is the same as network byte ## 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. ## 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].} = proc getServByName*(name, proto: string): Servent {.tags: [ReadIOEffect].} =
## Searches the database from the beginning and finds the first entry for ## 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: when useWinVersion:
var s = winlean.gethostbyaddr(addr(myaddr), sizeof(myaddr).cuint, var s = winlean.gethostbyaddr(addr(myaddr), sizeof(myaddr).cuint,
cint(rawsockets.AF_INET)) cint(AF_INET))
if s == nil: raiseOSError(osLastError()) if s == nil: raiseOSError(osLastError())
else: else:
var s = posix.gethostbyaddr(addr(myaddr), sizeof(myaddr).Socklen, 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)), if getsockname(socket, cast[ptr SockAddr](addr(name)),
addr(namelen)) == -1'i32: addr(namelen)) == -1'i32:
raiseOSError(osLastError()) raiseOSError(osLastError())
if name.sa_family == rawAfInet: if name.sa_family == nativeAfInet:
result = AF_INET result = AF_INET
elif name.sa_family == rawAfInet6: elif name.sa_family == nativeAfInet6:
result = AF_INET6 result = AF_INET6
else: else:
raiseOSError(osLastError(), "unknown socket family in getSockFamily") raiseOSError(osLastError(), "unknown socket family in getSockFamily")
@ -340,9 +344,9 @@ proc getSockDomain*(socket: SocketHandle): Domain =
proc getAddrString*(sockAddr: ptr SockAddr): string = proc getAddrString*(sockAddr: ptr SockAddr): string =
## return the string representation of address within sockAddr ## 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) result = $inet_ntoa(cast[ptr Sockaddr_in](sockAddr).sin_addr)
elif sockAddr.sa_family == rawAfInet6: elif sockAddr.sa_family == nativeAfInet6:
when not useWinVersion: when not useWinVersion:
# TODO: Windows # TODO: Windows
var v6addr = cast[ptr Sockaddr_in6](sockAddr).sin6_addr 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)), if getsockname(socket, cast[ptr SockAddr](addr(name)),
addr(namelen)) == -1'i32: addr(namelen)) == -1'i32:
raiseOSError(osLastError()) raiseOSError(osLastError())
result = Port(rawsockets.ntohs(name.sin_port)) result = Port(nativesockets.ntohs(name.sin_port))
proc getLocalAddr*(socket: SocketHandle, domain: Domain): (string, Port) = proc getLocalAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
## returns the socket's local address and port number. ## 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)), if getsockname(socket, cast[ptr SockAddr](addr(name)),
addr(namelen)) == -1'i32: addr(namelen)) == -1'i32:
raiseOSError(osLastError()) 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: of AF_INET6:
var name: Sockaddr_in6 var name: Sockaddr_in6
when useWinVersion: when useWinVersion:
@ -402,7 +407,7 @@ proc getLocalAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
if inet_ntop(name.sin6_family.cint, if inet_ntop(name.sin6_family.cint,
addr name, buf.cstring, sizeof(buf).int32).isNil: addr name, buf.cstring, sizeof(buf).int32).isNil:
raiseOSError(osLastError()) raiseOSError(osLastError())
result = ($buf, Port(rawsockets.ntohs(name.sin6_port))) result = ($buf, Port(nativesockets.ntohs(name.sin6_port)))
else: else:
raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr") 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)), if getpeername(socket, cast[ptr SockAddr](addr(name)),
addr(namelen)) == -1'i32: addr(namelen)) == -1'i32:
raiseOSError(osLastError()) 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: of AF_INET6:
var name: Sockaddr_in6 var name: Sockaddr_in6
when useWinVersion: when useWinVersion:
@ -437,7 +443,7 @@ proc getPeerAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
if inet_ntop(name.sin6_family.cint, if inet_ntop(name.sin6_family.cint,
addr name, buf.cstring, sizeof(buf).int32).isNil: addr name, buf.cstring, sizeof(buf).int32).isNil:
raiseOSError(osLastError()) raiseOSError(osLastError())
result = ($buf, Port(rawsockets.ntohs(name.sin6_port))) result = ($buf, Port(nativesockets.ntohs(name.sin6_port)))
else: else:
raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr") raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr")

View file

@ -10,7 +10,7 @@
## This module implements a high-level cross-platform sockets interface. ## This module implements a high-level cross-platform sockets interface.
{.deadCodeElim: on.} {.deadCodeElim: on.}
import rawsockets, os, strutils, unsigned, parseutils, times import nativesockets, os, strutils, unsigned, parseutils, times
export Port, `$`, `==` export Port, `$`, `==`
const useWinVersion = defined(Windows) or defined(nimdoc) const useWinVersion = defined(Windows) or defined(nimdoc)
@ -145,7 +145,7 @@ proc newSocket*(domain, sockType, protocol: cint, buffered = true): Socket =
## Creates a new socket. ## Creates a new socket.
## ##
## If an error occurs EOS will be raised. ## If an error occurs EOS will be raised.
let fd = newRawSocket(domain, sockType, protocol) let fd = newNativeSocket(domain, sockType, protocol)
if fd == osInvalidSocket: if fd == osInvalidSocket:
raiseOSError(osLastError()) raiseOSError(osLastError())
result = newSocket(fd, domain.Domain, sockType.SockType, protocol.Protocol, 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. ## Creates a new socket.
## ##
## If an error occurs EOS will be raised. ## If an error occurs EOS will be raised.
let fd = newRawSocket(domain, sockType, protocol) let fd = newNativeSocket(domain, sockType, protocol)
if fd == osInvalidSocket: if fd == osInvalidSocket:
raiseOSError(osLastError()) raiseOSError(osLastError())
result = newSocket(fd, domain, sockType, protocol, buffered) result = newSocket(fd, domain, sockType, protocol, buffered)
@ -354,7 +354,7 @@ proc listen*(socket: Socket, backlog = SOMAXCONN) {.tags: [ReadIOEffect].} =
## queue of pending connections. ## queue of pending connections.
## ##
## Raises an EOS error upon failure. ## Raises an EOS error upon failure.
if rawsockets.listen(socket.fd, backlog) < 0'i32: if nativesockets.listen(socket.fd, backlog) < 0'i32:
raiseOSError(osLastError()) raiseOSError(osLastError())
proc bindAddr*(socket: Socket, port = Port(0), address = "") {. proc bindAddr*(socket: Socket, port = Port(0), address = "") {.

View file

@ -496,7 +496,7 @@ when defined(nimdoc) and not declared(os):
proc existsFile(x: string): bool = discard proc existsFile(x: string): bool = discard
when declared(getEnv) or defined(nimscript): 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. ## Returns the home directory of the current user.
## ##
## This proc is wrapped by the expandTilde proc for the convenience of ## 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")) & "\\" when defined(windows): return string(getEnv("USERPROFILE")) & "\\"
else: return string(getEnv("HOME")) & "/" 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. ## Returns the config directory of the current user for applications.
when defined(windows): return string(getEnv("APPDATA")) & "\\" when defined(windows): return string(getEnv("APPDATA")) & "\\"
else: return string(getEnv("HOME")) & "/.config/" else: return string(getEnv("HOME")) & "/.config/"
@ -515,7 +515,7 @@ when declared(getEnv) or defined(nimscript):
when defined(windows): return string(getEnv("TEMP")) & "\\" when defined(windows): return string(getEnv("TEMP")) & "\\"
else: return "/tmp/" 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. ## Expands a path starting with ``~/`` to a full path.
## ##
## If `path` starts with the tilde character and is followed by `/` or `\\` ## 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) yield substr(s, first, last-1)
inc(last) 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 ## Searches for `exe` in the current working directory and then
## in directories listed in the ``PATH`` environment variable. ## in directories listed in the ``PATH`` environment variable.
## Returns "" if the `exe` cannot be found. On DOS-like platforms, `exe` ## Returns "" if the `exe` cannot be found. On DOS-like platforms, `exe`

View file

@ -248,7 +248,8 @@ proc countProcessors*(): int {.rtl, extern: "nosp$1".} =
proc execProcesses*(cmds: openArray[string], proc execProcesses*(cmds: openArray[string],
options = {poStdErrToStdOut, poParentStreams}, options = {poStdErrToStdOut, poParentStreams},
n = countProcessors(), 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", {.rtl, extern: "nosp$1",
tags: [ExecIOEffect, TimeEffect, ReadEnvEffect, RootEffect]} = tags: [ExecIOEffect, TimeEffect, ReadEnvEffect, RootEffect]} =
## executes the commands `cmds` in parallel. Creates `n` processes ## executes the commands `cmds` in parallel. Creates `n` processes
@ -278,6 +279,7 @@ proc execProcesses*(cmds: openArray[string],
err.add("\n") err.add("\n")
echo(err) echo(err)
result = max(waitForExit(q[r]), result) result = max(waitForExit(q[r]), result)
if afterRunEvent != nil: afterRunEvent(r, q[r])
if q[r] != nil: close(q[r]) if q[r] != nil: close(q[r])
if beforeRunEvent != nil: if beforeRunEvent != nil:
beforeRunEvent(i) beforeRunEvent(i)
@ -291,6 +293,7 @@ proc execProcesses*(cmds: openArray[string],
if not running(q[r]): if not running(q[r]):
#echo(outputStream(q[r]).readLine()) #echo(outputStream(q[r]).readLine())
result = max(waitForExit(q[r]), result) result = max(waitForExit(q[r]), result)
if afterRunEvent != nil: afterRunEvent(r, q[r])
if q[r] != nil: close(q[r]) if q[r] != nil: close(q[r])
if beforeRunEvent != nil: if beforeRunEvent != nil:
beforeRunEvent(i) beforeRunEvent(i)
@ -299,6 +302,7 @@ proc execProcesses*(cmds: openArray[string],
if i > high(cmds): break if i > high(cmds): break
for j in 0..m-1: for j in 0..m-1:
result = max(waitForExit(q[j]), result) result = max(waitForExit(q[j]), result)
if afterRunEvent != nil: afterRunEvent(j, q[j])
if q[j] != nil: close(q[j]) if q[j] != nil: close(q[j])
else: else:
for i in 0..high(cmds): for i in 0..high(cmds):
@ -306,6 +310,7 @@ proc execProcesses*(cmds: openArray[string],
beforeRunEvent(i) beforeRunEvent(i)
var p = startProcess(cmds[i], options=options + {poEvalCommand}) var p = startProcess(cmds[i], options=options + {poEvalCommand})
result = max(waitForExit(p), result) result = max(waitForExit(p), result)
if afterRunEvent != nil: afterRunEvent(i, p)
close(p) close(p)
proc select*(readfds: var seq[Process], timeout = 500): int {.benign.} proc select*(readfds: var seq[Process], timeout = 500): int {.benign.}

View file

@ -39,6 +39,63 @@ proc toRational*[T:SomeInteger](x: T): Rational[T] =
result.num = x result.num = x
result.den = 1 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 = proc toFloat*[T](x: Rational[T]): float =
## Convert a rational number `x` to a float. ## Convert a rational number `x` to a float.
x.num / x.den x.num / x.den
@ -288,3 +345,8 @@ when isMainModule:
assert toRational(5) == 5//1 assert toRational(5) == 5//1
assert abs(toFloat(y) - 0.4814814814814815) < 1.0e-7 assert abs(toFloat(y) - 0.4814814814814815) < 1.0e-7
assert toInt(z) == 0 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

View file

@ -31,7 +31,8 @@ proc moveFile(src, dest: string) {.
tags: [ReadIOEffect, WriteIOEffect], raises: [OSError].} = builtin tags: [ReadIOEffect, WriteIOEffect], raises: [OSError].} = builtin
proc copyFile(src, dest: string) {. proc copyFile(src, dest: string) {.
tags: [ReadIOEffect, WriteIOEffect], raises: [OSError].} = builtin 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 getOsError: string = builtin
proc setCurrentDir(dir: string) = builtin proc setCurrentDir(dir: string) = builtin
proc getCurrentDir(): string = builtin proc getCurrentDir(): string = builtin

View file

@ -2,7 +2,7 @@ discard """
file: "tasyncawait.nim" file: "tasyncawait.nim"
output: "5000" output: "5000"
""" """
import asyncdispatch, rawsockets, net, strutils, os import asyncdispatch, nativesockets, net, strutils, os
var msgCount = 0 var msgCount = 0
@ -18,7 +18,7 @@ proc sendMessages(client: TAsyncFD) {.async.} =
proc launchSwarm(port: TPort) {.async.} = proc launchSwarm(port: TPort) {.async.} =
for i in 0 .. <swarmSize: for i in 0 .. <swarmSize:
var sock = newAsyncRawSocket() var sock = newAsyncNativeSocket()
await connect(sock, "localhost", port) await connect(sock, "localhost", port)
await sendMessages(sock) await sendMessages(sock)
@ -38,7 +38,7 @@ proc readMessages(client: TAsyncFD) {.async.} =
doAssert false doAssert false
proc createServer(port: TPort) {.async.} = proc createServer(port: TPort) {.async.} =
var server = newAsyncRawSocket() var server = newAsyncNativeSocket()
block: block:
var name: Sockaddr_in var name: Sockaddr_in
when defined(windows): when defined(windows):

View file

@ -19,7 +19,7 @@ when defined(windows) or defined(nimdoc):
quit("Error: unhandled exception: Connection refused") quit("Error: unhandled exception: Connection refused")
else: else:
proc testAsyncConnect() {.async.} = proc testAsyncConnect() {.async.} =
var s = newAsyncRawSocket() var s = newAsyncNativeSocket()
await s.connect(testHost, testPort) await s.connect(testHost, testPort)

View file

@ -7,7 +7,7 @@ discard """
import import
asyncdispatch, asyncdispatch,
asyncnet, asyncnet,
rawsockets, nativesockets,
os os
@ -21,7 +21,7 @@ when defined(windows) or defined(nimdoc):
quit("Error: unhandled exception: Connection reset by peer") quit("Error: unhandled exception: Connection reset by peer")
else: else:
proc createListenSocket(host: string, port: Port): TAsyncFD = proc createListenSocket(host: string, port: Port): TAsyncFD =
result = newAsyncRawSocket() result = newAsyncNativeSocket()
SocketHandle(result).setSockOptInt(SOL_SOCKET, SO_REUSEADDR, 1) SocketHandle(result).setSockOptInt(SOL_SOCKET, SO_REUSEADDR, 1)

View file

@ -2,4 +2,4 @@ discard """
cmd: "nim cpp $file" cmd: "nim cpp $file"
""" """
import rawsockets import nativesockets

View file

@ -1,6 +1,6 @@
import rawsockets, asyncdispatch, macros import nativesockets, asyncdispatch, macros
var p = newDispatcher() var p = newDispatcher()
var sock = newAsyncRawSocket() var sock = newAsyncNativeSocket()
proc convertReturns(node, retFutureSym: NimNode): NimNode {.compileTime.} = proc convertReturns(node, retFutureSym: NimNode): NimNode {.compileTime.} =
case node.kind case node.kind

View file

@ -5,7 +5,7 @@ discard """
import mexporta import mexporta
# bug #1029: # bug #1029:
from rawsockets import accept from nativesockets import accept
# B.TMyObject has been imported implicitly here: # B.TMyObject has been imported implicitly here:
var x: TMyObject var x: TMyObject

View file

@ -213,6 +213,8 @@ proc compilerOutputTests(test: TTest, given: var TSpec, expected: TSpec;
expectedmsg = expected.nimout expectedmsg = expected.nimout
givenmsg = given.nimout.strip givenmsg = given.nimout.strip
nimoutCheck(test, expectedmsg, given) nimoutCheck(test, expectedmsg, given)
else:
givenmsg = given.nimout.strip
if given.err == reSuccess: inc(r.passed) if given.err == reSuccess: inc(r.passed)
r.addResult(test, expectedmsg, givenmsg, given.err) r.addResult(test, expectedmsg, givenmsg, given.err)

View file

@ -9,6 +9,9 @@ News
Changes affecting backwards compatibility Changes affecting backwards compatibility
----------------------------------------- -----------------------------------------
- The ``rawsockets`` module has been renamed to ``nativesockets`` to avoid
confusion with TCP/IP raw sockets, so ``newNativeSocket`` should be used
instead of ``newRawSocket``.
- The ``miliseconds`` property of ``times.TimeInterval`` is now ``milliseconds``. - The ``miliseconds`` property of ``times.TimeInterval`` is now ``milliseconds``.
Code accessing that property is deprecated and code using ``miliseconds`` Code accessing that property is deprecated and code using ``miliseconds``
during object initialization or as a named parameter of ``initInterval()`` during object initialization or as a named parameter of ``initInterval()``