Merge remote-tracking branch 'origin/devel' into fix-test-failures

This commit is contained in:
Aman Gupta 2015-10-06 11:06:41 -07:00
commit eea8d604d0
41 changed files with 358 additions and 163 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

@ -747,6 +747,17 @@ proc genTupleElem(p: BProc, e: PNode, d: var TLoc) =
addf(r, ".Field$1", [rope(i)]) addf(r, ".Field$1", [rope(i)])
putIntoDest(p, d, ty.sons[i], r, a.s) 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) = proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
var a: TLoc var a: TLoc
var ty = genRecordFieldAux(p, e, d, a) 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)]) addf(r, ".Field$1", [rope(f.position)])
putIntoDest(p, d, f.typ, r, a.s) putIntoDest(p, d, f.typ, r, a.s)
else: else:
var field: PSym = nil let field = lookupFieldAgain(p, ty, f, r)
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 ")
if field.loc.r == nil: internalError(e.info, "genRecordField 3") if field.loc.r == nil: internalError(e.info, "genRecordField 3")
addf(r, ".$1", [field.loc.r]) addf(r, ".$1", [field.loc.r])
putIntoDest(p, d, field.typ, r, a.s) 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 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 var test, u, v: TLoc
for i in countup(1, sonsLen(e) - 1): for i in countup(1, sonsLen(e) - 1):
var it = e.sons[i] var it = e.sons[i]
@ -786,8 +790,12 @@ proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym) =
assert(disc.kind == nkSym) assert(disc.kind == nkSym)
initLoc(test, locNone, it.typ, OnStack) initLoc(test, locNone, it.typ, OnStack)
initLocExpr(p, it.sons[1], u) initLocExpr(p, it.sons[1], u)
initLoc(v, locExpr, disc.typ, OnUnknown) var o = obj
v.r = "$1.$2" % [obj, disc.sym.loc.r] 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) genInExprAux(p, it, u, v, test)
let id = nodeTableTestOrSet(p.module.dataCache, let id = nodeTableTestOrSet(p.module.dataCache,
newStrNode(nkStrLit, field.name.s), gBackendId) 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) = proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
if optFieldCheck in p.options: if optFieldCheck in p.options:
var var a: TLoc
a: TLoc let ty = genRecordFieldAux(p, e.sons[0], d, a)
f, field: PSym var r = rdLoc(a)
ty: PType let f = e.sons[0].sons[1].sym
r: Rope let field = lookupFieldAgain(p, ty, f, r)
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")
if field.loc.r == nil: if field.loc.r == nil:
internalError(e.info, "genCheckedRecordField") # generate the checks: 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)) add(r, rfmt(nil, ".$1", field.loc.r))
putIntoDest(p, d, field.typ, r, a.s) putIntoDest(p, d, field.typ, r, a.s)
else: else:
@ -1150,20 +1147,15 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
else: else:
constructLoc(p, tmp) constructLoc(p, tmp)
discard getTypeDesc(p.module, t) discard getTypeDesc(p.module, t)
let ty = getUniqueType(t)
for i in 1 .. <e.len: for i in 1 .. <e.len:
let it = e.sons[i] let it = e.sons[i]
var tmp2: TLoc var tmp2: TLoc
tmp2.r = r tmp2.r = r
var field: PSym = nil let field = lookupFieldAgain(p, ty, it.sons[0].sym, tmp2.r)
var ty = getUniqueType(t) if field.loc.r == nil: internalError(e.info, "genObjConstr")
while ty != nil:
field = lookupInRecord(ty.n, it.sons[0].sym.name)
if field != nil: break
if not p.module.compileToCpp: add(tmp2.r, ".Sup")
ty = getUniqueType(ty.sons[0])
if field == nil or field.loc.r == nil: internalError(e.info, "genObjConstr")
if it.len == 3 and optFieldCheck in p.options: if it.len == 3 and optFieldCheck in p.options:
genFieldCheck(p, it.sons[2], tmp2.r, field) genFieldCheck(p, it.sons[2], tmp2.r, field, ty)
add(tmp2.r, ".") add(tmp2.r, ".")
add(tmp2.r, field.loc.r) add(tmp2.r, field.loc.r)
tmp2.k = locTemp tmp2.k = locTemp

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

@ -123,6 +123,14 @@ proc containsOrIncl*(c: var CritBitTree[void], key: string): bool =
var n = rawInsert(c, key) var n = rawInsert(c, key)
result = c.count == oldCount 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) = proc incl*(c: var CritBitTree[void], key: string) =
## includes `key` in `c`. ## includes `key` in `c`.
discard rawInsert(c, key) discard rawInsert(c, key)

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,
protocol: Protocol = IPPROTO_TCP): SocketHandle = sockType: SockType = SOCK_STREAM,
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,7 +203,9 @@ 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)
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) var gaiResult = getaddrinfo(address, $port, addr(hints), result)
if gaiResult != 0'i32: if gaiResult != 0'i32:
when useWinVersion: when useWinVersion:
@ -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
result = newString(posix.INET6_ADDRSTRLEN) result = newString(posix.INET6_ADDRSTRLEN)
@ -368,7 +372,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.
@ -385,7 +389,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:
@ -401,7 +406,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")
@ -420,7 +425,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:
@ -436,7 +442,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

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

@ -173,6 +173,9 @@ proc clear*(s: StringTableRef, mode: StringTableMode) =
s.mode = mode s.mode = mode
s.counter = 0 s.counter = 0
s.data.setLen(startSize) s.data.setLen(startSize)
for i in 0..<s.data.len:
if not isNil(s.data[i].key):
s.data[i].key = nil
proc newStringTable*(keyValuePairs: varargs[string], proc newStringTable*(keyValuePairs: varargs[string],
mode: StringTableMode): StringTableRef {. mode: StringTableMode): StringTableRef {.
@ -248,3 +251,6 @@ when isMainModule:
x.mget("11") = "23" x.mget("11") = "23"
assert x["11"] == "23" assert x["11"] == "23"
x.clear(modeCaseInsensitive)
x["11"] = "22"
assert x["11"] == "22"

View file

@ -169,7 +169,8 @@ proc cmpIgnoreStyle*(a, b: string): int {.noSideEffect,
inc(j) 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".} = {.noSideEffect, rtl, extern: "nsuStrip".} =
## Strips `chars` from `s` and returns the resulting string. ## Strips `chars` from `s` and returns the resulting string.
## ##
@ -504,7 +505,8 @@ proc repeat*(c: char, count: Natural): string {.noSideEffect,
## ##
## .. code-block:: nim ## .. code-block:: nim
## proc tabexpand(indent: int, text: string, tabsize: int = 4) = ## 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(4, "At four")
## tabexpand(5, "At five") ## tabexpand(5, "At five")
@ -533,11 +535,13 @@ template spaces*(n: Natural): string = repeat(' ',n)
## echo text1 & spaces(max(0, width - text1.len)) & "|" ## echo text1 & spaces(max(0, width - text1.len)) & "|"
## echo text2 & spaces(max(0, width - text2.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() ## 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) ## deprecated: use repeat(string, count) or string.repeat(count)
repeat(s, count)
proc align*(s: string, count: Natural, padding = ' '): string {. proc align*(s: string, count: Natural, padding = ' '): string {.
noSideEffect, rtl, extern: "nsuAlignString".} = 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 if sub == s[i]: return i
return -1 return -1
proc count*(s: string, sub: string, overlapping: bool = false): int {.noSideEffect, proc count*(s: string, sub: string, overlapping: bool = false): int {.
rtl, extern: "nsuCountString".} = noSideEffect, rtl, extern: "nsuCountString".} =
## Count the occurrences of a substring `sub` in the string `s`. ## Count the occurrences of a substring `sub` in the string `s`.
## Overlapping occurrences of `sub` only count when `overlapping` ## Overlapping occurrences of `sub` only count when `overlapping`
## is set to true. ## is set to true.
@ -1449,7 +1453,8 @@ proc removeSuffix*(s: var string, chars: set[char] = Newlines) {.
s.setLen(last + 1) 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. ## Removes a single character (in-place) from a string.
## .. code-block:: nim ## .. code-block:: nim
## var ## var
@ -1515,7 +1520,8 @@ when isMainModule:
doAssert strip("sfoofoofoos", chars = {'s'}) == "foofoofoo" doAssert strip("sfoofoofoos", chars = {'s'}) == "foofoofoo"
doAssert strip("barfoofoofoobar", chars = {'b', 'a', 'r'}) == "foofoofoo" doAssert strip("barfoofoofoobar", chars = {'b', 'a', 'r'}) == "foofoofoo"
doAssert strip("stripme but don't strip this stripme", 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", leading = false, chars = {'s'}) == "sfoofoofoo"
doAssert strip("sfoofoofoos", trailing = false, chars = {'s'}) == "foofoofoos" doAssert strip("sfoofoofoos", trailing = false, chars = {'s'}) == "foofoofoos"

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

@ -18,7 +18,7 @@ const
type type
Handle* = int Handle* = int
LONG* = int32 LONG* = int32
ULONG* = int ULONG* = int32
PULONG* = ptr int PULONG* = ptr int
WINBOOL* = int32 WINBOOL* = int32
DWORD* = int32 DWORD* = int32

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

@ -0,0 +1,30 @@
discard """
output: "(kind: None)"
"""
when true:
# bug #2637
type
OptionKind = enum
None,
Some
Option*[T] = object
case kind: OptionKind
of None:
discard
of Some:
value*: T
proc none*[T](): Option[T] =
Option[T](kind: None)
proc none*(T: typedesc): Option[T] = none[T]()
proc test(): Option[int] =
int.none
echo test()

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

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