mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-04 04:02:41 +00:00
Merge branch 'devel' into faster-nimsuggest
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)])
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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) =
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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))")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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':
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
22
doc/tut1.rst
22
doc/tut1.rst
@@ -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
|
||||
|
||||
5
koch.nim
5
koch.nim
@@ -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()
|
||||
|
||||
@@ -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].} =
|
||||
|
||||
@@ -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]
|
||||
|
||||
|
||||
@@ -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]`.
|
||||
|
||||
@@ -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 == @[])
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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']
|
||||
|
||||
@@ -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", @[""])
|
||||
@@ -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!
|
||||
|
||||
@@ -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 {.
|
||||
|
||||
@@ -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`.
|
||||
##
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
237
readme.md
@@ -1,146 +1,175 @@
|
||||
# <img src="https://raw.githubusercontent.com/nim-lang/assets/master/Art/logo-crown.png" width="36"> Nim [](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
|
||||
[](https://webchat.freenode.net/?channels=nim)
|
||||
[](https://gitter.im/nim-lang/Nim)
|
||||
[](http://forum.nim-lang.org)
|
||||
[](http://stackoverflow.com/questions/tagged/nim?sort=newest&pageSize=15)
|
||||
[](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]
|
||||
|
||||
[](https://gratipay.com/nim/)
|
||||
[](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/
|
||||
|
||||
26
tests/ccgbugs/tgeneric_smallobj_asgn_opt.nim
Normal file
26
tests/ccgbugs/tgeneric_smallobj_asgn_opt.nim
Normal 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)
|
||||
23
tests/errmsgs/tproper_stacktrace3.nim
Normal file
23
tests/errmsgs/tproper_stacktrace3.nim
Normal 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
88
tests/gc/foreign_thr.nim
Normal 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)
|
||||
17
tests/metatype/tfieldaccessor.nim
Normal file
17
tests/metatype/tfieldaccessor.nim
Normal 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
|
||||
@@ -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
11
tests/stdlib/tbug5382.nim
Normal 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]
|
||||
@@ -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()
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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
1
web/bountysource.nim.cfg
Normal file
@@ -0,0 +1 @@
|
||||
-d:ssl
|
||||
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
-----------------
|
||||
|
||||
@@ -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.
|
Reference in New Issue
Block a user