Merge branch 'devel' into faster-nimsuggest

This commit is contained in:
Andreas Rumpf
2017-02-17 10:48:01 +01:00
52 changed files with 1048 additions and 281 deletions

View File

@@ -7,10 +7,7 @@ cache:
# - i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z
matrix:
fast_finish: true # set this flag to immediately finish build once one of the jobs fails.
allow_failures:
- platform: x64
# - platform: x86
fast_finish: true
environment:
matrix:

View File

@@ -1541,8 +1541,7 @@ proc skipGenericOwner*(s: PSym): PSym =
## Generic instantiations are owned by their originating generic
## symbol. This proc skips such owners and goes straight to the owner
## of the generic itself (the module or the enclosing proc).
result = if s.kind in skProcKinds and {sfGenSym, sfFromGeneric} * s.flags ==
{sfFromGeneric}:
result = if s.kind in skProcKinds and sfFromGeneric in s.flags:
s.owner.owner
else:
s.owner

View File

@@ -388,6 +388,7 @@ proc debugTree(n: PNode, indent: int, maxRecDepth: int;
[istr, makeYamlString($n.kind)]
addf(result, ",$N$1\"info\": $2", [istr, lineInfoToStr(n.info)])
if maxRecDepth != 0:
addf(result, ",$N$1\"flags\": $2", [istr, rope($n.flags)])
case n.kind
of nkCharLit..nkUInt64Lit:
addf(result, ",$N$1\"intVal\": $2", [istr, rope(n.intVal)])

View File

@@ -220,7 +220,7 @@ proc genOptAsgnTuple(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
optAsgnLoc(src, t, field), newflags)
proc genOptAsgnObject(p: BProc, dest, src: TLoc, flags: TAssignmentFlags,
t: PNode) =
t: PNode, typ: PType) =
if t == nil: return
let newflags =
if src.s == OnStatic:
@@ -232,10 +232,11 @@ proc genOptAsgnObject(p: BProc, dest, src: TLoc, flags: TAssignmentFlags,
case t.kind
of nkSym:
let field = t.sym
if field.loc.r == nil: fillObjectFields(p.module, typ)
genAssignment(p, optAsgnLoc(dest, field.typ, field.loc.r),
optAsgnLoc(src, field.typ, field.loc.r), newflags)
of nkRecList:
for child in items(t): genOptAsgnObject(p, dest, src, newflags, child)
for child in items(t): genOptAsgnObject(p, dest, src, newflags, child, typ)
else: discard
proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
@@ -315,9 +316,9 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
genGenericAsgn(p, dest, src, flags)
elif needsComplexAssignment(ty):
if ty.sons[0].isNil and asgnComplexity(ty.n) <= 4:
discard getTypeDesc(p.module, dest.t)
discard getTypeDesc(p.module, ty)
internalAssert ty.n != nil
genOptAsgnObject(p, dest, src, flags, ty.n)
genOptAsgnObject(p, dest, src, flags, ty.n, ty)
else:
genGenericAsgn(p, dest, src, flags)
else:

View File

@@ -1103,8 +1103,8 @@ proc asgnFieldDiscriminant(p: BProc, e: PNode) =
genAssignment(p, a, tmp, {})
proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) =
genLineDir(p, e)
if e.sons[0].kind == nkSym and sfGoto in e.sons[0].sym.flags:
genLineDir(p, e)
genGotoVar(p, e.sons[1])
elif not fieldDiscriminantCheckNeeded(p, e):
var a: TLoc
@@ -1114,8 +1114,11 @@ proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) =
initLocExpr(p, e.sons[0], a)
if fastAsgn: incl(a.flags, lfNoDeepCopy)
assert(a.t != nil)
loadInto(p, e.sons[0], e.sons[1], a)
let ri = e.sons[1]
genLineDir(p, ri)
loadInto(p, e.sons[0], ri, a)
else:
genLineDir(p, e)
asgnFieldDiscriminant(p, e)
proc genStmts(p: BProc, t: PNode) =

View File

@@ -57,8 +57,8 @@ proc generateThreadLocalStorage(m: BModule) =
proc generateThreadVarsSize(m: BModule) =
if nimtv != nil:
let externc = if gCmd != cmdCompileToCpp and
sfCompileToCpp in m.module.flags: "extern \"C\""
let externc = if gCmd == cmdCompileToCpp or
sfCompileToCpp in m.module.flags: "extern \"C\" "
else: ""
addf(m.s[cfsProcs],
"$#NI NimThreadVarsSize(){return (NI)sizeof(NimThreadVars);}$n",

View File

@@ -715,10 +715,13 @@ proc genProcAux(m: BModule, prc: PSym) =
add(generatedProc, ~"}$N")
add(m.s[cfsProcs], generatedProc)
proc crossesCppBoundary(m: BModule; sym: PSym): bool {.inline.} =
result = sfCompileToCpp in m.module.flags and
proc requiresExternC(m: BModule; sym: PSym): bool {.inline.} =
result = (sfCompileToCpp in m.module.flags and
sfCompileToCpp notin sym.getModule().flags and
gCmd != cmdCompileToCpp
gCmd != cmdCompileToCpp) or (
sym.flags * {sfImportc, sfInfixCall, sfCompilerProc} == {sfImportc} and
sym.magic == mNone and
gCmd == cmdCompileToCpp)
proc genProcPrototype(m: BModule, sym: PSym) =
useHeader(m, sym)
@@ -732,7 +735,7 @@ proc genProcPrototype(m: BModule, sym: PSym) =
var header = genProcHeader(m, sym)
if sfNoReturn in sym.flags and hasDeclspec in extccomp.CC[cCompiler].props:
header = "__declspec(noreturn) " & header
if sym.typ.callConv != ccInline and crossesCppBoundary(m, sym):
if sym.typ.callConv != ccInline and requiresExternC(m, sym):
header = "extern \"C\" " & header
if sfPure in sym.flags and hasAttribute in CC[cCompiler].props:
header.add(" __attribute__((naked))")

View File

@@ -566,16 +566,18 @@ proc needsExeExt(): bool {.inline.} =
result = (optGenScript in gGlobalOptions and targetOS == osWindows) or
(platform.hostOS == osWindows)
proc getCompilerExe(compiler: TSystemCC): string =
result = if gCmd == cmdCompileToCpp: CC[compiler].cppCompiler
else: CC[compiler].compilerExe
proc getCompilerExe(compiler: TSystemCC; cfile: string): string =
result = if gCmd == cmdCompileToCpp and not cfile.endsWith(".c"):
CC[compiler].cppCompiler
else:
CC[compiler].compilerExe
if result.len == 0:
rawMessage(errCompilerDoesntSupportTarget, CC[compiler].name)
proc getLinkerExe(compiler: TSystemCC): string =
result = if CC[compiler].linkerExe.len > 0: CC[compiler].linkerExe
elif gMixedMode and gCmd != cmdCompileToCpp: CC[compiler].cppCompiler
else: compiler.getCompilerExe
else: compiler.getCompilerExe("")
proc getCompileCFileCmd*(cfile: Cfile): string =
var c = cCompiler
@@ -596,7 +598,7 @@ proc getCompileCFileCmd*(cfile: Cfile): string =
var options = cFileSpecificOptions(cfile.cname)
var exe = getConfigVar(c, ".exe")
if exe.len == 0: exe = c.getCompilerExe
if exe.len == 0: exe = c.getCompilerExe(cfile.cname)
if needsExeExt(): exe = addFileExt(exe, "exe")
if optGenDynLib in gGlobalOptions and
@@ -614,7 +616,7 @@ proc getCompileCFileCmd*(cfile: Cfile): string =
compilePattern = joinPath(ccompilerpath, exe)
else:
includeCmd = ""
compilePattern = c.getCompilerExe
compilePattern = c.getCompilerExe(cfile.cname)
var cf = if noAbsolutePaths(): extractFilename(cfile.cname)
else: cfile.cname

View File

@@ -178,6 +178,11 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
if result.kind != kind:
localError(n.info, "cannot use symbol of kind '" &
$result.kind & "' as a '" & $kind & "'")
if sfGenSym in result.flags and result.kind notin {skTemplate, skMacro, skParam}:
# declarative context, so produce a fresh gensym:
result = copySym(result)
result.ast = n.sym.ast
put(c.p, n.sym, result)
# when there is a nested proc inside a template, semtmpl
# will assign a wrong owner during the first pass over the
# template; we must fix it here: see #909

View File

@@ -39,6 +39,7 @@ type
next*: PProcCon # used for stacking procedure contexts
wasForwarded*: bool # whether the current proc has a separate header
bracketExpr*: PNode # current bracket expression (for ^ support)
mapping*: TIdTable
TInstantiationPair* = object
genericSym*: PSym
@@ -147,6 +148,35 @@ proc lastOptionEntry*(c: PContext): POptionEntry =
proc popProcCon*(c: PContext) {.inline.} = c.p = c.p.next
proc put*(p: PProcCon; key, val: PSym) =
if p.mapping.data == nil: initIdTable(p.mapping)
#echo "put into table ", key.info
p.mapping.idTablePut(key, val)
proc get*(p: PProcCon; key: PSym): PSym =
if p.mapping.data == nil: return nil
result = PSym(p.mapping.idTableGet(key))
proc getGenSym*(c: PContext; s: PSym): PSym =
if sfGenSym notin s.flags: return s
var it = c.p
while it != nil:
result = get(it, s)
if result != nil:
#echo "got from table ", result.name.s, " ", result.info
return result
it = it.next
result = s
proc considerGenSyms*(c: PContext; n: PNode) =
if n.kind == nkSym:
let s = getGenSym(c, n.sym)
if n.sym != s:
n.sym = s
else:
for i in 0..<n.safeLen:
considerGenSyms(c, n.sons[i])
proc newOptionEntry*(): POptionEntry =
new(result)
result.options = gOptions

View File

@@ -922,7 +922,8 @@ proc readTypeParameter(c: PContext, typ: PType,
return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info)
#echo "came here: returned nil"
proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
let s = getGenSym(c, sym)
case s.kind
of skConst:
markUsed(n.info, s)
@@ -1093,11 +1094,11 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
return readTypeParameter(c, ty, i, n.info)
of tyObject, tyTuple:
if ty.n != nil and ty.n.kind == nkRecList:
for field in ty.n:
if field.sym.name == i:
n.typ = newTypeWithSons(c, tyFieldAccessor, @[ty, field.sym.typ])
n.typ.n = copyTree(n)
return n
let field = lookupInRecord(ty.n, i)
if field != nil:
n.typ = newTypeWithSons(c, tyFieldAccessor, @[ty, field.typ])
n.typ.n = copyTree(n)
return n
else:
# echo "TYPE FIELD ACCESS"
# debug ty

View File

@@ -628,7 +628,10 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
of {skProc, skMethod}:
result = n
of skType:
result = newSymNodeTypeDesc(s, n.info)
# XXX gensym'ed symbols can come here and cannot be resolved. This is
# dirty, but correct.
if s.typ != nil:
result = newSymNodeTypeDesc(s, n.info)
of skGenericParam:
if s.typ.kind == tyStatic:
if s.typ.n != nil:
@@ -656,7 +659,7 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
localError(a.info, errCannotEvalXBecauseIncompletelyDefined,
"sizeof")
result = nil
elif skipTypes(a.typ, typedescInst).kind in
elif skipTypes(a.typ, typedescInst+{tyRange}).kind in
IntegralTypes+NilableTypes+{tySet}:
#{tyArray,tyObject,tyTuple}:
result = newIntNodeT(getSize(a.typ), n)

View File

@@ -106,15 +106,18 @@ proc freshGenSyms(n: PNode, owner, orig: PSym, symMap: var TIdTable) =
#if n.kind == nkSym and sfGenSym in n.sym.flags:
# if n.sym.owner != orig:
# echo "symbol ", n.sym.name.s, " orig ", orig, " owner ", n.sym.owner
if n.kind == nkSym and {sfGenSym, sfFromGeneric} * n.sym.flags == {sfGenSym}: # and
if n.kind == nkSym and sfGenSym in n.sym.flags: # and
# (n.sym.owner == orig or n.sym.owner.kind in {skPackage}):
let s = n.sym
var x = PSym(idTableGet(symMap, s))
if x == nil:
if x != nil:
n.sym = x
elif s.owner.kind == skPackage:
#echo "copied this ", s.name.s
x = copySym(s, false)
x.owner = owner
idTablePut(symMap, s, x)
n.sym = x
n.sym = x
else:
for i in 0 .. <safeLen(n): freshGenSyms(n.sons[i], owner, orig, symMap)

View File

@@ -1360,6 +1360,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
proc determineType(c: PContext, s: PSym) =
if s.typ != nil: return
#if s.magic != mNone: return
#if s.ast.isNil: return
discard semProcAux(c, s.ast, s.kind, {}, stepDetermineType)
proc semIterator(c: PContext, n: PNode): PNode =

View File

@@ -172,7 +172,7 @@ proc newGenSym(kind: TSymKind, n: PNode, c: var TemplCtx): PSym =
result = newSym(kind, considerQuotedIdent(n), c.owner, n.info)
incl(result.flags, sfGenSym)
incl(result.flags, sfShadowed)
if c.scopeN == 0: incl(result.flags, sfFromGeneric)
#if c.scopeN == 0: incl(result.flags, sfFromGeneric)
proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
# locals default to 'gensym':

View File

@@ -297,7 +297,7 @@ proc semOrdinal(c: PContext, n: PNode, prev: PType): PType =
proc semTypeIdent(c: PContext, n: PNode): PSym =
if n.kind == nkSym:
result = n.sym
result = getGenSym(c, n.sym)
else:
when defined(nimfix):
result = pickSym(c, n, skType)
@@ -1319,8 +1319,9 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
prev.id = s.typ.id
result = prev
of nkSym:
if n.sym.kind == skType and n.sym.typ != nil:
var t = n.sym.typ
let s = getGenSym(c, n.sym)
if s.kind == skType and s.typ != nil:
var t = s.typ
let alias = maybeAliasType(c, t, prev)
if alias != nil:
result = alias
@@ -1332,7 +1333,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
markUsed(n.info, n.sym)
styleCheckUse(n.info, n.sym)
else:
if n.sym.kind != skError: localError(n.info, errTypeExpected)
if s.kind != skError: localError(n.info, errTypeExpected)
result = newOrPrevType(tyError, prev, c)
of nkObjectTy: result = semObjectNode(c, n, prev)
of nkTupleTy: result = semTuple(c, n, prev)

View File

@@ -1583,12 +1583,14 @@ proc prepareOperand(c: PContext; formal: PType; a: PNode): PNode =
result = c.semOperand(c, a, flags)
else:
result = a
considerGenSyms(c, result)
proc prepareOperand(c: PContext; a: PNode): PNode =
if a.typ.isNil:
result = c.semOperand(c, a, {efDetermineType})
else:
result = a
considerGenSyms(c, result)
proc prepareNamedParam(a: PNode) =
if a.sons[0].kind != nkIdent:

View File

@@ -869,7 +869,12 @@ proc transform(c: PTransf, n: PNode): PTransNode =
else:
result = transformSons(c, n)
of nkIdentDefs, nkConstDef:
result = transformSons(c, n)
when true:
result = transformSons(c, n)
else:
result = n.PTransNode
let L = n.len-1
result[L] = transform(c, n.sons[L])
# XXX comment handling really sucks:
if importantComments():
PNode(result).comment = n.comment

View File

@@ -38,7 +38,7 @@ proc exprStructuralEquivalent*(a, b: PNode; strictSymEquality=false): bool =
# don't go nuts here: same symbol as string is enough:
result = a.sym.name.id == b.sym.name.id
of nkIdent: result = a.ident.id == b.ident.id
of nkCharLit..nkInt64Lit: result = a.intVal == b.intVal
of nkCharLit..nkUInt64Lit: result = a.intVal == b.intVal
of nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal
of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
of nkEmpty, nkNilLit, nkType: result = true

View File

@@ -461,3 +461,11 @@ can then attach a GC to this thread via
It is **not** safe to disable the garbage collector and enable it after the
call from your background thread even if the code you are calling is short
lived.
Before the thread exits, you should tear down the thread's GC to prevent memory
leaks by calling
.. code-block:: nim
system.tearDownForeignThreadGc()

View File

@@ -361,7 +361,7 @@ iterator:
.. code-block:: nim
echo "Counting to ten: "
for i in countup(1, 10):
echo $i
echo i
# --> Outputs 1 2 3 4 5 6 7 8 9 10 on different lines
The built-in `$ <system.html#$>`_ operator turns an integer (``int``) and many
@@ -374,7 +374,7 @@ Each value is ``echo``-ed. This code does the same:
echo "Counting to 10: "
var i = 1
while i <= 10:
echo $i
echo i
inc(i) # increment i by 1
# --> Outputs 1 2 3 4 5 6 7 8 9 10 on different lines
@@ -383,7 +383,7 @@ Counting down can be achieved as easily (but is less often needed):
.. code-block:: nim
echo "Counting down from 10 to 1: "
for i in countdown(10, 1):
echo $i
echo i
# --> Outputs 10 9 8 7 6 5 4 3 2 1 on different lines
Since counting up occurs so often in programs, Nim also has a `..
@@ -827,7 +827,7 @@ Let's return to the boring counting example:
.. code-block:: nim
echo "Counting to ten: "
for i in countup(1, 10):
echo $i
echo i
Can a `countup <system.html#countup>`_ proc be written that supports this
loop? Lets try:
@@ -1035,15 +1035,15 @@ there is a difference between the ``$`` and ``repr`` outputs:
myString = "nim"
myInteger = 42
myFloat = 3.14
echo $myBool, ":", repr(myBool)
echo myBool, ":", repr(myBool)
# --> true:true
echo $myCharacter, ":", repr(myCharacter)
echo myCharacter, ":", repr(myCharacter)
# --> n:'n'
echo $myString, ":", repr(myString)
echo myString, ":", repr(myString)
# --> nim:0x10fa8c050"nim"
echo $myInteger, ":", repr(myInteger)
echo myInteger, ":", repr(myInteger)
# --> 42:42
echo $myFloat, ":", repr(myFloat)
echo myFloat, ":", repr(myFloat)
# --> 3.1400000000000001e+00:3.1400000000000001e+00
@@ -1075,7 +1075,7 @@ at runtime by 0, the second by 1 and so on. Example:
north, east, south, west
var x = south # `x` is of type `Direction`; its value is `south`
echo $x # writes "south" to `stdout`
echo x # writes "south" to `stdout`
All comparison operators can be used with enumeration types.
@@ -1289,7 +1289,7 @@ value. Here the ``for`` statement is looping over the results from the
.. code-block:: nim
for i in @[3, 4, 5]:
echo $i
echo i
# --> 3
# --> 4
# --> 5

View File

@@ -223,8 +223,9 @@ proc bundleWinTools() =
copyExe("tools/finish".exe, "finish".exe)
removeFile("tools/finish".exe)
nimexec("c -o:bin/vccexe.exe tools/vccenv/vccexe")
nimexec(r"c --cc:vcc --app:gui -o:bin\downloader.exe -d:ssl --noNimblePath " &
r"--path:..\ui tools\downloader.nim")
when false:
nimexec(r"c --cc:vcc --app:gui -o:bin\downloader.exe -d:ssl --noNimblePath " &
r"--path:..\ui tools\downloader.nim")
proc zip(args: string) =
bundleNimbleSrc()

View File

@@ -69,16 +69,14 @@ import db_common
export db_common
type
DbConn* = PPGconn ## encapsulates a database connection
Row* = seq[string] ## a row of a dataset. NULL database values will be
## converted to nil.
InstantRow* = tuple[res: PPGresult, line: int32] ## a handle that can be
## used to get a row's
## column text on demand
DbConn* = PPGconn ## encapsulates a database connection
Row* = seq[string] ## a row of a dataset. NULL database values will be
## converted to nil.
InstantRow* = object ## a handle that can be
res: PPGresult ## used to get a row's
line: int ## column text on demand
SqlPrepared* = distinct string ## a identifier for the prepared queries
{.deprecated: [TRow: Row, TDbConn: DbConn,
TSqlPrepared: SqlPrepared].}
{.deprecated: [TRow: Row, TDbConn: DbConn, TSqlPrepared: SqlPrepared].}
proc dbError*(db: DbConn) {.noreturn.} =
## raises a DbError exception.
@@ -213,7 +211,7 @@ iterator instantRows*(db: DbConn, query: SqlQuery,
## on demand using []. Returned handle is valid only within iterator body.
var res = setupQuery(db, query, args)
for i in 0..pqNtuples(res)-1:
yield (res: res, line: i)
yield InstantRow(res: res, line: i)
pqClear(res)
iterator instantRows*(db: DbConn, stmtName: SqlPrepared,
@@ -223,16 +221,170 @@ iterator instantRows*(db: DbConn, stmtName: SqlPrepared,
## on demand using []. Returned handle is valid only within iterator body.
var res = setupQuery(db, stmtName, args)
for i in 0..pqNtuples(res)-1:
yield (res: res, line: i)
yield InstantRow(res: res, line: i)
pqClear(res)
proc `[]`*(row: InstantRow, col: int32): string {.inline.} =
## returns text for given column of the row
$pqgetvalue(row.res, row.line, col)
proc getColumnType(res: PPGresult, col: int) : DbType =
## returns DbType for given column in the row
## defined in pg_type.h file in the postgres source code
## Wire representation for types: http://www.npgsql.org/dev/types.html
var oid = pqftype(res, int32(col))
## The integer returned is the internal OID number of the type
case oid
of 16: return DbType(kind: DbTypeKind.dbBool, name: "bool")
of 17: return DbType(kind: DbTypeKind.dbBlob, name: "bytea")
proc len*(row: InstantRow): int32 {.inline.} =
of 21: return DbType(kind: DbTypeKind.dbInt, name: "int2", size: 2)
of 23: return DbType(kind: DbTypeKind.dbInt, name: "int4", size: 4)
of 20: return DbType(kind: DbTypeKind.dbInt, name: "int8", size: 8)
of 1560: return DbType(kind: DbTypeKind.dbBit, name: "bit")
of 1562: return DbType(kind: DbTypeKind.dbInt, name: "varbit")
of 18: return DbType(kind: DbTypeKind.dbFixedChar, name: "char")
of 19: return DbType(kind: DbTypeKind.dbFixedChar, name: "name")
of 1042: return DbType(kind: DbTypeKind.dbFixedChar, name: "bpchar")
of 25: return DbType(kind: DbTypeKind.dbVarchar, name: "text")
of 1043: return DbType(kind: DbTypeKind.dbVarChar, name: "varchar")
of 2275: return DbType(kind: DbTypeKind.dbVarchar, name: "cstring")
of 700: return DbType(kind: DbTypeKind.dbFloat, name: "float4")
of 701: return DbType(kind: DbTypeKind.dbFloat, name: "float8")
of 790: return DbType(kind: DbTypeKind.dbDecimal, name: "money")
of 1700: return DbType(kind: DbTypeKind.dbDecimal, name: "numeric")
of 704: return DbType(kind: DbTypeKind.dbTimeInterval, name: "tinterval")
of 702: return DbType(kind: DbTypeKind.dbTimestamp, name: "abstime")
of 703: return DbType(kind: DbTypeKind.dbTimeInterval, name: "reltime")
of 1082: return DbType(kind: DbTypeKind.dbDate, name: "date")
of 1083: return DbType(kind: DbTypeKind.dbTime, name: "time")
of 1114: return DbType(kind: DbTypeKind.dbTimestamp, name: "timestamp")
of 1184: return DbType(kind: DbTypeKind.dbTimestamp, name: "timestamptz")
of 1186: return DbType(kind: DbTypeKind.dbTimeInterval, name: "interval")
of 1266: return DbType(kind: DbTypeKind.dbTime, name: "timetz")
of 114: return DbType(kind: DbTypeKind.dbJson, name: "json")
of 142: return DbType(kind: DbTypeKind.dbXml, name: "xml")
of 3802: return DbType(kind: DbTypeKind.dbJson, name: "jsonb")
of 600: return DbType(kind: DbTypeKind.dbPoint, name: "point")
of 601: return DbType(kind: DbTypeKind.dbLseg, name: "lseg")
of 602: return DbType(kind: DbTypeKind.dbPath, name: "path")
of 603: return DbType(kind: DbTypeKind.dbBox, name: "box")
of 604: return DbType(kind: DbTypeKind.dbPolygon, name: "polygon")
of 628: return DbType(kind: DbTypeKind.dbLine, name: "line")
of 718: return DbType(kind: DbTypeKind.dbCircle, name: "circle")
of 650: return DbType(kind: DbTypeKind.dbInet, name: "cidr")
of 829: return DbType(kind: DbTypeKind.dbMacAddress, name: "macaddr")
of 869: return DbType(kind: DbTypeKind.dbInet, name: "inet")
of 2950: return DbType(kind: DbTypeKind.dbVarchar, name: "uuid")
of 3614: return DbType(kind: DbTypeKind.dbVarchar, name: "tsvector")
of 3615: return DbType(kind: DbTypeKind.dbVarchar, name: "tsquery")
of 2970: return DbType(kind: DbTypeKind.dbVarchar, name: "txid_snapshot")
of 27: return DbType(kind: DbTypeKind.dbComposite, name: "tid")
of 1790: return DbType(kind: DbTypeKind.dbComposite, name: "refcursor")
of 2249: return DbType(kind: DbTypeKind.dbComposite, name: "record")
of 3904: return DbType(kind: DbTypeKind.dbComposite, name: "int4range")
of 3906: return DbType(kind: DbTypeKind.dbComposite, name: "numrange")
of 3908: return DbType(kind: DbTypeKind.dbComposite, name: "tsrange")
of 3910: return DbType(kind: DbTypeKind.dbComposite, name: "tstzrange")
of 3912: return DbType(kind: DbTypeKind.dbComposite, name: "daterange")
of 3926: return DbType(kind: DbTypeKind.dbComposite, name: "int8range")
of 22: return DbType(kind: DbTypeKind.dbArray, name: "int2vector")
of 30: return DbType(kind: DbTypeKind.dbArray, name: "oidvector")
of 143: return DbType(kind: DbTypeKind.dbArray, name: "xml[]")
of 199: return DbType(kind: DbTypeKind.dbArray, name: "json[]")
of 629: return DbType(kind: DbTypeKind.dbArray, name: "line[]")
of 651: return DbType(kind: DbTypeKind.dbArray, name: "cidr[]")
of 719: return DbType(kind: DbTypeKind.dbArray, name: "circle[]")
of 791: return DbType(kind: DbTypeKind.dbArray, name: "money[]")
of 1000: return DbType(kind: DbTypeKind.dbArray, name: "bool[]")
of 1001: return DbType(kind: DbTypeKind.dbArray, name: "bytea[]")
of 1002: return DbType(kind: DbTypeKind.dbArray, name: "char[]")
of 1003: return DbType(kind: DbTypeKind.dbArray, name: "name[]")
of 1005: return DbType(kind: DbTypeKind.dbArray, name: "int2[]")
of 1006: return DbType(kind: DbTypeKind.dbArray, name: "int2vector[]")
of 1007: return DbType(kind: DbTypeKind.dbArray, name: "int4[]")
of 1008: return DbType(kind: DbTypeKind.dbArray, name: "regproc[]")
of 1009: return DbType(kind: DbTypeKind.dbArray, name: "text[]")
of 1028: return DbType(kind: DbTypeKind.dbArray, name: "oid[]")
of 1010: return DbType(kind: DbTypeKind.dbArray, name: "tid[]")
of 1011: return DbType(kind: DbTypeKind.dbArray, name: "xid[]")
of 1012: return DbType(kind: DbTypeKind.dbArray, name: "cid[]")
of 1013: return DbType(kind: DbTypeKind.dbArray, name: "oidvector[]")
of 1014: return DbType(kind: DbTypeKind.dbArray, name: "bpchar[]")
of 1015: return DbType(kind: DbTypeKind.dbArray, name: "varchar[]")
of 1016: return DbType(kind: DbTypeKind.dbArray, name: "int8[]")
of 1017: return DbType(kind: DbTypeKind.dbArray, name: "point[]")
of 1018: return DbType(kind: DbTypeKind.dbArray, name: "lseg[]")
of 1019: return DbType(kind: DbTypeKind.dbArray, name: "path[]")
of 1020: return DbType(kind: DbTypeKind.dbArray, name: "box[]")
of 1021: return DbType(kind: DbTypeKind.dbArray, name: "float4[]")
of 1022: return DbType(kind: DbTypeKind.dbArray, name: "float8[]")
of 1023: return DbType(kind: DbTypeKind.dbArray, name: "abstime[]")
of 1024: return DbType(kind: DbTypeKind.dbArray, name: "reltime[]")
of 1025: return DbType(kind: DbTypeKind.dbArray, name: "tinterval[]")
of 1027: return DbType(kind: DbTypeKind.dbArray, name: "polygon[]")
of 1040: return DbType(kind: DbTypeKind.dbArray, name: "macaddr[]")
of 1041: return DbType(kind: DbTypeKind.dbArray, name: "inet[]")
of 1263: return DbType(kind: DbTypeKind.dbArray, name: "cstring[]")
of 1115: return DbType(kind: DbTypeKind.dbArray, name: "timestamp[]")
of 1182: return DbType(kind: DbTypeKind.dbArray, name: "date[]")
of 1183: return DbType(kind: DbTypeKind.dbArray, name: "time[]")
of 1185: return DbType(kind: DbTypeKind.dbArray, name: "timestamptz[]")
of 1187: return DbType(kind: DbTypeKind.dbArray, name: "interval[]")
of 1231: return DbType(kind: DbTypeKind.dbArray, name: "numeric[]")
of 1270: return DbType(kind: DbTypeKind.dbArray, name: "timetz[]")
of 1561: return DbType(kind: DbTypeKind.dbArray, name: "bit[]")
of 1563: return DbType(kind: DbTypeKind.dbArray, name: "varbit[]")
of 2201: return DbType(kind: DbTypeKind.dbArray, name: "refcursor[]")
of 2951: return DbType(kind: DbTypeKind.dbArray, name: "uuid[]")
of 3643: return DbType(kind: DbTypeKind.dbArray, name: "tsvector[]")
of 3645: return DbType(kind: DbTypeKind.dbArray, name: "tsquery[]")
of 3807: return DbType(kind: DbTypeKind.dbArray, name: "jsonb[]")
of 2949: return DbType(kind: DbTypeKind.dbArray, name: "txid_snapshot[]")
of 3905: return DbType(kind: DbTypeKind.dbArray, name: "int4range[]")
of 3907: return DbType(kind: DbTypeKind.dbArray, name: "numrange[]")
of 3909: return DbType(kind: DbTypeKind.dbArray, name: "tsrange[]")
of 3911: return DbType(kind: DbTypeKind.dbArray, name: "tstzrange[]")
of 3913: return DbType(kind: DbTypeKind.dbArray, name: "daterange[]")
of 3927: return DbType(kind: DbTypeKind.dbArray, name: "int8range[]")
of 2287: return DbType(kind: DbTypeKind.dbArray, name: "record[]")
of 705: return DbType(kind: DbTypeKind.dbUnknown, name: "unknown")
else: return DbType(kind: DbTypeKind.dbUnknown, name: $oid) ## Query the system table pg_type to determine exactly which type is referenced.
proc setColumnInfo(columns: var DbColumns; res: PPGresult; L: int32) =
setLen(columns, L)
for i in 0..<L:
columns[i].name = $pqfname(res, i)
columns[i].typ = getColumnType(res, i)
columns[i].tableName = $(pqftable(res, i)) ## Returns the OID of the table from which the given column was fetched.
## Query the system table pg_class to determine exactly which table is referenced.
#columns[i].primaryKey = libpq does not have a function for that
#columns[i].foreignKey = libpq does not have a function for that
iterator instantRows*(db: DbConn; columns: var DbColumns; query: SqlQuery;
args: varargs[string, `$`]): InstantRow
{.tags: [ReadDbEffect].} =
var res = setupQuery(db, query, args)
setColumnInfo(columns, res, pqnfields(res))
for i in 0..<pqntuples(res):
yield InstantRow(res: res, line: i)
pqClear(res)
proc `[]`*(row: InstantRow; col: int): string {.inline.} =
## returns text for given column of the row
$pqgetvalue(row.res, int32(row.line), int32(col))
proc len*(row: InstantRow): int {.inline.} =
## returns number of columns in the row
pqNfields(row.res)
int(pqNfields(row.res))
proc getRow*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =

View File

@@ -290,7 +290,7 @@ proc find*(buf: cstring, pattern: Regex, matches: var openArray[string],
for i in 1..int(res)-1:
var a = rawMatches[i * 2]
var b = rawMatches[i * 2 + 1]
if a >= 0'i32: matches[i-1] = bufSubstr(buf, int(a), int(b)-1)
if a >= 0'i32: matches[i-1] = bufSubstr(buf, int(a), int(b))
else: matches[i-1] = nil
return rawMatches[0]

View File

@@ -46,7 +46,7 @@ proc reverse*[T](a: var openArray[T], first, last: Natural) =
proc reverse*[T](a: var openArray[T]) =
## reverses the array `a`.
reverse(a, 0, a.high)
reverse(a, 0, max(0, a.high))
proc reversed*[T](a: openArray[T], first: Natural, last: int): seq[T] =
## returns the reverse of the array `a[first..last]`.

View File

@@ -77,8 +77,10 @@ proc pop*[T](heap: var HeapQueue[T]): T =
proc del*[T](heap: var HeapQueue[T], index: int) =
## Removes element at `index`, maintaining the heap invariant.
swap(seq[T](heap)[^1], seq[T](heap)[index])
seq[T](heap).setLen(heap.len - 1)
heap.siftup(index)
let newLen = heap.len - 1
seq[T](heap).setLen(newLen)
if index < newLen:
heap.siftup(index)
proc replace*[T](heap: var HeapQueue[T], item: T): T =
## Pop and return the current smallest value, and add the new item.
@@ -101,16 +103,19 @@ proc pushpop*[T](heap: var HeapQueue[T], item: T): T =
return item
when isMainModule:
proc toSortedSeq[T](h: HeapQueue[T]): seq[T] =
var tmp = h
result = @[]
while tmp.len > 0:
result.add(pop(tmp))
block: # Simple sanity test
var heap = newHeapQueue[int]()
let data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0]
for item in data:
push(heap, item)
doAssert(heap[0] == 0)
var sort = newSeq[int]()
while heap.len > 0:
sort.add(pop(heap))
doAssert(sort == @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
doAssert(heap.toSortedSeq == @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
block: # Test del
var heap = newHeapQueue[int]()
@@ -121,11 +126,27 @@ when isMainModule:
doAssert(heap[0] == 1)
heap.del(seq[int](heap).find(7))
heap.del(seq[int](heap).find(5))
heap.del(seq[int](heap).find(6))
heap.del(seq[int](heap).find(2))
doAssert(heap.toSortedSeq == @[1, 2, 3, 4, 5, 6, 8, 9])
var sort = newSeq[int]()
while heap.len > 0:
sort.add(pop(heap))
doAssert(sort == @[1, 3, 4, 8, 9])
heap.del(seq[int](heap).find(5))
doAssert(heap.toSortedSeq == @[1, 2, 3, 4, 6, 8, 9])
heap.del(seq[int](heap).find(6))
doAssert(heap.toSortedSeq == @[1, 2, 3, 4, 8, 9])
heap.del(seq[int](heap).find(2))
doAssert(heap.toSortedSeq == @[1, 3, 4, 8, 9])
block: # Test del last
var heap = newHeapQueue[int]()
let data = [1, 2, 3]
for item in data: push(heap, item)
heap.del(2)
doAssert(heap.toSortedSeq == @[1, 2])
heap.del(1)
doAssert(heap.toSortedSeq == @[1])
heap.del(0)
doAssert(heap.toSortedSeq == @[])

View File

@@ -225,7 +225,7 @@ proc foreignDepInstallCmd*(foreignPackageName: string): (string, bool) =
else:
result = ("<your package manager here> install " & p, true)
else:
result = ("brew install " & p, true)
result = ("brew install " & p, false)
proc foreignDep*(foreignPackageName: string) =
## Registers 'foreignPackageName' to the internal list of foreign deps.

View File

@@ -127,6 +127,15 @@ proc hash*(x: string): Hash =
h = h !& ord(x[i])
result = !$h
proc hash*(x: cstring): Hash =
## efficient hashing of null-terminated strings
var h: Hash = 0
var i = 0
while x[i] != 0.char:
h = h !& ord(x[i])
inc i
result = !$h
proc hash*(sBuf: string, sPos, ePos: int): Hash =
## efficient hashing of a string buffer, from starting
## position `sPos` to ending position `ePos`
@@ -239,6 +248,7 @@ proc hash*[A](x: set[A]): Hash =
when isMainModule:
doAssert( hash("aa bb aaaa1234") == hash("aa bb aaaa1234", 0, 13) )
doAssert( hash("aa bb aaaa1234") == hash(cstring("aa bb aaaa1234")) )
doAssert( hashIgnoreCase("aa bb aaaa1234") == hash("aa bb aaaa1234") )
doAssert( hashIgnoreStyle("aa bb aaaa1234") == hashIgnoreCase("aa bb aaaa1234") )
let xx = @['H','e','l','l','o']

View File

@@ -206,6 +206,8 @@ proc parseHeader*(line: string): tuple[key: string, value: seq[string]] =
inc(i) # skip :
if i < len(line):
i += parseList(line, result.value, i)
elif result.key.len > 0:
result.value = @[""]
else:
result.value = @[]
@@ -318,4 +320,6 @@ when isMainModule:
let (key, value) = parseHeader("foobar: ")
test = newHttpHeaders()
test[key] = value
doAssert test["foobar"] == ""
doAssert test["foobar"] == ""
doAssert parseHeader("foobar:") == ("foobar", @[""])

View File

@@ -1002,8 +1002,8 @@ iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path:
iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string {.
tags: [ReadDirEffect].} =
## walks over the directory `dir` and yields for each file in `dir`. The
## full path for each file is returned.
## Recursively walks over the directory `dir` and yields for each file in `dir`.
## The full path for each file is returned. Directories are not returned.
## **Warning**:
## Modifying the directory structure while the iterator
## is traversing may result in undefined behavior!

View File

@@ -250,18 +250,18 @@ proc parseInt*(s: string, number: var int, start = 0): int {.
elif result != 0:
number = int(res)
# overflowChecks doesn't work with uint64
proc rawParseUInt(s: string, b: var uint64, start = 0): int =
# overflowChecks doesn't work with BiggestUInt
proc rawParseUInt(s: string, b: var BiggestUInt, start = 0): int =
var
res = 0'u64
prev = 0'u64
res = 0.BiggestUInt
prev = 0.BiggestUInt
i = start
if s[i] == '+': inc(i) # Allow
if s[i] in {'0'..'9'}:
b = 0
while s[i] in {'0'..'9'}:
prev = res
res = res * 10 + (ord(s[i]) - ord('0')).uint64
res = res * 10 + (ord(s[i]) - ord('0')).BiggestUInt
if prev > res:
return 0 # overflowChecks emulation
inc(i)
@@ -269,13 +269,13 @@ proc rawParseUInt(s: string, b: var uint64, start = 0): int =
b = res
result = i - start
proc parseBiggestUInt*(s: string, number: var uint64, start = 0): int {.
proc parseBiggestUInt*(s: string, number: var BiggestUInt, start = 0): int {.
rtl, extern: "npuParseBiggestUInt", noSideEffect.} =
## parses an unsigned integer starting at `start` and stores the value
## into `number`.
## Result is the number of processed chars or 0 if there is no integer
## or overflow detected.
var res: uint64
var res: BiggestUInt
# use 'res' for exception safety (don't write to 'number' in case of an
# overflow exception):
result = rawParseUInt(s, res, start)
@@ -287,12 +287,12 @@ proc parseUInt*(s: string, number: var uint, start = 0): int {.
## into `number`.
## Result is the number of processed chars or 0 if there is no integer or
## overflow detected.
var res: uint64
var res: BiggestUInt
result = parseBiggestUInt(s, res, start)
if (sizeof(uint) <= 4) and
(res > 0xFFFF_FFFF'u64):
raise newException(OverflowError, "overflow")
elif result != 0:
when sizeof(BiggestUInt) > sizeof(uint) and sizeof(uint) <= 4:
if res > 0xFFFF_FFFF'u64:
raise newException(OverflowError, "overflow")
if result != 0:
number = uint(res)
proc parseBiggestFloat*(s: string, number: var BiggestFloat, start = 0): int {.

View File

@@ -939,7 +939,7 @@ proc parseUInt*(s: string): uint {.noSideEffect, procvar,
if L != s.len or L == 0:
raise newException(ValueError, "invalid unsigned integer: " & s)
proc parseBiggestUInt*(s: string): uint64 {.noSideEffect, procvar,
proc parseBiggestUInt*(s: string): BiggestUInt {.noSideEffect, procvar,
rtl, extern: "nsuParseBiggestUInt".} =
## Parses a decimal unsigned integer value contained in `s`.
##

View File

@@ -1512,6 +1512,17 @@ type
## compiler supports. Currently this is ``float64``, but it is
## platform-dependant in general.
when defined(JS):
type BiggestUInt* = uint32
## is an alias for the biggest unsigned integer type the Nim compiler
## supports. Currently this is ``uint32`` for JS and ``uint64`` for other
## targets.
else:
type BiggestUInt* = uint64
## is an alias for the biggest unsigned integer type the Nim compiler
## supports. Currently this is ``uint32`` for JS and ``uint64`` for other
## targets.
{.deprecated: [TAddress: ByteAddress].}
when defined(windows):

View File

@@ -128,13 +128,7 @@ iterator items(stack: ptr GcStack): ptr GcStack =
yield s
s = s.next
# There will be problems with GC in foreign threads if `threads` option is off or TLS emulation is enabled
const allowForeignThreadGc = compileOption("threads") and not compileOption("tlsEmulation")
when allowForeignThreadGc:
var
localGcInitialized {.rtlThreadVar.}: bool
when declared(threadType):
proc setupForeignThreadGc*() {.gcsafe.} =
## Call this if you registered a callback that will be run from a thread not
## under your control. This has a cheap thread-local guard, so the GC for
@@ -143,16 +137,33 @@ when allowForeignThreadGc:
##
## This function is available only when ``--threads:on`` and ``--tlsEmulation:off``
## switches are used
if not localGcInitialized:
localGcInitialized = true
if threadType == ThreadType.None:
initAllocator()
var stackTop {.volatile.}: pointer
setStackBottom(addr(stackTop))
initGC()
threadType = ThreadType.ForeignThread
proc tearDownForeignThreadGc*() {.gcsafe.} =
## Call this to tear down the GC, previously initialized by ``setupForeignThreadGc``.
## If GC has not been previously initialized, or has already been torn down, the
## call does nothing.
##
## This function is available only when ``--threads:on`` and ``--tlsEmulation:off``
## switches are used
if threadType != ThreadType.ForeignThread:
return
when declared(deallocOsPages): deallocOsPages()
threadType = ThreadType.None
when declared(gch): zeroMem(addr gch, sizeof(gch))
else:
template setupForeignThreadGc*() =
{.error: "setupForeignThreadGc is available only when ``--threads:on`` and ``--tlsEmulation:off`` are used".}
template tearDownForeignThreadGc*() =
{.error: "tearDownForeignThreadGc is available only when ``--threads:on`` and ``--tlsEmulation:off`` are used".}
# ----------------- stack management --------------------------------------
# inspired from Smart Eiffel

View File

@@ -67,7 +67,7 @@ proc checkErr(f: File) =
{.push stackTrace:off, profiler:off.}
proc readBuffer(f: File, buffer: pointer, len: Natural): int =
result = c_fread(buffer, 1, len, f)
checkErr(f)
if result != len: checkErr(f)
proc readBytes(f: File, a: var openArray[int8|uint8], start, len: Natural): int =
result = readBuffer(f, addr(a[start]), len)
@@ -118,8 +118,9 @@ const
proc close*(f: File) = discard c_fclose(f)
proc readChar(f: File): char =
let x = c_fgetc(f)
if x == -1: raiseEOF()
checkErr(f)
if x < 0:
checkErr(f)
raiseEOF()
result = char(x)
proc flushFile*(f: File) = discard c_fflush(f)
@@ -140,7 +141,7 @@ proc readLine(f: File, line: var TaintedString): bool =
# fgets doesn't append an \L
c_memset(addr line.string[pos], '\L'.ord, sp)
var fgetsSuccess = c_fgets(addr line.string[pos], sp, f) != nil
checkErr(f)
if not fgetsSuccess: checkErr(f)
let m = c_memchr(addr line.string[pos], '\L'.ord, sp)
if m != nil:
# \l found: Could be our own or the one by fgets, in any case, we're done
@@ -170,21 +171,23 @@ proc readLine(f: File): TaintedString =
proc write(f: File, i: int) =
when sizeof(int) == 8:
c_fprintf(f, "%lld", i)
if c_fprintf(f, "%lld", i) < 0: checkErr(f)
else:
c_fprintf(f, "%ld", i)
if c_fprintf(f, "%ld", i) < 0: checkErr(f)
proc write(f: File, i: BiggestInt) =
when sizeof(BiggestInt) == 8:
c_fprintf(f, "%lld", i)
if c_fprintf(f, "%lld", i) < 0: checkErr(f)
else:
c_fprintf(f, "%ld", i)
if c_fprintf(f, "%ld", i) < 0: checkErr(f)
proc write(f: File, b: bool) =
if b: write(f, "true")
else: write(f, "false")
proc write(f: File, r: float32) = c_fprintf(f, "%g", r)
proc write(f: File, r: BiggestFloat) = c_fprintf(f, "%g", r)
proc write(f: File, r: float32) =
if c_fprintf(f, "%g", r) < 0: checkErr(f)
proc write(f: File, r: BiggestFloat) =
if c_fprintf(f, "%g", r) < 0: checkErr(f)
proc write(f: File, c: char) = discard c_putc(ord(c), f)
proc write(f: File, a: varargs[string, `$`]) =
@@ -212,7 +215,10 @@ proc rawFileSize(file: File): int =
discard c_fseek(file, clong(oldPos), 0)
proc endOfFile(f: File): bool =
result = c_feof(f) != 0
var c = c_fgetc(f)
discard c_ungetc(c, f)
return c < 0'i32
#result = c_feof(f) != 0
proc readAllFile(file: File, len: int): string =
# We acquire the filesize beforehand and hope it doesn't change.

View File

@@ -285,7 +285,19 @@ when useStackMaskHack:
when not defined(useNimRtl):
when not useStackMaskHack:
#when not defined(createNimRtl): initStackBottom()
when declared(initGC): initGC()
when declared(initGC):
initGC()
when not emulatedThreadVars:
type ThreadType {.pure.} = enum
None = 0,
NimThread = 1,
ForeignThread = 2
var
threadType {.rtlThreadVar.}: ThreadType
threadType = ThreadType.NimThread
when emulatedThreadVars:
if nimThreadVarsSize() > sizeof(ThreadLocalStorage):
@@ -442,6 +454,8 @@ proc threadProcWrapStackFrame[TArg](thrd: ptr Thread[TArg]) =
# init the GC for refc/markandsweep
setStackBottom(addr(p))
initGC()
when declared(threadType):
threadType = ThreadType.NimThread
when declared(registerThread):
thrd.stackBottom = addr(thrd)
registerThread(thrd)

237
readme.md
View File

@@ -1,146 +1,175 @@
# <img src="https://raw.githubusercontent.com/nim-lang/assets/master/Art/logo-crown.png" width="36"> Nim [![Build Status](https://travis-ci.org/nim-lang/Nim.svg?branch=devel)](https://travis-ci.org/nim-lang/Nim)
# ![Logo][image-nim-logo] Nim [![Build Status][badge-nim-travisci]][nim-travisci]
This repo contains the Nim compiler, Nim's stdlib, tools and
documentation. For more information about Nim, including downloads
and documentation for the latest release, check out
[Nim's website](http://nim-lang.org).
This repository contains the Nim compiler, Nim's stdlib, tools and documentation.
For more information about Nim, including downloads and documentation for
the latest release, check out [Nim's website][nim-site].
## Community
[![Join the IRC chat][badge-nim-irc]][nim-irc]
[![Join the Gitter chat][badge-nim-gitter]][nim-gitter]
[![Get help][badge-nim-forum-gethelp]][nim-forum]
[![View Nim posts on Stack Overflow][badge-nim-stackoverflow]][nim-stackoverflow-newest]
[![Follow @nim_lang on Twitter][badge-nim-twitter]][nim-twitter]
* The [forum][nim-forum] - the best place to ask questions and to discuss Nim.
* [#nim IRC Channel (Freenode)][nim-irc] - a place to discuss Nim in real-time.
Also where most development decisions get made.
* [Gitter][nim-gitter] - an additional place to discuss Nim in real-time. There
is a bridge between Gitter and the IRC channel.
* [Stack Overflow][nim-stackoverflow] - a popular Q/A site for programming related
topics that includes posts about Nim.
## Compiling
Compiling the Nim compiler is quite straightforward. Because
the Nim compiler itself is written in the Nim programming language
the C source of an older version of the compiler are needed to bootstrap the
latest version. The C sources are available in a separate
repo [here](http://github.com/nim-lang/csources).
The compiler currently supports the following platform and architecture
combinations:
The compiler currently officially supports the following platform and
architecture combinations:
* Windows (Windows XP or greater) - x86 and x86_64
* Linux (most, if not all, distributions) - x86, x86_64, ppc64 and armv6l
* Mac OS X 10.04 or higher - x86, x86_64 and ppc64
* Mac OS X (10.04 or greater) - x86, x86_64 and ppc64
In reality a lot more are supported, however they are not tested regularly.
More platforms are supported, however they are not tested regularly and they
may not be as stable as the above-listed platforms.
To build from source you will need:
Compiling the Nim compiler is quite straightforward if you follow these steps:
* gcc 3.x or later recommended. Other alternatives which may work
are: clang, Visual C++, Intel's C++ compiler
* git or wget
First, the C source of an older version of the Nim compiler is needed to
bootstrap the latest version because the Nim compiler itself is written in the
Nim programming language. Those C sources are available within the
[``nim-lang/csources``][csources-repo] repository.
**Note:** When installing ``gcc`` on Ubuntu (and likely other distros) ensure
that the ``build-essentials`` package is installed also.
Next, to build from source you will need:
If you are on a fairly modern *nix system, the following steps should work:
* A C compiler such as ``gcc`` 3.x/later or an alternative such as ``clang``,
``Visual C++`` or ``Intel C++``. It is recommended to use ``gcc`` 3.x or
later.
* Either ``git`` or ``wget`` to download the needed source repositories.
* The ``build-essentials`` package when using ``gcc`` on Ubuntu (and likely
other distros as well).
Then, if you are on a \*nix system or Windows, the following steps should compile
Nim from source using ``gcc``, ``git`` and the ``koch`` build tool (in the place
of ``sh build.sh`` you should substitute ``build.bat`` on x86 Windows or
``build64.bat`` on x86_64 Windows):
```
$ git clone https://github.com/nim-lang/Nim.git
$ cd Nim
$ git clone --depth 1 https://github.com/nim-lang/csources
$ cd csources && sh build.sh
$ cd ..
$ git clone --depth 1 https://github.com/nim-lang/csources.git
$ cd csources
$ sh build.sh
$ cd ../
$ bin/nim c koch
$ ./koch boot -d:release
```
You should then add the ``bin`` directory to your PATH, to make it easily
executable on your system.
Finally, once you have finished the build steps (on Windows, Mac or Linux) you
should add the ``bin`` directory to your PATH.
The above steps can be performed on Windows in a similar fashion, the
``build.bat`` and ``build64.bat`` (for x86_64 systems) are provided to be used
instead of ``build.sh``.
## Koch
``koch`` is the build tool used to build various parts of Nim and to generate
documentation and the website, among other things. The ``koch`` tool can also
be used to run the Nim test suite.
The ``koch`` tool is the Nim build tool, more ``koch`` related options are
documented in [doc/koch.rst](doc/koch.rst).
Assuming that you added Nim's ``bin`` directory to your PATH, you may execute
the tests using ``./koch tests``. The tests take a while to run, but you
can run a subset of tests by specifying a category (for example
``./koch tests cat async``).
For more information on the ``koch`` build tool please see the documentation
within the [doc/koch.rst](doc/koch.rst) file.
## Nimble
[Nimble](https://github.com/nim-lang/nimble) is Nim's package manager. For the
source based installations, where you added Nim's ``bin`` directory to your PATH,
the easiest way of installing Nimble is via:
```
$ koch nimble
```
## Community
[![Join the Chat at irc.freenode.net#nim](https://img.shields.io/badge/IRC-join_chat_in_%23nim-blue.svg)](https://webchat.freenode.net/?channels=nim)
[![Join the Gitter channel](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/nim-lang/Nim)
[![Get help](https://img.shields.io/badge/Forum-get%20help-4eb899.svg)](http://forum.nim-lang.org)
[![Stackoverflow](https://img.shields.io/badge/stackoverflow-use_%23nim_tag-yellow.svg)](http://stackoverflow.com/questions/tagged/nim?sort=newest&pageSize=15)
[![Follow @nim_lang!](https://img.shields.io/twitter/follow/nim_lang.svg?style=social)](https://twitter.com/nim_lang)
* The [forum](http://forum.nim-lang.org/) - the best place to ask questions and to discuss Nim.
* [IRC (Freenode#nim)](https://webchat.freenode.net/?channels=nim) - a place to discuss
Nim in real-time, this is also where most development decision get made!
* [Gitter](https://gitter.im/nim-lang/Nim) allows to discuss Nim from your browser, one click to join.
There is a bridge between Gitter and IRC channels.
* [Stackoverflow](http://stackoverflow.com/questions/tagged/nim)
``nimble`` is Nim's package manager and it can be acquired from the
[``nim-lang/nimble``][nimble-repo] repository. Assuming that you added Nim's
``bin`` directory to your PATH, you may install Nimble from source by running
``koch nimble`` within the root of the cloned repository.
## Contributing
[![Contribute to Nim via Gratipay][badge-nim-gratipay]][nim-gratipay]
[![Setup a bounty via Bountysource][badge-nim-bountysource]][nim-bountysource]
[![Donate Bitcoins][badge-nim-bitcoin]][nim-bitcoin]
[![Contribute to Nim via Gratipay!](https://img.shields.io/gratipay/team/nim.svg)](https://gratipay.com/nim/)
[![Bountysource](https://img.shields.io/bountysource/team/nim/activity.svg)](https://www.bountysource.com/teams/nim)
We welcome everyone's contributions to Nim. No matter how small or large
the contribution is, anything from small spelling fixes to large modules
intended to be included in the standard library are accepted. Before
you get started, you should know the following about this repositories
structure:
We welcome everyone's contributions to Nim independent of how small or how large
they are. Anything from small spelling fixes to large modules intended to
be included in the standard library are welcome and appreciated. Before you get
started contributing, you should familiarize yourself with the repository structure:
* ``bin/``, ``build/`` - these directories are empty, but are used when Nim is built.
* ``compiler/`` - the compiler source code, all the Nim source code files in this
directory implement the compiler. This also includes nimfix, and plugins
which live in ``compiler/nimfix`` and ``compiler/plugins``
respectively. Nimsuggest used to live in the ``compiler`` directory also,
but was moved to https://github.com/nim-lang/nimsuggest.
* ``compiler/`` - the compiler source code. Also includes nimfix, and plugins within
``compiler/nimfix`` and ``compiler/plugins`` respectively. Nimsuggest was moved to
the [``nim-lang/nimsuggest``][nimsuggest-repo] repository, though it previously also
lived within the ``compiler/`` directory.
* ``config/`` - the configuration for the compiler and documentation generator.
* ``doc/`` - the documentation files in reStructuredText format.
* ``lib/`` - where the standard library lives.
* ``lib/`` - the standard library, including:
* ``pure/`` - modules in the standard library written in pure Nim.
* ``impure/`` - modules in the standard library written in pure Nim which
depend on libraries written in other languages.
* ``wrappers/`` - modules which wrap libraries written in other languages.
* ``tests/`` - contains tests for the compiler and standard library, organised by
category.
* ``tools/`` - the tools including ``niminst`` and ``nimweb``, most of these are invoked
via ``koch``.
* ``web/`` - the Nim website (http://nim-lang.org).
* ``koch.nim`` - tool used to bootstrap Nim, generate C sources, build the website, documentation
and more.
* ``impure/`` - modules in the standard library written in pure Nim with
dependencies written in other languages.
* ``wrappers/`` - modules which wrap dependencies written in other languages.
* ``tests/`` - contains categorized tests for the compiler and standard library.
* ``tools/`` - the tools including ``niminst`` and ``nimweb`` (mostly invoked via
``koch``).
* ``web/`` - [the Nim website][nim-site].
* ``koch.nim`` - tool used to bootstrap Nim, generate C sources, build the website,
and generate the documentation.
Most importantly, the ``koch`` tool can be used to run the test suite. To do so compile it first
by executing ``nim c koch``, then execute ``./koch tests``. The test suite takes a while to run,
but you can run specific tests by specifying a category to run, for example ``./koch tests cat async``.
If you are not familiar with making a pull request using GitHub and/or git, please
read [this guide][pull-request-instructions].
Make sure that the tests all pass before
[submitting your pull request](https://help.github.com/articles/using-pull-requests/).
If you're short on time, you can
just run the tests specific to your change. Just run the category which corresponds to the change
you've made. When you create your pull request, Travis CI will verify that all the tests pass
anyway.
Ideally you should make sure that all tests pass before submitting a pull request.
However, if you are short on time, you can just run the tests specific to your
changes by only running the corresponding categories of tests. Travis CI verifies
that all tests pass before allowing the pull request to be accepted, so only
running specific tests should be harmless.
If you're looking for things to do, take a look at our
[issue tracker](https://github.com/nim-lang/Nim/issues). There is always plenty of issues
labelled [``Easy``](https://github.com/nim-lang/Nim/labels/Easy), these should be a good
starting point if this is your first contribution to Nim.
If you're looking for ways to contribute, please look at our [issue tracker][nim-issues].
There are always plenty of issues labelled [``Easy``][nim-issues-easy]; these should
be a good starting point for an initial contribution to Nim.
You can also help with the development of Nim by making donations. You can do so
in many ways:
You can also help with the development of Nim by making donations. Donations can be
made using:
* [Gratipay](https://gratipay.com/nim/)
* [Bountysource](https://www.bountysource.com/teams/nim)
* Bitcoin - 1BXfuKM2uvoD6mbx4g5xM3eQhLzkCK77tJ
* [Gratipay][nim-gratipay]
* [Bountysource][nim-bountysource]
* [Bitcoin][nim-bitcoin]
Finally, if you have any questions feel free to submit a question on the issue tracker,
on the [Nim forum](http://forum.nim-lang.org), or on IRC.
If you have any questions feel free to submit a question on the
[Nim forum][nim-forum], or via IRC on [the \#nim channel][nim-irc].
## License
The compiler and the standard library are licensed under the MIT license,
except for some modules where the documentation suggests otherwise. This means
that you can use any license for your own programs developed with Nim,
allowing you to create commercial applications.
The compiler and the standard library are licensed under the MIT license, except
for some modules which explicitly state otherwise. As a result you may use any
compatible license (essentially any license) for your own programs developed with
Nim. You are explicitly permitted to develop commercial applications using Nim.
Read copying.txt for more details.
Please read the [copying.txt](copying.txt) file for more details.
Copyright (c) 2006-2017 Andreas Rumpf.
All rights reserved.
Copyright © 2006-2017 Andreas Rumpf, all rights reserved.
[nim-site]: https://nim-lang.org
[nim-forum]: https://forum.nim-lang.org
[nim-issues]: https://github.com/nim-lang/Nim/issues
[nim-issues-easy]: https://github.com/nim-lang/Nim/labels/Easy
[nim-irc]: https://webchat.freenode.net/?channels=nim
[nim-travisci]: https://travis-ci.org/nim-lang/Nim
[nim-twitter]: https://twitter.com/nim_lang
[nim-stackoverflow]: https://stackoverflow.com/questions/tagged/nim
[nim-stackoverflow-newest]: https://stackoverflow.com/questions/tagged/nim?sort=newest&pageSize=15
[nim-gitter]: https://gitter.im/nim-lang/Nim
[nim-gratipay]: https://gratipay.com/nim/
[nim-bountysource]: https://www.bountysource.com/teams/nim
[nim-bitcoin]: https://blockchain.info/address/1BXfuKM2uvoD6mbx4g5xM3eQhLzkCK77tJ
[nimble-repo]: https://github.com/nim-lang/nimble
[nimsuggest-repo]: https://github.com/nim-lang/nimsuggest
[csources-repo]: https://github.com/nim-lang/csources
[badge-nim-travisci]: https://img.shields.io/travis/nim-lang/Nim/devel.svg?style=flat-square
[badge-nim-irc]: https://img.shields.io/badge/chat-on_irc-blue.svg?style=flat-square
[badge-nim-gitter]: https://img.shields.io/badge/chat-on_gitter-blue.svg?style=flat-square
[badge-nim-forum-gethelp]: https://img.shields.io/badge/Forum-get%20help-4eb899.svg?style=flat-square
[badge-nim-twitter]: https://img.shields.io/twitter/follow/nim_lang.svg?style=social
[badge-nim-stackoverflow]: https://img.shields.io/badge/stackoverflow-nim_tag-yellow.svg?style=flat-square
[badge-nim-gratipay]: https://img.shields.io/gratipay/team/nim.svg?style=flat-square
[badge-nim-bountysource]: https://img.shields.io/bountysource/team/nim/activity.svg?style=flat-square
[badge-nim-bitcoin]: https://img.shields.io/badge/bitcoin-1BXfuKM2uvoD6mbx4g5xM3eQhLzkCK77tJ-D69134.svg?style=flat-square
[image-nim-logo]: https://images1-focus-opensocial.googleusercontent.com/gadgets/proxy?url=https://raw.githubusercontent.com/nim-lang/assets/master/Art/logo-crown.png&container=focus&resize_w=36&refresh=21600
[pull-request-instructions]: https://help.github.com/articles/using-pull-requests/

View File

@@ -0,0 +1,26 @@
discard """
output: '''false'''
"""
# bug #5402
import lists
type
Container[T] = ref object
obj: T
ListOfContainers[T] = ref object
list: DoublyLinkedList[Container[T]]
proc contains[T](this: ListOfContainers[T], obj: T): bool =
for item in this.list.items():
if item.obj == obj: return true
return false
proc newListOfContainers[T](): ListOfContainers[T] =
new(result)
result.list = initDoublyLinkedList[Container[T]]()
let q = newListOfContainers[int64]()
echo q.contains(123)

View File

@@ -0,0 +1,23 @@
discard """
outputsub: '''tproper_stacktrace3.nim(21) main'''
exitcode: 1
"""
# bug #5400
type Container = object
val: int
proc actualResolver(x: ptr Container): ptr Container = x
template resolve(): untyped = actualResolver(db)
proc myfail(): int =
doAssert false
proc main() =
var db: ptr Container = nil
# actualResolver(db).val = myfail() # actualResolver is not included in stack trace.
resolve().val = myfail() # resolve template is included in stack trace.
main()

88
tests/gc/foreign_thr.nim Normal file
View File

@@ -0,0 +1,88 @@
discard """
output: '''
Hello from thread
Hello from thread
Hello from thread
Hello from thread
'''
cmd: "nim $target --hints:on --threads:on --tlsEmulation:off $options $file"
"""
# Copied from stdlib
import strutils
const
StackGuardSize = 4096
ThreadStackMask = 1024*256*sizeof(int)-1
ThreadStackSize = ThreadStackMask+1 - StackGuardSize
type ThreadFunc = proc() {.thread.}
when defined(posix):
import posix
proc runInForeignThread(f: ThreadFunc) =
proc wrapper(p: pointer): pointer {.noconv.} =
let thr = cast[ThreadFunc](p)
setupForeignThreadGc()
thr()
tearDownForeignThreadGc()
setupForeignThreadGc()
thr()
tearDownForeignThreadGc()
result = nil
var attrs {.noinit.}: PthreadAttr
doAssert pthread_attr_init(addr attrs) == 0
doAssert pthread_attr_setstacksize(addr attrs, ThreadStackSize) == 0
var tid: Pthread
doAssert pthread_create(addr tid, addr attrs, wrapper, f) == 0
doAssert pthread_join(tid, nil) == 0
elif defined(windows):
import winlean
type
WinThreadProc = proc (x: pointer): int32 {.stdcall.}
proc createThread(lpThreadAttributes: pointer, dwStackSize: DWORD,
lpStartAddress: WinThreadProc,
lpParameter: pointer,
dwCreationFlags: DWORD,
lpThreadId: var DWORD): Handle {.
stdcall, dynlib: "kernel32", importc: "CreateThread".}
proc wrapper(p: pointer): int32 {.stdcall.} =
let thr = cast[ThreadFunc](p)
setupForeignThreadGc()
thr()
tearDownForeignThreadGc()
setupForeignThreadGc()
thr()
tearDownForeignThreadGc()
result = 0'i32
proc runInForeignThread(f: ThreadFunc) =
var dummyThreadId: DWORD
var h = createThread(nil, ThreadStackSize.int32, wrapper.WinThreadProc, cast[pointer](f), 0, dummyThreadId)
doAssert h != 0.Handle
doAssert waitForSingleObject(h, -1'i32) == 0.DWORD
else:
{.fatal: "Unknown system".}
proc runInNativeThread(f: ThreadFunc) =
proc wrapper(f: ThreadFunc) {.thread.} =
# These operations must be NOP
setupForeignThreadGc()
tearDownForeignThreadGc()
f()
f()
var thr: Thread[ThreadFunc]
createThread(thr, wrapper, f)
joinThread(thr)
proc f {.thread.} =
var msg = "Hello " & "from thread"
echo msg
runInForeignThread(f)
runInNativeThread(f)

View File

@@ -0,0 +1,17 @@
type
Test = object
x: int
case p: bool
of true:
a: int
else:
case q: bool
of true:
b: int
else:
discard
proc f[T](t: typedesc[T]): int =
1
assert Test.f == 1

View File

@@ -19,7 +19,7 @@ when true:
q(B()) # This call reported as ambiguous.
# bug #2219
template testPred(a: expr) =
template testPred(a: untyped) =
block:
type A = object of RootObj
type B = object of A

11
tests/stdlib/tbug5382.nim Normal file
View File

@@ -0,0 +1,11 @@
discard """
output: '''
02
'''
"""
import re
let regexp = re"^\/([0-9]{2})\.html$"
var matches: array[1, string]
discard "/02.html".find(regexp, matches)
echo matches[0]

View File

@@ -1,3 +1,10 @@
discard """
output: '''[0.0, 0.0, 0.0]
[0.0, 0.0, 0.0, 0.0]
5050'''
"""
template mathPerComponent(op: untyped): untyped =
proc op*[N,T](v,u: array[N,T]): array[N,T] {.inline.} =
@@ -19,3 +26,24 @@ proc foo(): void =
echo repr(v1 *** v2)
foo()
# bug #5383
import sequtils
proc zipWithIndex[A](ts: seq[A]): seq[(int, A)] =
toSeq(pairs(ts))
proc main =
discard zipWithIndex(@["foo", "bar"])
discard zipWithIndex(@[1, 2])
discard zipWithIndex(@[true, false])
main()
# bug #5405
proc main2() =
let s = toSeq(1..100).foldL(a + b)
echo s
main2()

View File

@@ -5,8 +5,8 @@ import macros
# Test that parameters are properly gensym'ed finally:
template genNodeKind(kind, name: expr): stmt =
proc name*(children: varargs[PNimrodNode]): PNimrodNode {.compiletime.}=
template genNodeKind(kind, name: untyped) =
proc name*(children: varargs[NimNode]): NimNode {.compiletime.}=
result = newNimNode(kind)
for c in children:
result.add(c)
@@ -22,7 +22,7 @@ type Something = object
proc testA(x: Something) = discard
template def(name: expr) {.immediate.} =
template def(name: untyped) =
proc testB[T](reallyUniqueName: T) =
`test name`(reallyUniqueName)
def A
@@ -35,8 +35,7 @@ testB(x)
# Test that templates in generics still work (regression to fix the
# regression...)
template forStatic(index: expr, slice: Slice[int], predicate: stmt):
stmt {.immediate.} =
template forStatic(index, slice, predicate: untyped) =
const a = slice.a
const b = slice.b
when a <= b:

View File

@@ -147,6 +147,7 @@ proc gcTests(r: var TResults, cat: Category, options: string) =
testSpec r, makeTest("tests/gc" / filename, options &
" -d:release --gc:boehm", cat, actionRun)
testWithoutBoehm "foreign_thr"
test "gcemscripten"
test "growobjcrash"
test "gcbench"

View File

@@ -76,7 +76,236 @@ for i in 1..10:
echo(name)
discard db.getRow(
SqlQuery("INSERT INTO tags(name) VALUES(\'$1\') RETURNING id" % [name]))
# get column details
db.exec(SqlQuery("DROP TABLE IF EXISTS dbtypes;"))
db.exec(SqlQuery("DROP TYPE IF EXISTS custom_enum;"))
db.exec(SqlQuery("CREATE TYPE custom_enum AS ENUM ('1', '2', '3');"))
db.exec(SqlQuery("DROP TYPE IF EXISTS custom_composite;"))
db.exec(SqlQuery("CREATE TYPE custom_composite AS (r double precision, i double precision);"))
db.exec(SqlQuery("""CREATE TABLE dbtypes(
id serial UNIQUE,
bytea_col bytea,
smallint_col smallint,
integer_col integer,
bigint_col bigint,
decimal_col decimal,
numeric_col numeric,
real_col real,
double_precision_col double precision,
smallserial_col smallserial,
serial_col serial,
bigserial_col bigserial,
money_col money,
varchar_col varchar(10),
character_col character(1),
text_col text,
timestamp_col timestamp,
date_col date,
time_col time,
interval_col interval,
bool_col boolean,
custom_enum_col custom_enum,
point_col point,
line_col line,
lseg_col lseg,
box_col box,
path_col path,
polygon_col polygon,
circle_col circle,
cidr_col cidr,
inet_col inet,
macaddr_col macaddr,
bit_col bit,
varbit_col bit(3),
tsvector_col tsvector,
tsquery_col tsquery,
uuid_col uuid,
xml_col xml,
json_col json,
array_col integer[],
custom_composite_col custom_composite,
range_col int4range
);"""))
db.exec(SqlQuery("INSERT INTO dbtypes (id) VALUES(0);"))
var dbCols : DbColumns = @[]
for row in db.instantRows(dbCols, sql"SELECT * FROM dbtypes"):
doAssert len(dbCols) == 42
doAssert dbCols[0].name == "id"
doAssert dbCols[0].typ.kind == DbTypeKind.dbInt
doAssert dbCols[0].typ.name == "int4"
doAssert dbCols[0].typ.size == 4
doAssert dbCols[1].name == "bytea_col"
doAssert dbCols[1].typ.kind == DbTypeKind.dbBlob
doAssert dbCols[1].typ.name == "bytea"
doAssert dbCols[2].name == "smallint_col"
doAssert dbCols[2].typ.kind == DbTypeKind.dbInt
doAssert dbCols[2].typ.name == "int2"
doAssert dbCols[2].typ.size == 2
doAssert dbCols[3].name == "integer_col"
doAssert dbCols[3].typ.kind == DbTypeKind.dbInt
doAssert dbCols[3].typ.name == "int4"
doAssert dbCols[3].typ.size == 4
doAssert dbCols[4].name == "bigint_col"
doAssert dbCols[4].typ.kind == DbTypeKind.dbInt
doAssert dbCols[4].typ.name == "int8"
doAssert dbCols[4].typ.size == 8
doAssert dbCols[5].name == "decimal_col"
doAssert dbCols[5].typ.kind == DbTypeKind.dbDecimal
doAssert dbCols[5].typ.name == "numeric"
doAssert dbCols[6].name == "numeric_col"
doAssert dbCols[6].typ.kind == DbTypeKind.dbDecimal
doAssert dbCols[6].typ.name == "numeric"
doAssert dbCols[7].name == "real_col"
doAssert dbCols[7].typ.kind == DbTypeKind.dbFloat
doAssert dbCols[7].typ.name == "float4"
doAssert dbCols[8].name == "double_precision_col"
doAssert dbCols[8].typ.kind == DbTypeKind.dbFloat
doAssert dbCols[8].typ.name == "float8"
doAssert dbCols[9].name == "smallserial_col"
doAssert dbCols[9].typ.kind == DbTypeKind.dbInt
doAssert dbCols[9].typ.name == "int2"
doAssert dbCols[10].name == "serial_col"
doAssert dbCols[10].typ.kind == DbTypeKind.dbInt
doAssert dbCols[10].typ.name == "int4"
doAssert dbCols[11].name == "bigserial_col"
doAssert dbCols[11].typ.kind == DbTypeKind.dbInt
doAssert dbCols[11].typ.name == "int8"
doAssert dbCols[12].name == "money_col"
doAssert dbCols[12].typ.kind == DbTypeKind.dbDecimal
doAssert dbCols[12].typ.name == "money"
doAssert dbCols[13].name == "varchar_col"
doAssert dbCols[13].typ.kind == DbTypeKind.dbVarchar
doAssert dbCols[13].typ.name == "varchar"
doAssert dbCols[14].name == "character_col"
doAssert dbCols[14].typ.kind == DbTypeKind.dbFixedChar
doAssert dbCols[14].typ.name == "bpchar"
doAssert dbCols[15].name == "text_col"
doAssert dbCols[15].typ.kind == DbTypeKind.dbVarchar
doAssert dbCols[15].typ.name == "text"
doAssert dbCols[16].name == "timestamp_col"
doAssert dbCols[16].typ.kind == DbTypeKind.dbTimestamp
doAssert dbCols[16].typ.name == "timestamp"
doAssert dbCols[17].name == "date_col"
doAssert dbCols[17].typ.kind == DbTypeKind.dbDate
doAssert dbCols[17].typ.name == "date"
doAssert dbCols[18].name == "time_col"
doAssert dbCols[18].typ.kind == DbTypeKind.dbTime
doAssert dbCols[18].typ.name == "time"
doAssert dbCols[19].name == "interval_col"
doAssert dbCols[19].typ.kind == DbTypeKind.dbTimeInterval
doAssert dbCols[19].typ.name == "interval"
doAssert dbCols[20].name == "bool_col"
doAssert dbCols[20].typ.kind == DbTypeKind.dbBool
doAssert dbCols[20].typ.name == "bool"
doAssert dbCols[21].name == "custom_enum_col"
doAssert dbCols[21].typ.kind == DbTypeKind.dbUnknown
doAssert parseInt(dbCols[21].typ.name) > 0
doAssert dbCols[22].name == "point_col"
doAssert dbCols[22].typ.kind == DbTypeKind.dbPoint
doAssert dbCols[22].typ.name == "point"
doAssert dbCols[23].name == "line_col"
doAssert dbCols[23].typ.kind == DbTypeKind.dbLine
doAssert dbCols[23].typ.name == "line"
doAssert dbCols[24].name == "lseg_col"
doAssert dbCols[24].typ.kind == DbTypeKind.dbLseg
doAssert dbCols[24].typ.name == "lseg"
doAssert dbCols[25].name == "box_col"
doAssert dbCols[25].typ.kind == DbTypeKind.dbBox
doAssert dbCols[25].typ.name == "box"
doAssert dbCols[26].name == "path_col"
doAssert dbCols[26].typ.kind == DbTypeKind.dbPath
doAssert dbCols[26].typ.name == "path"
doAssert dbCols[27].name == "polygon_col"
doAssert dbCols[27].typ.kind == DbTypeKind.dbPolygon
doAssert dbCols[27].typ.name == "polygon"
doAssert dbCols[28].name == "circle_col"
doAssert dbCols[28].typ.kind == DbTypeKind.dbCircle
doAssert dbCols[28].typ.name == "circle"
doAssert dbCols[29].name == "cidr_col"
doAssert dbCols[29].typ.kind == DbTypeKind.dbInet
doAssert dbCols[29].typ.name == "cidr"
doAssert dbCols[30].name == "inet_col"
doAssert dbCols[30].typ.kind == DbTypeKind.dbInet
doAssert dbCols[30].typ.name == "inet"
doAssert dbCols[31].name == "macaddr_col"
doAssert dbCols[31].typ.kind == DbTypeKind.dbMacAddress
doAssert dbCols[31].typ.name == "macaddr"
doAssert dbCols[32].name == "bit_col"
doAssert dbCols[32].typ.kind == DbTypeKind.dbBit
doAssert dbCols[32].typ.name == "bit"
doAssert dbCols[33].name == "varbit_col"
doAssert dbCols[33].typ.kind == DbTypeKind.dbBit
doAssert dbCols[33].typ.name == "bit"
doAssert dbCols[34].name == "tsvector_col"
doAssert dbCols[34].typ.kind == DbTypeKind.dbVarchar
doAssert dbCols[34].typ.name == "tsvector"
doAssert dbCols[35].name == "tsquery_col"
doAssert dbCols[35].typ.kind == DbTypeKind.dbVarchar
doAssert dbCols[35].typ.name == "tsquery"
doAssert dbCols[36].name == "uuid_col"
doAssert dbCols[36].typ.kind == DbTypeKind.dbVarchar
doAssert dbCols[36].typ.name == "uuid"
doAssert dbCols[37].name == "xml_col"
doAssert dbCols[37].typ.kind == DbTypeKind.dbXml
doAssert dbCols[37].typ.name == "xml"
doAssert dbCols[38].name == "json_col"
doAssert dbCols[38].typ.kind == DbTypeKind.dbJson
doAssert dbCols[38].typ.name == "json"
doAssert dbCols[39].name == "array_col"
doAssert dbCols[39].typ.kind == DbTypeKind.dbArray
doAssert dbCols[39].typ.name == "int4[]"
doAssert dbCols[40].name == "custom_composite_col"
doAssert dbCols[40].typ.kind == DbTypeKind.dbUnknown
doAssert parseInt(dbCols[40].typ.name) > 0
doAssert dbCols[41].name == "range_col"
doAssert dbCols[41].typ.kind == DbTypeKind.dbComposite
doAssert dbCols[41].typ.name == "int4range"
echo("All tests succeeded!")
db.close()

View File

@@ -209,6 +209,9 @@ proc main() =
of Manual:
echo "After download, move it to: ", dest
if askBool("Download successful? (y/n) "):
while not fileExists("dist" / mingw):
echo "could not find: ", "dist" / mingw
if not askBool("Try again? (y/n) "): break
if unzip(): retry = true
of Failure: discard
of Success:

1
web/bountysource.nim.cfg Normal file
View File

@@ -0,0 +1 @@
-d:ssl

View File

@@ -1,26 +1,40 @@
logo, name, url, this_month, all_time, since, level
,bogen,,0,1010,"Jul 23, 2016",1
,mikra,,0,400,"Apr 28, 2016",1
,linkmonitor,,0,180,"Jan 28, 2016",1
,shkolnick-kun,,0,375,"Jul 6, 2016",1
,"Chris Heller",,0,350,"May 19, 2016",1
,linkmonitor,,0,280,"Jan 28, 2016",1
,avsej,,0,110,"Jun 10, 2016",1
,WilRubin,,0,100,"Aug 11, 2015",1
,"Benny Luypaert",,0,100,"Apr 10, 2016",1
,"Chris Heller",,0,100,"May 19, 2016",1
,PhilipWitte,,0,100,"Aug 5, 2016",1
,skunkiferous,,0,100,"Oct 2, 2016",1
,"Jonathan Arnett",,0,90,"May 20, 2016",1
,Boxifier,,0,75,"Apr 12, 2016",1
,iolloyd,,0,75,"Apr 29, 2016",1
,btbytes,,0,70,"Apr 6, 2016",1
,rb01,,0,50,"May 4, 2016",1
,barcharcraz,,0,50,"Jun 2, 2016",1
,zachaysan,,0,50,"Jun 7, 2016",1
,kunev,,0,50,"Dec 26, 2016",1
,iboB,,0,50,"Jan 28, 2017",1
,TedSinger,,0,45,"Apr 9, 2016",1
,johnnovak,,0,45,"Apr 30, 2016",1
,"Matthew Baulch",,0,40,"Jun 7, 2016",1
,"Matthew Newton",,0,35,"Apr 20, 2016",1
,martinbbjerregaard,,0,35,"Jun 9, 2016",1
,RationalG,,0,30,"Jun 17, 2016",1
,benbve,,0,30,"Jul 12, 2016",1
,barcharcraz,,0,25,"Jun 2, 2016",1
,multikatt,,0,30,"Nov 2, 2016",1
,"Landon Bass",,0,25,"Jun 7, 2016",1
,jimrichards,,0,25,"Jun 8, 2016",1
,jjzazuet,,0,25,"Jul 10, 2016",1
,moigagoo,,0,20,"May 13, 2016",1
,kteza1,,0,20,"Jun 10, 2016",1
,tomkeus,,0,20,"Sep 4, 2016",1
,csoriano89,,0,20,"Sep 7, 2016",1
,juanjux,,0,20,"Oct 29, 2016",1
,zagfai,,0,20,"Nov 3, 2016",1
,hellcoderz,,0,20,"Jan 24, 2017",1
,mirek,,0,15,"Apr 9, 2016",1
,DateinAsia,,0,15,"Jul 30, 2016",1
,rickc,,0,15,"Jul 31, 2016",1
@@ -38,13 +52,6 @@ logo, name, url, this_month, all_time, since, level
,Blumenversand,,0,10,"Jul 21, 2016",1
,cinnabardk,,0,10,"Aug 6, 2016",1
,reddec,,0,10,"Aug 31, 2016",1
,cupen,,0,10,"Nov 21, 2016",1
,yay,,0,10,"Jan 25, 2017",1
,niv,,0,5,"Apr 6, 2016",1
,goniz,,0,5,"Apr 7, 2016",1
,genunix,,0,5,"Apr 12, 2016",1
,CynepHy6,,0,5,"Apr 14, 2016",1
,ivanflorentin,,0,5,"May 3, 2016",1
,stevenyhw,,0,5,"May 20, 2016",1
,"Sanjay Singh",,0,5,"Jun 6, 2016",1
,yuttie,,0,5,"Jun 7, 2016",1
,hron,,0,5,"Jun 11, 2016",1
,laszlowaty,,0,5,"Jun 17, 2016",1
1 logo name url this_month all_time since level
2 bogen 0 1010 Jul 23, 2016 1
3 mikra 0 400 Apr 28, 2016 1
4 linkmonitor shkolnick-kun 0 180 375 Jan 28, 2016 Jul 6, 2016 1
5 Chris Heller 0 350 May 19, 2016 1
6 linkmonitor 0 280 Jan 28, 2016 1
7 avsej 0 110 Jun 10, 2016 1
8 WilRubin 0 100 Aug 11, 2015 1
9 Benny Luypaert 0 100 Apr 10, 2016 1
Chris Heller 0 100 May 19, 2016 1
10 PhilipWitte 0 100 Aug 5, 2016 1
11 skunkiferous 0 100 Oct 2, 2016 1
12 Jonathan Arnett 0 90 May 20, 2016 1
13 Boxifier 0 75 Apr 12, 2016 1
14 iolloyd 0 75 Apr 29, 2016 1
15 btbytes 0 70 Apr 6, 2016 1
16 rb01 0 50 May 4, 2016 1
17 barcharcraz 0 50 Jun 2, 2016 1
18 zachaysan 0 50 Jun 7, 2016 1
19 kunev 0 50 Dec 26, 2016 1
20 iboB 0 50 Jan 28, 2017 1
21 TedSinger 0 45 Apr 9, 2016 1
22 johnnovak 0 45 Apr 30, 2016 1
23 Matthew Baulch 0 40 Jun 7, 2016 1
24 Matthew Newton 0 35 Apr 20, 2016 1
25 martinbbjerregaard 0 35 Jun 9, 2016 1
26 RationalG 0 30 Jun 17, 2016 1
27 benbve 0 30 Jul 12, 2016 1
28 barcharcraz multikatt 0 25 30 Jun 2, 2016 Nov 2, 2016 1
29 Landon Bass 0 25 Jun 7, 2016 1
30 jimrichards 0 25 Jun 8, 2016 1
31 jjzazuet 0 25 Jul 10, 2016 1
moigagoo 0 20 May 13, 2016 1
32 kteza1 0 20 Jun 10, 2016 1
33 tomkeus 0 20 Sep 4, 2016 1
34 csoriano89 0 20 Sep 7, 2016 1
35 juanjux 0 20 Oct 29, 2016 1
36 zagfai 0 20 Nov 3, 2016 1
37 hellcoderz 0 20 Jan 24, 2017 1
38 mirek 0 15 Apr 9, 2016 1
39 DateinAsia 0 15 Jul 30, 2016 1
40 rickc 0 15 Jul 31, 2016 1
52 Blumenversand 0 10 Jul 21, 2016 1
53 cinnabardk 0 10 Aug 6, 2016 1
54 reddec 0 10 Aug 31, 2016 1
55 cupen 0 10 Nov 21, 2016 1
56 yay 0 10 Jan 25, 2017 1
57 niv 0 5 Apr 6, 2016 1
goniz 0 5 Apr 7, 2016 1
genunix 0 5 Apr 12, 2016 1
CynepHy6 0 5 Apr 14, 2016 1
ivanflorentin 0 5 May 3, 2016 1
stevenyhw 0 5 May 20, 2016 1
Sanjay Singh 0 5 Jun 6, 2016 1
yuttie 0 5 Jun 7, 2016 1
hron 0 5 Jun 11, 2016 1
laszlowaty 0 5 Jun 17, 2016 1

View File

@@ -18,7 +18,11 @@ Changes affecting backwards compatibility
- The IO routines now raise ``EOFError`` for the "end of file" condition.
``EOFError`` is a subtype of ``IOError`` and so it's easier to distinguish
between "error during read" and "error due to EOF".
- A hash procedure has been added for ``cstring`` type in ``hashes`` module.
Previously, hash of a ``cstring`` would be calculated as a hash of the
pointer. Now the hash is calculated from the contents of the string, assuming
``cstring`` is a null-terminated string. Equal ``string`` and ``cstring``
values produce an equal hash value.
Library Additions
-----------------

View File

@@ -1,34 +1,40 @@
logo, name, url, this_month, all_time, since, level
assets/bountysource/secondspectrum.png,Second Spectrum,http://www.secondspectrum.com/,250,1250,"May 5, 2016",250
assets/bountysource/xored.svg,"Xored Software, Inc.",http://xored.com/,250,1000,"Jun 20, 2016",250
,shkolnick-kun,https://github.com/shkolnick-kun,75,225,"Jul 6, 2016",75
,flyx,http://flyx.org,35,210,"Apr 7, 2016",75
,"Yuriy Glukhov",,25,150,"Apr 6, 2016",25
,endragor,https://github.com/endragor,25,150,"Apr 7, 2016",25
,FedericoCeratto,http://firelet.net,25,150,"Apr 7, 2016",25
,"Adrian Veith",,25,150,"Apr 20, 2016",25
,skunkiferous,https://github.com/skunkiferous,100,100,"Oct 2, 2016",150
,euantorano,http://euantorano.co.uk,25,100,"Jun 7, 2016",25
,xxlabaza,https://github.com/xxlabaza,25,95,"Jun 17, 2016",25
,btbytes,https://www.btbytes.com/,10,60,"Apr 6, 2016",10
,niebaopeng,https://github.com/niebaopeng,10,50,"Apr 15, 2016",10
,"Jonathan Arnett",,10,50,"May 20, 2016",10
,swalf,https://github.com/swalf,5,45,"May 9, 2016",5
,zolern,https://github.com/zolern,10,40,"Apr 15, 2016",10
,"pyloor ",https://schwarz-weiss.cc/,10,40,"May 16, 2016",10
,zachaysan,http://venn.lc,10,40,"Jun 7, 2016",10
,"Matthew Baulch",,10,40,"Jun 7, 2016",10
,"Oskari Timperi",,10,40,"Jun 8, 2016",10
,"Handojo Goenadi",,5,35,"Apr 19, 2016",5
,"Matthew Newton",,5,30,"Apr 20, 2016",5
,johnnovak,http://www.johnnovak.net/,5,30,"Apr 29, 2016",5
,RyanMarcus,http://rmarcus.info,5,15,"Jul 19, 2016",5
,lenzenmi,https://github.com/lenzenmi,5,15,"Jul 28, 2016",5
,cpunion,https://github.com/cpunion,10,10,"Sep 9, 2016",10
,pandada8,https://github.com/pandada8,5,10,"Aug 12, 2016",5
,abeaumont,http://alfredobeaumont.org/blog,5,10,"Aug 12, 2016",5
,"Svend Knudsen",,1,6,"Apr 11, 2016",1
,"Michael D. Sklaroff",,1,6,"Apr 27, 2016",1
,csoriano89,https://github.com/csoriano89,5,5,"Sep 7, 2016",5
,nicck,,1,2,"Aug 9, 2016",1
,campbellr,,1,1,"Sep 4, 2016",1
assets/bountysource/secondspectrum.png,Second Spectrum,http://www.secondspectrum.com/,250,2250,"May 5, 2016",250
assets/bountysource/xored.svg,"Xored Software, Inc.",http://xored.com/,250,1000,250,2000,"Jun 20, 2016",250
,Varriount,https://github.com/Varriount,250,750,"Nov 18, 2016",250
,flyx,http://flyx.org,35,350,"Apr 7, 2016",75
,"Yuriy Glukhov",,25,250,"Apr 6, 2016",25
,endragor,https://github.com/endragor,25,250,"Apr 7, 2016",25
,FedericoCeratto,http://firelet.net,25,250,"Apr 7, 2016",25
,"Adrian Veith",,25,250,"Apr 20, 2016",25
,euantorano,http://euantorano.co.uk,25,200,"Jun 7, 2016",25
,xxlabaza,https://github.com/xxlabaza,25,170,"Jun 17, 2016",25
,devted,https://github.com/devted,25,100,"Oct 19, 2016",25
,"pyloor ",https://schwarz-weiss.cc/,10,95,"May 16, 2016",10
,niebaopeng,https://github.com/niebaopeng,10,90,"Apr 15, 2016",10
,zolern,https://github.com/zolern,10,80,"Apr 15, 2016",10
,"Oskari Timperi",,10,80,"Jun 8, 2016",10
,jcosborn,https://github.com/jcosborn,25,75,"Nov 21, 2016",25
,swalf,https://github.com/swalf,5,65,"May 9, 2016",5
,"Handojo Goenadi",,5,55,"Apr 19, 2016",5
,cpunion,https://github.com/cpunion,10,50,"Sep 9, 2016",10
,D-L,https://github.com/D-L,5,50,"Apr 7, 2016",5
,moigagoo,http://sloth-ci.com,10,40,"May 13, 2016",10
,enthus1ast,http://code0.xyz/,10,40,"Oct 28, 2016",10
,RyanMarcus,http://rmarcus.info,5,35,"Jul 19, 2016",5
,lenzenmi,https://github.com/lenzenmi,5,35,"Jul 28, 2016",5
,"Christian Bagley",,10,30,"Oct 11, 2016",10
,pandada8,https://github.com/pandada8,5,30,"Aug 12, 2016",5
,abeaumont,http://alfredobeaumont.org/blog,5,30,"Aug 12, 2016",5
,opendragon,http://www.opendragon.com,25,25,"Jan 18, 2017",25
,"Eric Raible",,10,20,"Dec 23, 2016",10
,zefciu,http://pythonista.net,10,20,"Dec 29, 2016",10
,"Andrey ",https://github.com/Andrey,5,20,"Oct 10, 2016",5
,syrol,https://github.com/syrol,5,10,"Dec 12, 2016",5
,"Svend Knudsen",,1,10,"Apr 11, 2016",1
,"Michael D. Sklaroff",,1,10,"Apr 27, 2016",1
,nicck,,1,6,"Aug 9, 2016",1
,cnygaard,,5,5,"Jan 17, 2017",5
,Aldrog,,5,5,"Feb 11, 2017",5
,mpachecofaulk55,,5,5,"Feb 11, 2017",5
,campbellr,,1,5,"Sep 4, 2016",1
Can't render this file because it has a wrong number of fields in line 3.