Merge branch 'devel' into faster-nimsuggest
This commit is contained in:
commit
ba29ca0c63
52 changed files with 1048 additions and 281 deletions
|
|
@ -7,10 +7,7 @@ cache:
|
||||||
# - i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z
|
# - i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
fast_finish: true # set this flag to immediately finish build once one of the jobs fails.
|
fast_finish: true
|
||||||
allow_failures:
|
|
||||||
- platform: x64
|
|
||||||
# - platform: x86
|
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
matrix:
|
matrix:
|
||||||
|
|
|
||||||
|
|
@ -1541,8 +1541,7 @@ proc skipGenericOwner*(s: PSym): PSym =
|
||||||
## Generic instantiations are owned by their originating generic
|
## Generic instantiations are owned by their originating generic
|
||||||
## symbol. This proc skips such owners and goes straight to the owner
|
## symbol. This proc skips such owners and goes straight to the owner
|
||||||
## of the generic itself (the module or the enclosing proc).
|
## of the generic itself (the module or the enclosing proc).
|
||||||
result = if s.kind in skProcKinds and {sfGenSym, sfFromGeneric} * s.flags ==
|
result = if s.kind in skProcKinds and sfFromGeneric in s.flags:
|
||||||
{sfFromGeneric}:
|
|
||||||
s.owner.owner
|
s.owner.owner
|
||||||
else:
|
else:
|
||||||
s.owner
|
s.owner
|
||||||
|
|
|
||||||
|
|
@ -388,6 +388,7 @@ proc debugTree(n: PNode, indent: int, maxRecDepth: int;
|
||||||
[istr, makeYamlString($n.kind)]
|
[istr, makeYamlString($n.kind)]
|
||||||
addf(result, ",$N$1\"info\": $2", [istr, lineInfoToStr(n.info)])
|
addf(result, ",$N$1\"info\": $2", [istr, lineInfoToStr(n.info)])
|
||||||
if maxRecDepth != 0:
|
if maxRecDepth != 0:
|
||||||
|
addf(result, ",$N$1\"flags\": $2", [istr, rope($n.flags)])
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkCharLit..nkUInt64Lit:
|
of nkCharLit..nkUInt64Lit:
|
||||||
addf(result, ",$N$1\"intVal\": $2", [istr, rope(n.intVal)])
|
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)
|
optAsgnLoc(src, t, field), newflags)
|
||||||
|
|
||||||
proc genOptAsgnObject(p: BProc, dest, src: TLoc, flags: TAssignmentFlags,
|
proc genOptAsgnObject(p: BProc, dest, src: TLoc, flags: TAssignmentFlags,
|
||||||
t: PNode) =
|
t: PNode, typ: PType) =
|
||||||
if t == nil: return
|
if t == nil: return
|
||||||
let newflags =
|
let newflags =
|
||||||
if src.s == OnStatic:
|
if src.s == OnStatic:
|
||||||
|
|
@ -232,10 +232,11 @@ proc genOptAsgnObject(p: BProc, dest, src: TLoc, flags: TAssignmentFlags,
|
||||||
case t.kind
|
case t.kind
|
||||||
of nkSym:
|
of nkSym:
|
||||||
let field = t.sym
|
let field = t.sym
|
||||||
|
if field.loc.r == nil: fillObjectFields(p.module, typ)
|
||||||
genAssignment(p, optAsgnLoc(dest, field.typ, field.loc.r),
|
genAssignment(p, optAsgnLoc(dest, field.typ, field.loc.r),
|
||||||
optAsgnLoc(src, field.typ, field.loc.r), newflags)
|
optAsgnLoc(src, field.typ, field.loc.r), newflags)
|
||||||
of nkRecList:
|
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
|
else: discard
|
||||||
|
|
||||||
proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
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)
|
genGenericAsgn(p, dest, src, flags)
|
||||||
elif needsComplexAssignment(ty):
|
elif needsComplexAssignment(ty):
|
||||||
if ty.sons[0].isNil and asgnComplexity(ty.n) <= 4:
|
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
|
internalAssert ty.n != nil
|
||||||
genOptAsgnObject(p, dest, src, flags, ty.n)
|
genOptAsgnObject(p, dest, src, flags, ty.n, ty)
|
||||||
else:
|
else:
|
||||||
genGenericAsgn(p, dest, src, flags)
|
genGenericAsgn(p, dest, src, flags)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -1103,8 +1103,8 @@ proc asgnFieldDiscriminant(p: BProc, e: PNode) =
|
||||||
genAssignment(p, a, tmp, {})
|
genAssignment(p, a, tmp, {})
|
||||||
|
|
||||||
proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) =
|
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:
|
if e.sons[0].kind == nkSym and sfGoto in e.sons[0].sym.flags:
|
||||||
|
genLineDir(p, e)
|
||||||
genGotoVar(p, e.sons[1])
|
genGotoVar(p, e.sons[1])
|
||||||
elif not fieldDiscriminantCheckNeeded(p, e):
|
elif not fieldDiscriminantCheckNeeded(p, e):
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
|
|
@ -1114,8 +1114,11 @@ proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) =
|
||||||
initLocExpr(p, e.sons[0], a)
|
initLocExpr(p, e.sons[0], a)
|
||||||
if fastAsgn: incl(a.flags, lfNoDeepCopy)
|
if fastAsgn: incl(a.flags, lfNoDeepCopy)
|
||||||
assert(a.t != nil)
|
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:
|
else:
|
||||||
|
genLineDir(p, e)
|
||||||
asgnFieldDiscriminant(p, e)
|
asgnFieldDiscriminant(p, e)
|
||||||
|
|
||||||
proc genStmts(p: BProc, t: PNode) =
|
proc genStmts(p: BProc, t: PNode) =
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ proc generateThreadLocalStorage(m: BModule) =
|
||||||
|
|
||||||
proc generateThreadVarsSize(m: BModule) =
|
proc generateThreadVarsSize(m: BModule) =
|
||||||
if nimtv != nil:
|
if nimtv != nil:
|
||||||
let externc = if gCmd != cmdCompileToCpp and
|
let externc = if gCmd == cmdCompileToCpp or
|
||||||
sfCompileToCpp in m.module.flags: "extern \"C\" "
|
sfCompileToCpp in m.module.flags: "extern \"C\" "
|
||||||
else: ""
|
else: ""
|
||||||
addf(m.s[cfsProcs],
|
addf(m.s[cfsProcs],
|
||||||
|
|
|
||||||
|
|
@ -715,10 +715,13 @@ proc genProcAux(m: BModule, prc: PSym) =
|
||||||
add(generatedProc, ~"}$N")
|
add(generatedProc, ~"}$N")
|
||||||
add(m.s[cfsProcs], generatedProc)
|
add(m.s[cfsProcs], generatedProc)
|
||||||
|
|
||||||
proc crossesCppBoundary(m: BModule; sym: PSym): bool {.inline.} =
|
proc requiresExternC(m: BModule; sym: PSym): bool {.inline.} =
|
||||||
result = sfCompileToCpp in m.module.flags and
|
result = (sfCompileToCpp in m.module.flags and
|
||||||
sfCompileToCpp notin sym.getModule().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) =
|
proc genProcPrototype(m: BModule, sym: PSym) =
|
||||||
useHeader(m, sym)
|
useHeader(m, sym)
|
||||||
|
|
@ -732,7 +735,7 @@ proc genProcPrototype(m: BModule, sym: PSym) =
|
||||||
var header = genProcHeader(m, sym)
|
var header = genProcHeader(m, sym)
|
||||||
if sfNoReturn in sym.flags and hasDeclspec in extccomp.CC[cCompiler].props:
|
if sfNoReturn in sym.flags and hasDeclspec in extccomp.CC[cCompiler].props:
|
||||||
header = "__declspec(noreturn) " & header
|
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
|
header = "extern \"C\" " & header
|
||||||
if sfPure in sym.flags and hasAttribute in CC[cCompiler].props:
|
if sfPure in sym.flags and hasAttribute in CC[cCompiler].props:
|
||||||
header.add(" __attribute__((naked))")
|
header.add(" __attribute__((naked))")
|
||||||
|
|
|
||||||
|
|
@ -566,16 +566,18 @@ proc needsExeExt(): bool {.inline.} =
|
||||||
result = (optGenScript in gGlobalOptions and targetOS == osWindows) or
|
result = (optGenScript in gGlobalOptions and targetOS == osWindows) or
|
||||||
(platform.hostOS == osWindows)
|
(platform.hostOS == osWindows)
|
||||||
|
|
||||||
proc getCompilerExe(compiler: TSystemCC): string =
|
proc getCompilerExe(compiler: TSystemCC; cfile: string): string =
|
||||||
result = if gCmd == cmdCompileToCpp: CC[compiler].cppCompiler
|
result = if gCmd == cmdCompileToCpp and not cfile.endsWith(".c"):
|
||||||
else: CC[compiler].compilerExe
|
CC[compiler].cppCompiler
|
||||||
|
else:
|
||||||
|
CC[compiler].compilerExe
|
||||||
if result.len == 0:
|
if result.len == 0:
|
||||||
rawMessage(errCompilerDoesntSupportTarget, CC[compiler].name)
|
rawMessage(errCompilerDoesntSupportTarget, CC[compiler].name)
|
||||||
|
|
||||||
proc getLinkerExe(compiler: TSystemCC): string =
|
proc getLinkerExe(compiler: TSystemCC): string =
|
||||||
result = if CC[compiler].linkerExe.len > 0: CC[compiler].linkerExe
|
result = if CC[compiler].linkerExe.len > 0: CC[compiler].linkerExe
|
||||||
elif gMixedMode and gCmd != cmdCompileToCpp: CC[compiler].cppCompiler
|
elif gMixedMode and gCmd != cmdCompileToCpp: CC[compiler].cppCompiler
|
||||||
else: compiler.getCompilerExe
|
else: compiler.getCompilerExe("")
|
||||||
|
|
||||||
proc getCompileCFileCmd*(cfile: Cfile): string =
|
proc getCompileCFileCmd*(cfile: Cfile): string =
|
||||||
var c = cCompiler
|
var c = cCompiler
|
||||||
|
|
@ -596,7 +598,7 @@ proc getCompileCFileCmd*(cfile: Cfile): string =
|
||||||
|
|
||||||
var options = cFileSpecificOptions(cfile.cname)
|
var options = cFileSpecificOptions(cfile.cname)
|
||||||
var exe = getConfigVar(c, ".exe")
|
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 needsExeExt(): exe = addFileExt(exe, "exe")
|
||||||
if optGenDynLib in gGlobalOptions and
|
if optGenDynLib in gGlobalOptions and
|
||||||
|
|
@ -614,7 +616,7 @@ proc getCompileCFileCmd*(cfile: Cfile): string =
|
||||||
compilePattern = joinPath(ccompilerpath, exe)
|
compilePattern = joinPath(ccompilerpath, exe)
|
||||||
else:
|
else:
|
||||||
includeCmd = ""
|
includeCmd = ""
|
||||||
compilePattern = c.getCompilerExe
|
compilePattern = c.getCompilerExe(cfile.cname)
|
||||||
|
|
||||||
var cf = if noAbsolutePaths(): extractFilename(cfile.cname)
|
var cf = if noAbsolutePaths(): extractFilename(cfile.cname)
|
||||||
else: cfile.cname
|
else: cfile.cname
|
||||||
|
|
|
||||||
|
|
@ -178,6 +178,11 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
|
||||||
if result.kind != kind:
|
if result.kind != kind:
|
||||||
localError(n.info, "cannot use symbol of kind '" &
|
localError(n.info, "cannot use symbol of kind '" &
|
||||||
$result.kind & "' as a '" & $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
|
# when there is a nested proc inside a template, semtmpl
|
||||||
# will assign a wrong owner during the first pass over the
|
# will assign a wrong owner during the first pass over the
|
||||||
# template; we must fix it here: see #909
|
# template; we must fix it here: see #909
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ type
|
||||||
next*: PProcCon # used for stacking procedure contexts
|
next*: PProcCon # used for stacking procedure contexts
|
||||||
wasForwarded*: bool # whether the current proc has a separate header
|
wasForwarded*: bool # whether the current proc has a separate header
|
||||||
bracketExpr*: PNode # current bracket expression (for ^ support)
|
bracketExpr*: PNode # current bracket expression (for ^ support)
|
||||||
|
mapping*: TIdTable
|
||||||
|
|
||||||
TInstantiationPair* = object
|
TInstantiationPair* = object
|
||||||
genericSym*: PSym
|
genericSym*: PSym
|
||||||
|
|
@ -147,6 +148,35 @@ proc lastOptionEntry*(c: PContext): POptionEntry =
|
||||||
|
|
||||||
proc popProcCon*(c: PContext) {.inline.} = c.p = c.p.next
|
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 =
|
proc newOptionEntry*(): POptionEntry =
|
||||||
new(result)
|
new(result)
|
||||||
result.options = gOptions
|
result.options = gOptions
|
||||||
|
|
|
||||||
|
|
@ -922,7 +922,8 @@ proc readTypeParameter(c: PContext, typ: PType,
|
||||||
return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info)
|
return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info)
|
||||||
#echo "came here: returned nil"
|
#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
|
case s.kind
|
||||||
of skConst:
|
of skConst:
|
||||||
markUsed(n.info, s)
|
markUsed(n.info, s)
|
||||||
|
|
@ -1093,9 +1094,9 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
return readTypeParameter(c, ty, i, n.info)
|
return readTypeParameter(c, ty, i, n.info)
|
||||||
of tyObject, tyTuple:
|
of tyObject, tyTuple:
|
||||||
if ty.n != nil and ty.n.kind == nkRecList:
|
if ty.n != nil and ty.n.kind == nkRecList:
|
||||||
for field in ty.n:
|
let field = lookupInRecord(ty.n, i)
|
||||||
if field.sym.name == i:
|
if field != nil:
|
||||||
n.typ = newTypeWithSons(c, tyFieldAccessor, @[ty, field.sym.typ])
|
n.typ = newTypeWithSons(c, tyFieldAccessor, @[ty, field.typ])
|
||||||
n.typ.n = copyTree(n)
|
n.typ.n = copyTree(n)
|
||||||
return n
|
return n
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -628,6 +628,9 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||||
of {skProc, skMethod}:
|
of {skProc, skMethod}:
|
||||||
result = n
|
result = n
|
||||||
of skType:
|
of skType:
|
||||||
|
# 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)
|
result = newSymNodeTypeDesc(s, n.info)
|
||||||
of skGenericParam:
|
of skGenericParam:
|
||||||
if s.typ.kind == tyStatic:
|
if s.typ.kind == tyStatic:
|
||||||
|
|
@ -656,7 +659,7 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||||
localError(a.info, errCannotEvalXBecauseIncompletelyDefined,
|
localError(a.info, errCannotEvalXBecauseIncompletelyDefined,
|
||||||
"sizeof")
|
"sizeof")
|
||||||
result = nil
|
result = nil
|
||||||
elif skipTypes(a.typ, typedescInst).kind in
|
elif skipTypes(a.typ, typedescInst+{tyRange}).kind in
|
||||||
IntegralTypes+NilableTypes+{tySet}:
|
IntegralTypes+NilableTypes+{tySet}:
|
||||||
#{tyArray,tyObject,tyTuple}:
|
#{tyArray,tyObject,tyTuple}:
|
||||||
result = newIntNodeT(getSize(a.typ), n)
|
result = newIntNodeT(getSize(a.typ), n)
|
||||||
|
|
|
||||||
|
|
@ -106,11 +106,14 @@ proc freshGenSyms(n: PNode, owner, orig: PSym, symMap: var TIdTable) =
|
||||||
#if n.kind == nkSym and sfGenSym in n.sym.flags:
|
#if n.kind == nkSym and sfGenSym in n.sym.flags:
|
||||||
# if n.sym.owner != orig:
|
# if n.sym.owner != orig:
|
||||||
# echo "symbol ", n.sym.name.s, " orig ", orig, " owner ", n.sym.owner
|
# 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}):
|
# (n.sym.owner == orig or n.sym.owner.kind in {skPackage}):
|
||||||
let s = n.sym
|
let s = n.sym
|
||||||
var x = PSym(idTableGet(symMap, s))
|
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 = copySym(s, false)
|
||||||
x.owner = owner
|
x.owner = owner
|
||||||
idTablePut(symMap, s, x)
|
idTablePut(symMap, s, x)
|
||||||
|
|
|
||||||
|
|
@ -1360,6 +1360,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||||
proc determineType(c: PContext, s: PSym) =
|
proc determineType(c: PContext, s: PSym) =
|
||||||
if s.typ != nil: return
|
if s.typ != nil: return
|
||||||
#if s.magic != mNone: return
|
#if s.magic != mNone: return
|
||||||
|
#if s.ast.isNil: return
|
||||||
discard semProcAux(c, s.ast, s.kind, {}, stepDetermineType)
|
discard semProcAux(c, s.ast, s.kind, {}, stepDetermineType)
|
||||||
|
|
||||||
proc semIterator(c: PContext, n: PNode): PNode =
|
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)
|
result = newSym(kind, considerQuotedIdent(n), c.owner, n.info)
|
||||||
incl(result.flags, sfGenSym)
|
incl(result.flags, sfGenSym)
|
||||||
incl(result.flags, sfShadowed)
|
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) =
|
proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
|
||||||
# locals default to 'gensym':
|
# locals default to 'gensym':
|
||||||
|
|
|
||||||
|
|
@ -297,7 +297,7 @@ proc semOrdinal(c: PContext, n: PNode, prev: PType): PType =
|
||||||
|
|
||||||
proc semTypeIdent(c: PContext, n: PNode): PSym =
|
proc semTypeIdent(c: PContext, n: PNode): PSym =
|
||||||
if n.kind == nkSym:
|
if n.kind == nkSym:
|
||||||
result = n.sym
|
result = getGenSym(c, n.sym)
|
||||||
else:
|
else:
|
||||||
when defined(nimfix):
|
when defined(nimfix):
|
||||||
result = pickSym(c, n, skType)
|
result = pickSym(c, n, skType)
|
||||||
|
|
@ -1319,8 +1319,9 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||||
prev.id = s.typ.id
|
prev.id = s.typ.id
|
||||||
result = prev
|
result = prev
|
||||||
of nkSym:
|
of nkSym:
|
||||||
if n.sym.kind == skType and n.sym.typ != nil:
|
let s = getGenSym(c, n.sym)
|
||||||
var t = n.sym.typ
|
if s.kind == skType and s.typ != nil:
|
||||||
|
var t = s.typ
|
||||||
let alias = maybeAliasType(c, t, prev)
|
let alias = maybeAliasType(c, t, prev)
|
||||||
if alias != nil:
|
if alias != nil:
|
||||||
result = alias
|
result = alias
|
||||||
|
|
@ -1332,7 +1333,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||||
markUsed(n.info, n.sym)
|
markUsed(n.info, n.sym)
|
||||||
styleCheckUse(n.info, n.sym)
|
styleCheckUse(n.info, n.sym)
|
||||||
else:
|
else:
|
||||||
if n.sym.kind != skError: localError(n.info, errTypeExpected)
|
if s.kind != skError: localError(n.info, errTypeExpected)
|
||||||
result = newOrPrevType(tyError, prev, c)
|
result = newOrPrevType(tyError, prev, c)
|
||||||
of nkObjectTy: result = semObjectNode(c, n, prev)
|
of nkObjectTy: result = semObjectNode(c, n, prev)
|
||||||
of nkTupleTy: result = semTuple(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)
|
result = c.semOperand(c, a, flags)
|
||||||
else:
|
else:
|
||||||
result = a
|
result = a
|
||||||
|
considerGenSyms(c, result)
|
||||||
|
|
||||||
proc prepareOperand(c: PContext; a: PNode): PNode =
|
proc prepareOperand(c: PContext; a: PNode): PNode =
|
||||||
if a.typ.isNil:
|
if a.typ.isNil:
|
||||||
result = c.semOperand(c, a, {efDetermineType})
|
result = c.semOperand(c, a, {efDetermineType})
|
||||||
else:
|
else:
|
||||||
result = a
|
result = a
|
||||||
|
considerGenSyms(c, result)
|
||||||
|
|
||||||
proc prepareNamedParam(a: PNode) =
|
proc prepareNamedParam(a: PNode) =
|
||||||
if a.sons[0].kind != nkIdent:
|
if a.sons[0].kind != nkIdent:
|
||||||
|
|
|
||||||
|
|
@ -869,7 +869,12 @@ proc transform(c: PTransf, n: PNode): PTransNode =
|
||||||
else:
|
else:
|
||||||
result = transformSons(c, n)
|
result = transformSons(c, n)
|
||||||
of nkIdentDefs, nkConstDef:
|
of nkIdentDefs, nkConstDef:
|
||||||
|
when true:
|
||||||
result = transformSons(c, n)
|
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:
|
# XXX comment handling really sucks:
|
||||||
if importantComments():
|
if importantComments():
|
||||||
PNode(result).comment = n.comment
|
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:
|
# don't go nuts here: same symbol as string is enough:
|
||||||
result = a.sym.name.id == b.sym.name.id
|
result = a.sym.name.id == b.sym.name.id
|
||||||
of nkIdent: result = a.ident.id == b.ident.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 nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal
|
||||||
of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
|
of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
|
||||||
of nkEmpty, nkNilLit, nkType: result = true
|
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
|
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
|
call from your background thread even if the code you are calling is short
|
||||||
lived.
|
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
|
.. code-block:: nim
|
||||||
echo "Counting to ten: "
|
echo "Counting to ten: "
|
||||||
for i in countup(1, 10):
|
for i in countup(1, 10):
|
||||||
echo $i
|
echo i
|
||||||
# --> Outputs 1 2 3 4 5 6 7 8 9 10 on different lines
|
# --> 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
|
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: "
|
echo "Counting to 10: "
|
||||||
var i = 1
|
var i = 1
|
||||||
while i <= 10:
|
while i <= 10:
|
||||||
echo $i
|
echo i
|
||||||
inc(i) # increment i by 1
|
inc(i) # increment i by 1
|
||||||
# --> Outputs 1 2 3 4 5 6 7 8 9 10 on different lines
|
# --> 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
|
.. code-block:: nim
|
||||||
echo "Counting down from 10 to 1: "
|
echo "Counting down from 10 to 1: "
|
||||||
for i in countdown(10, 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
|
# --> 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 `..
|
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
|
.. code-block:: nim
|
||||||
echo "Counting to ten: "
|
echo "Counting to ten: "
|
||||||
for i in countup(1, 10):
|
for i in countup(1, 10):
|
||||||
echo $i
|
echo i
|
||||||
|
|
||||||
Can a `countup <system.html#countup>`_ proc be written that supports this
|
Can a `countup <system.html#countup>`_ proc be written that supports this
|
||||||
loop? Lets try:
|
loop? Lets try:
|
||||||
|
|
@ -1035,15 +1035,15 @@ there is a difference between the ``$`` and ``repr`` outputs:
|
||||||
myString = "nim"
|
myString = "nim"
|
||||||
myInteger = 42
|
myInteger = 42
|
||||||
myFloat = 3.14
|
myFloat = 3.14
|
||||||
echo $myBool, ":", repr(myBool)
|
echo myBool, ":", repr(myBool)
|
||||||
# --> true:true
|
# --> true:true
|
||||||
echo $myCharacter, ":", repr(myCharacter)
|
echo myCharacter, ":", repr(myCharacter)
|
||||||
# --> n:'n'
|
# --> n:'n'
|
||||||
echo $myString, ":", repr(myString)
|
echo myString, ":", repr(myString)
|
||||||
# --> nim:0x10fa8c050"nim"
|
# --> nim:0x10fa8c050"nim"
|
||||||
echo $myInteger, ":", repr(myInteger)
|
echo myInteger, ":", repr(myInteger)
|
||||||
# --> 42:42
|
# --> 42:42
|
||||||
echo $myFloat, ":", repr(myFloat)
|
echo myFloat, ":", repr(myFloat)
|
||||||
# --> 3.1400000000000001e+00:3.1400000000000001e+00
|
# --> 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
|
north, east, south, west
|
||||||
|
|
||||||
var x = south # `x` is of type `Direction`; its value is `south`
|
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.
|
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
|
.. code-block:: nim
|
||||||
for i in @[3, 4, 5]:
|
for i in @[3, 4, 5]:
|
||||||
echo $i
|
echo i
|
||||||
# --> 3
|
# --> 3
|
||||||
# --> 4
|
# --> 4
|
||||||
# --> 5
|
# --> 5
|
||||||
|
|
|
||||||
1
koch.nim
1
koch.nim
|
|
@ -223,6 +223,7 @@ proc bundleWinTools() =
|
||||||
copyExe("tools/finish".exe, "finish".exe)
|
copyExe("tools/finish".exe, "finish".exe)
|
||||||
removeFile("tools/finish".exe)
|
removeFile("tools/finish".exe)
|
||||||
nimexec("c -o:bin/vccexe.exe tools/vccenv/vccexe")
|
nimexec("c -o:bin/vccexe.exe tools/vccenv/vccexe")
|
||||||
|
when false:
|
||||||
nimexec(r"c --cc:vcc --app:gui -o:bin\downloader.exe -d:ssl --noNimblePath " &
|
nimexec(r"c --cc:vcc --app:gui -o:bin\downloader.exe -d:ssl --noNimblePath " &
|
||||||
r"--path:..\ui tools\downloader.nim")
|
r"--path:..\ui tools\downloader.nim")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,13 +72,11 @@ type
|
||||||
DbConn* = PPGconn ## encapsulates a database connection
|
DbConn* = PPGconn ## encapsulates a database connection
|
||||||
Row* = seq[string] ## a row of a dataset. NULL database values will be
|
Row* = seq[string] ## a row of a dataset. NULL database values will be
|
||||||
## converted to nil.
|
## converted to nil.
|
||||||
InstantRow* = tuple[res: PPGresult, line: int32] ## a handle that can be
|
InstantRow* = object ## a handle that can be
|
||||||
## used to get a row's
|
res: PPGresult ## used to get a row's
|
||||||
## column text on demand
|
line: int ## column text on demand
|
||||||
SqlPrepared* = distinct string ## a identifier for the prepared queries
|
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.} =
|
proc dbError*(db: DbConn) {.noreturn.} =
|
||||||
## raises a DbError exception.
|
## 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.
|
## on demand using []. Returned handle is valid only within iterator body.
|
||||||
var res = setupQuery(db, query, args)
|
var res = setupQuery(db, query, args)
|
||||||
for i in 0..pqNtuples(res)-1:
|
for i in 0..pqNtuples(res)-1:
|
||||||
yield (res: res, line: i)
|
yield InstantRow(res: res, line: i)
|
||||||
pqClear(res)
|
pqClear(res)
|
||||||
|
|
||||||
iterator instantRows*(db: DbConn, stmtName: SqlPrepared,
|
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.
|
## on demand using []. Returned handle is valid only within iterator body.
|
||||||
var res = setupQuery(db, stmtName, args)
|
var res = setupQuery(db, stmtName, args)
|
||||||
for i in 0..pqNtuples(res)-1:
|
for i in 0..pqNtuples(res)-1:
|
||||||
yield (res: res, line: i)
|
yield InstantRow(res: res, line: i)
|
||||||
pqClear(res)
|
pqClear(res)
|
||||||
|
|
||||||
proc `[]`*(row: InstantRow, col: int32): string {.inline.} =
|
proc getColumnType(res: PPGresult, col: int) : DbType =
|
||||||
## returns text for given column of the row
|
## returns DbType for given column in the row
|
||||||
$pqgetvalue(row.res, row.line, col)
|
## 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
|
## returns number of columns in the row
|
||||||
pqNfields(row.res)
|
int(pqNfields(row.res))
|
||||||
|
|
||||||
proc getRow*(db: DbConn, query: SqlQuery,
|
proc getRow*(db: DbConn, query: SqlQuery,
|
||||||
args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
|
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:
|
for i in 1..int(res)-1:
|
||||||
var a = rawMatches[i * 2]
|
var a = rawMatches[i * 2]
|
||||||
var b = rawMatches[i * 2 + 1]
|
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
|
else: matches[i-1] = nil
|
||||||
return rawMatches[0]
|
return rawMatches[0]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ proc reverse*[T](a: var openArray[T], first, last: Natural) =
|
||||||
|
|
||||||
proc reverse*[T](a: var openArray[T]) =
|
proc reverse*[T](a: var openArray[T]) =
|
||||||
## reverses the array `a`.
|
## 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] =
|
proc reversed*[T](a: openArray[T], first: Natural, last: int): seq[T] =
|
||||||
## returns the reverse of the array `a[first..last]`.
|
## returns the reverse of the array `a[first..last]`.
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,9 @@ proc pop*[T](heap: var HeapQueue[T]): T =
|
||||||
proc del*[T](heap: var HeapQueue[T], index: int) =
|
proc del*[T](heap: var HeapQueue[T], index: int) =
|
||||||
## Removes element at `index`, maintaining the heap invariant.
|
## Removes element at `index`, maintaining the heap invariant.
|
||||||
swap(seq[T](heap)[^1], seq[T](heap)[index])
|
swap(seq[T](heap)[^1], seq[T](heap)[index])
|
||||||
seq[T](heap).setLen(heap.len - 1)
|
let newLen = heap.len - 1
|
||||||
|
seq[T](heap).setLen(newLen)
|
||||||
|
if index < newLen:
|
||||||
heap.siftup(index)
|
heap.siftup(index)
|
||||||
|
|
||||||
proc replace*[T](heap: var HeapQueue[T], item: T): T =
|
proc replace*[T](heap: var HeapQueue[T], item: T): T =
|
||||||
|
|
@ -101,16 +103,19 @@ proc pushpop*[T](heap: var HeapQueue[T], item: T): T =
|
||||||
return item
|
return item
|
||||||
|
|
||||||
when isMainModule:
|
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
|
block: # Simple sanity test
|
||||||
var heap = newHeapQueue[int]()
|
var heap = newHeapQueue[int]()
|
||||||
let data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0]
|
let data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0]
|
||||||
for item in data:
|
for item in data:
|
||||||
push(heap, item)
|
push(heap, item)
|
||||||
doAssert(heap[0] == 0)
|
doAssert(heap[0] == 0)
|
||||||
var sort = newSeq[int]()
|
doAssert(heap.toSortedSeq == @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
|
||||||
while heap.len > 0:
|
|
||||||
sort.add(pop(heap))
|
|
||||||
doAssert(sort == @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
|
|
||||||
|
|
||||||
block: # Test del
|
block: # Test del
|
||||||
var heap = newHeapQueue[int]()
|
var heap = newHeapQueue[int]()
|
||||||
|
|
@ -121,11 +126,27 @@ when isMainModule:
|
||||||
doAssert(heap[0] == 1)
|
doAssert(heap[0] == 1)
|
||||||
|
|
||||||
heap.del(seq[int](heap).find(7))
|
heap.del(seq[int](heap).find(7))
|
||||||
heap.del(seq[int](heap).find(5))
|
doAssert(heap.toSortedSeq == @[1, 2, 3, 4, 5, 6, 8, 9])
|
||||||
heap.del(seq[int](heap).find(6))
|
|
||||||
heap.del(seq[int](heap).find(2))
|
|
||||||
|
|
||||||
var sort = newSeq[int]()
|
heap.del(seq[int](heap).find(5))
|
||||||
while heap.len > 0:
|
doAssert(heap.toSortedSeq == @[1, 2, 3, 4, 6, 8, 9])
|
||||||
sort.add(pop(heap))
|
|
||||||
doAssert(sort == @[1, 3, 4, 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:
|
else:
|
||||||
result = ("<your package manager here> install " & p, true)
|
result = ("<your package manager here> install " & p, true)
|
||||||
else:
|
else:
|
||||||
result = ("brew install " & p, true)
|
result = ("brew install " & p, false)
|
||||||
|
|
||||||
proc foreignDep*(foreignPackageName: string) =
|
proc foreignDep*(foreignPackageName: string) =
|
||||||
## Registers 'foreignPackageName' to the internal list of foreign deps.
|
## Registers 'foreignPackageName' to the internal list of foreign deps.
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,15 @@ proc hash*(x: string): Hash =
|
||||||
h = h !& ord(x[i])
|
h = h !& ord(x[i])
|
||||||
result = !$h
|
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 =
|
proc hash*(sBuf: string, sPos, ePos: int): Hash =
|
||||||
## efficient hashing of a string buffer, from starting
|
## efficient hashing of a string buffer, from starting
|
||||||
## position `sPos` to ending position `ePos`
|
## position `sPos` to ending position `ePos`
|
||||||
|
|
@ -239,6 +248,7 @@ proc hash*[A](x: set[A]): Hash =
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
doAssert( hash("aa bb aaaa1234") == hash("aa bb aaaa1234", 0, 13) )
|
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( hashIgnoreCase("aa bb aaaa1234") == hash("aa bb aaaa1234") )
|
||||||
doAssert( hashIgnoreStyle("aa bb aaaa1234") == hashIgnoreCase("aa bb aaaa1234") )
|
doAssert( hashIgnoreStyle("aa bb aaaa1234") == hashIgnoreCase("aa bb aaaa1234") )
|
||||||
let xx = @['H','e','l','l','o']
|
let xx = @['H','e','l','l','o']
|
||||||
|
|
|
||||||
|
|
@ -206,6 +206,8 @@ proc parseHeader*(line: string): tuple[key: string, value: seq[string]] =
|
||||||
inc(i) # skip :
|
inc(i) # skip :
|
||||||
if i < len(line):
|
if i < len(line):
|
||||||
i += parseList(line, result.value, i)
|
i += parseList(line, result.value, i)
|
||||||
|
elif result.key.len > 0:
|
||||||
|
result.value = @[""]
|
||||||
else:
|
else:
|
||||||
result.value = @[]
|
result.value = @[]
|
||||||
|
|
||||||
|
|
@ -319,3 +321,5 @@ when isMainModule:
|
||||||
test = newHttpHeaders()
|
test = newHttpHeaders()
|
||||||
test[key] = value
|
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 {.
|
iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string {.
|
||||||
tags: [ReadDirEffect].} =
|
tags: [ReadDirEffect].} =
|
||||||
## walks over the directory `dir` and yields for each file in `dir`. The
|
## Recursively walks over the directory `dir` and yields for each file in `dir`.
|
||||||
## full path for each file is returned.
|
## The full path for each file is returned. Directories are not returned.
|
||||||
## **Warning**:
|
## **Warning**:
|
||||||
## Modifying the directory structure while the iterator
|
## Modifying the directory structure while the iterator
|
||||||
## is traversing may result in undefined behavior!
|
## is traversing may result in undefined behavior!
|
||||||
|
|
|
||||||
|
|
@ -250,18 +250,18 @@ proc parseInt*(s: string, number: var int, start = 0): int {.
|
||||||
elif result != 0:
|
elif result != 0:
|
||||||
number = int(res)
|
number = int(res)
|
||||||
|
|
||||||
# overflowChecks doesn't work with uint64
|
# overflowChecks doesn't work with BiggestUInt
|
||||||
proc rawParseUInt(s: string, b: var uint64, start = 0): int =
|
proc rawParseUInt(s: string, b: var BiggestUInt, start = 0): int =
|
||||||
var
|
var
|
||||||
res = 0'u64
|
res = 0.BiggestUInt
|
||||||
prev = 0'u64
|
prev = 0.BiggestUInt
|
||||||
i = start
|
i = start
|
||||||
if s[i] == '+': inc(i) # Allow
|
if s[i] == '+': inc(i) # Allow
|
||||||
if s[i] in {'0'..'9'}:
|
if s[i] in {'0'..'9'}:
|
||||||
b = 0
|
b = 0
|
||||||
while s[i] in {'0'..'9'}:
|
while s[i] in {'0'..'9'}:
|
||||||
prev = res
|
prev = res
|
||||||
res = res * 10 + (ord(s[i]) - ord('0')).uint64
|
res = res * 10 + (ord(s[i]) - ord('0')).BiggestUInt
|
||||||
if prev > res:
|
if prev > res:
|
||||||
return 0 # overflowChecks emulation
|
return 0 # overflowChecks emulation
|
||||||
inc(i)
|
inc(i)
|
||||||
|
|
@ -269,13 +269,13 @@ proc rawParseUInt(s: string, b: var uint64, start = 0): int =
|
||||||
b = res
|
b = res
|
||||||
result = i - start
|
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.} =
|
rtl, extern: "npuParseBiggestUInt", noSideEffect.} =
|
||||||
## parses an unsigned integer starting at `start` and stores the value
|
## parses an unsigned integer starting at `start` and stores the value
|
||||||
## into `number`.
|
## into `number`.
|
||||||
## Result is the number of processed chars or 0 if there is no integer
|
## Result is the number of processed chars or 0 if there is no integer
|
||||||
## or overflow detected.
|
## or overflow detected.
|
||||||
var res: uint64
|
var res: BiggestUInt
|
||||||
# use 'res' for exception safety (don't write to 'number' in case of an
|
# use 'res' for exception safety (don't write to 'number' in case of an
|
||||||
# overflow exception):
|
# overflow exception):
|
||||||
result = rawParseUInt(s, res, start)
|
result = rawParseUInt(s, res, start)
|
||||||
|
|
@ -287,12 +287,12 @@ proc parseUInt*(s: string, number: var uint, start = 0): int {.
|
||||||
## into `number`.
|
## into `number`.
|
||||||
## Result is the number of processed chars or 0 if there is no integer or
|
## Result is the number of processed chars or 0 if there is no integer or
|
||||||
## overflow detected.
|
## overflow detected.
|
||||||
var res: uint64
|
var res: BiggestUInt
|
||||||
result = parseBiggestUInt(s, res, start)
|
result = parseBiggestUInt(s, res, start)
|
||||||
if (sizeof(uint) <= 4) and
|
when sizeof(BiggestUInt) > sizeof(uint) and sizeof(uint) <= 4:
|
||||||
(res > 0xFFFF_FFFF'u64):
|
if res > 0xFFFF_FFFF'u64:
|
||||||
raise newException(OverflowError, "overflow")
|
raise newException(OverflowError, "overflow")
|
||||||
elif result != 0:
|
if result != 0:
|
||||||
number = uint(res)
|
number = uint(res)
|
||||||
|
|
||||||
proc parseBiggestFloat*(s: string, number: var BiggestFloat, start = 0): int {.
|
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:
|
if L != s.len or L == 0:
|
||||||
raise newException(ValueError, "invalid unsigned integer: " & s)
|
raise newException(ValueError, "invalid unsigned integer: " & s)
|
||||||
|
|
||||||
proc parseBiggestUInt*(s: string): uint64 {.noSideEffect, procvar,
|
proc parseBiggestUInt*(s: string): BiggestUInt {.noSideEffect, procvar,
|
||||||
rtl, extern: "nsuParseBiggestUInt".} =
|
rtl, extern: "nsuParseBiggestUInt".} =
|
||||||
## Parses a decimal unsigned integer value contained in `s`.
|
## Parses a decimal unsigned integer value contained in `s`.
|
||||||
##
|
##
|
||||||
|
|
|
||||||
|
|
@ -1512,6 +1512,17 @@ type
|
||||||
## compiler supports. Currently this is ``float64``, but it is
|
## compiler supports. Currently this is ``float64``, but it is
|
||||||
## platform-dependant in general.
|
## 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].}
|
{.deprecated: [TAddress: ByteAddress].}
|
||||||
|
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
|
|
|
||||||
|
|
@ -128,13 +128,7 @@ iterator items(stack: ptr GcStack): ptr GcStack =
|
||||||
yield s
|
yield s
|
||||||
s = s.next
|
s = s.next
|
||||||
|
|
||||||
# There will be problems with GC in foreign threads if `threads` option is off or TLS emulation is enabled
|
when declared(threadType):
|
||||||
const allowForeignThreadGc = compileOption("threads") and not compileOption("tlsEmulation")
|
|
||||||
|
|
||||||
when allowForeignThreadGc:
|
|
||||||
var
|
|
||||||
localGcInitialized {.rtlThreadVar.}: bool
|
|
||||||
|
|
||||||
proc setupForeignThreadGc*() {.gcsafe.} =
|
proc setupForeignThreadGc*() {.gcsafe.} =
|
||||||
## Call this if you registered a callback that will be run from a thread not
|
## 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
|
## 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``
|
## This function is available only when ``--threads:on`` and ``--tlsEmulation:off``
|
||||||
## switches are used
|
## switches are used
|
||||||
if not localGcInitialized:
|
if threadType == ThreadType.None:
|
||||||
localGcInitialized = true
|
|
||||||
initAllocator()
|
initAllocator()
|
||||||
var stackTop {.volatile.}: pointer
|
var stackTop {.volatile.}: pointer
|
||||||
setStackBottom(addr(stackTop))
|
setStackBottom(addr(stackTop))
|
||||||
initGC()
|
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:
|
else:
|
||||||
template setupForeignThreadGc*() =
|
template setupForeignThreadGc*() =
|
||||||
{.error: "setupForeignThreadGc is available only when ``--threads:on`` and ``--tlsEmulation:off`` are used".}
|
{.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 --------------------------------------
|
# ----------------- stack management --------------------------------------
|
||||||
# inspired from Smart Eiffel
|
# inspired from Smart Eiffel
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ proc checkErr(f: File) =
|
||||||
{.push stackTrace:off, profiler:off.}
|
{.push stackTrace:off, profiler:off.}
|
||||||
proc readBuffer(f: File, buffer: pointer, len: Natural): int =
|
proc readBuffer(f: File, buffer: pointer, len: Natural): int =
|
||||||
result = c_fread(buffer, 1, len, f)
|
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 =
|
proc readBytes(f: File, a: var openArray[int8|uint8], start, len: Natural): int =
|
||||||
result = readBuffer(f, addr(a[start]), len)
|
result = readBuffer(f, addr(a[start]), len)
|
||||||
|
|
@ -118,8 +118,9 @@ const
|
||||||
proc close*(f: File) = discard c_fclose(f)
|
proc close*(f: File) = discard c_fclose(f)
|
||||||
proc readChar(f: File): char =
|
proc readChar(f: File): char =
|
||||||
let x = c_fgetc(f)
|
let x = c_fgetc(f)
|
||||||
if x == -1: raiseEOF()
|
if x < 0:
|
||||||
checkErr(f)
|
checkErr(f)
|
||||||
|
raiseEOF()
|
||||||
result = char(x)
|
result = char(x)
|
||||||
|
|
||||||
proc flushFile*(f: File) = discard c_fflush(f)
|
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
|
# fgets doesn't append an \L
|
||||||
c_memset(addr line.string[pos], '\L'.ord, sp)
|
c_memset(addr line.string[pos], '\L'.ord, sp)
|
||||||
var fgetsSuccess = c_fgets(addr line.string[pos], sp, f) != nil
|
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)
|
let m = c_memchr(addr line.string[pos], '\L'.ord, sp)
|
||||||
if m != nil:
|
if m != nil:
|
||||||
# \l found: Could be our own or the one by fgets, in any case, we're done
|
# \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) =
|
proc write(f: File, i: int) =
|
||||||
when sizeof(int) == 8:
|
when sizeof(int) == 8:
|
||||||
c_fprintf(f, "%lld", i)
|
if c_fprintf(f, "%lld", i) < 0: checkErr(f)
|
||||||
else:
|
else:
|
||||||
c_fprintf(f, "%ld", i)
|
if c_fprintf(f, "%ld", i) < 0: checkErr(f)
|
||||||
|
|
||||||
proc write(f: File, i: BiggestInt) =
|
proc write(f: File, i: BiggestInt) =
|
||||||
when sizeof(BiggestInt) == 8:
|
when sizeof(BiggestInt) == 8:
|
||||||
c_fprintf(f, "%lld", i)
|
if c_fprintf(f, "%lld", i) < 0: checkErr(f)
|
||||||
else:
|
else:
|
||||||
c_fprintf(f, "%ld", i)
|
if c_fprintf(f, "%ld", i) < 0: checkErr(f)
|
||||||
|
|
||||||
proc write(f: File, b: bool) =
|
proc write(f: File, b: bool) =
|
||||||
if b: write(f, "true")
|
if b: write(f, "true")
|
||||||
else: write(f, "false")
|
else: write(f, "false")
|
||||||
proc write(f: File, r: float32) = c_fprintf(f, "%g", r)
|
proc write(f: File, r: float32) =
|
||||||
proc write(f: File, r: BiggestFloat) = c_fprintf(f, "%g", r)
|
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, c: char) = discard c_putc(ord(c), f)
|
||||||
proc write(f: File, a: varargs[string, `$`]) =
|
proc write(f: File, a: varargs[string, `$`]) =
|
||||||
|
|
@ -212,7 +215,10 @@ proc rawFileSize(file: File): int =
|
||||||
discard c_fseek(file, clong(oldPos), 0)
|
discard c_fseek(file, clong(oldPos), 0)
|
||||||
|
|
||||||
proc endOfFile(f: File): bool =
|
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 =
|
proc readAllFile(file: File, len: int): string =
|
||||||
# We acquire the filesize beforehand and hope it doesn't change.
|
# We acquire the filesize beforehand and hope it doesn't change.
|
||||||
|
|
|
||||||
|
|
@ -285,7 +285,19 @@ when useStackMaskHack:
|
||||||
when not defined(useNimRtl):
|
when not defined(useNimRtl):
|
||||||
when not useStackMaskHack:
|
when not useStackMaskHack:
|
||||||
#when not defined(createNimRtl): initStackBottom()
|
#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:
|
when emulatedThreadVars:
|
||||||
if nimThreadVarsSize() > sizeof(ThreadLocalStorage):
|
if nimThreadVarsSize() > sizeof(ThreadLocalStorage):
|
||||||
|
|
@ -442,6 +454,8 @@ proc threadProcWrapStackFrame[TArg](thrd: ptr Thread[TArg]) =
|
||||||
# init the GC for refc/markandsweep
|
# init the GC for refc/markandsweep
|
||||||
setStackBottom(addr(p))
|
setStackBottom(addr(p))
|
||||||
initGC()
|
initGC()
|
||||||
|
when declared(threadType):
|
||||||
|
threadType = ThreadType.NimThread
|
||||||
when declared(registerThread):
|
when declared(registerThread):
|
||||||
thrd.stackBottom = addr(thrd)
|
thrd.stackBottom = addr(thrd)
|
||||||
registerThread(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
|
This repository contains the Nim compiler, Nim's stdlib, tools and documentation.
|
||||||
documentation. For more information about Nim, including downloads
|
For more information about Nim, including downloads and documentation for
|
||||||
and documentation for the latest release, check out
|
the latest release, check out [Nim's website][nim-site].
|
||||||
[Nim's website](http://nim-lang.org).
|
|
||||||
|
## 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
|
||||||
Compiling the Nim compiler is quite straightforward. Because
|
The compiler currently officially supports the following platform and
|
||||||
the Nim compiler itself is written in the Nim programming language
|
architecture combinations:
|
||||||
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:
|
|
||||||
|
|
||||||
* Windows (Windows XP or greater) - x86 and x86_64
|
* Windows (Windows XP or greater) - x86 and x86_64
|
||||||
* Linux (most, if not all, distributions) - x86, x86_64, ppc64 and armv6l
|
* 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
|
First, the C source of an older version of the Nim compiler is needed to
|
||||||
are: clang, Visual C++, Intel's C++ compiler
|
bootstrap the latest version because the Nim compiler itself is written in the
|
||||||
* git or wget
|
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
|
Next, to build from source you will need:
|
||||||
that the ``build-essentials`` package is installed also.
|
|
||||||
|
|
||||||
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
|
$ git clone https://github.com/nim-lang/Nim.git
|
||||||
$ cd Nim
|
$ cd Nim
|
||||||
$ git clone --depth 1 https://github.com/nim-lang/csources
|
$ git clone --depth 1 https://github.com/nim-lang/csources.git
|
||||||
$ cd csources && sh build.sh
|
$ cd csources
|
||||||
$ cd ..
|
$ sh build.sh
|
||||||
|
$ cd ../
|
||||||
$ bin/nim c koch
|
$ bin/nim c koch
|
||||||
$ ./koch boot -d:release
|
$ ./koch boot -d:release
|
||||||
```
|
```
|
||||||
|
|
||||||
You should then add the ``bin`` directory to your PATH, to make it easily
|
Finally, once you have finished the build steps (on Windows, Mac or Linux) you
|
||||||
executable on your system.
|
should add the ``bin`` directory to your PATH.
|
||||||
|
|
||||||
The above steps can be performed on Windows in a similar fashion, the
|
## Koch
|
||||||
``build.bat`` and ``build64.bat`` (for x86_64 systems) are provided to be used
|
``koch`` is the build tool used to build various parts of Nim and to generate
|
||||||
instead of ``build.sh``.
|
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
|
Assuming that you added Nim's ``bin`` directory to your PATH, you may execute
|
||||||
documented in [doc/koch.rst](doc/koch.rst).
|
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
|
||||||
[Nimble](https://github.com/nim-lang/nimble) is Nim's package manager. For the
|
``nimble`` is Nim's package manager and it can be acquired from the
|
||||||
source based installations, where you added Nim's ``bin`` directory to your PATH,
|
[``nim-lang/nimble``][nimble-repo] repository. Assuming that you added Nim's
|
||||||
the easiest way of installing Nimble is via:
|
``bin`` directory to your PATH, you may install Nimble from source by running
|
||||||
|
``koch nimble`` within the root of the cloned repository.
|
||||||
```
|
|
||||||
$ 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)
|
|
||||||
|
|
||||||
## Contributing
|
## 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/)
|
We welcome everyone's contributions to Nim independent of how small or how large
|
||||||
[](https://www.bountysource.com/teams/nim)
|
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
|
||||||
We welcome everyone's contributions to Nim. No matter how small or large
|
started contributing, you should familiarize yourself with the repository structure:
|
||||||
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:
|
|
||||||
|
|
||||||
* ``bin/``, ``build/`` - these directories are empty, but are used when Nim is built.
|
* ``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
|
* ``compiler/`` - the compiler source code. Also includes nimfix, and plugins within
|
||||||
directory implement the compiler. This also includes nimfix, and plugins
|
``compiler/nimfix`` and ``compiler/plugins`` respectively. Nimsuggest was moved to
|
||||||
which live in ``compiler/nimfix`` and ``compiler/plugins``
|
the [``nim-lang/nimsuggest``][nimsuggest-repo] repository, though it previously also
|
||||||
respectively. Nimsuggest used to live in the ``compiler`` directory also,
|
lived within the ``compiler/`` directory.
|
||||||
but was moved to https://github.com/nim-lang/nimsuggest.
|
|
||||||
* ``config/`` - the configuration for the compiler and documentation generator.
|
* ``config/`` - the configuration for the compiler and documentation generator.
|
||||||
* ``doc/`` - the documentation files in reStructuredText format.
|
* ``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.
|
* ``pure/`` - modules in the standard library written in pure Nim.
|
||||||
* ``impure/`` - modules in the standard library written in pure Nim which
|
* ``impure/`` - modules in the standard library written in pure Nim with
|
||||||
depend on libraries written in other languages.
|
dependencies written in other languages.
|
||||||
* ``wrappers/`` - modules which wrap libraries written in other languages.
|
* ``wrappers/`` - modules which wrap dependencies written in other languages.
|
||||||
* ``tests/`` - contains tests for the compiler and standard library, organised by
|
* ``tests/`` - contains categorized tests for the compiler and standard library.
|
||||||
category.
|
* ``tools/`` - the tools including ``niminst`` and ``nimweb`` (mostly invoked via
|
||||||
* ``tools/`` - the tools including ``niminst`` and ``nimweb``, most of these are invoked
|
``koch``).
|
||||||
via ``koch``.
|
* ``web/`` - [the Nim website][nim-site].
|
||||||
* ``web/`` - the Nim website (http://nim-lang.org).
|
* ``koch.nim`` - tool used to bootstrap Nim, generate C sources, build the website,
|
||||||
* ``koch.nim`` - tool used to bootstrap Nim, generate C sources, build the website, documentation
|
and generate the documentation.
|
||||||
and more.
|
|
||||||
|
|
||||||
Most importantly, the ``koch`` tool can be used to run the test suite. To do so compile it first
|
If you are not familiar with making a pull request using GitHub and/or git, please
|
||||||
by executing ``nim c koch``, then execute ``./koch tests``. The test suite takes a while to run,
|
read [this guide][pull-request-instructions].
|
||||||
but you can run specific tests by specifying a category to run, for example ``./koch tests cat async``.
|
|
||||||
|
|
||||||
Make sure that the tests all pass before
|
Ideally you should make sure that all tests pass before submitting a pull request.
|
||||||
[submitting your pull request](https://help.github.com/articles/using-pull-requests/).
|
However, if you are short on time, you can just run the tests specific to your
|
||||||
If you're short on time, you can
|
changes by only running the corresponding categories of tests. Travis CI verifies
|
||||||
just run the tests specific to your change. Just run the category which corresponds to the change
|
that all tests pass before allowing the pull request to be accepted, so only
|
||||||
you've made. When you create your pull request, Travis CI will verify that all the tests pass
|
running specific tests should be harmless.
|
||||||
anyway.
|
|
||||||
|
|
||||||
If you're looking for things to do, take a look at our
|
If you're looking for ways to contribute, please look at our [issue tracker][nim-issues].
|
||||||
[issue tracker](https://github.com/nim-lang/Nim/issues). There is always plenty of issues
|
There are always plenty of issues labelled [``Easy``][nim-issues-easy]; these should
|
||||||
labelled [``Easy``](https://github.com/nim-lang/Nim/labels/Easy), these should be a good
|
be a good starting point for an initial contribution to Nim.
|
||||||
starting point if this is your first contribution to Nim.
|
|
||||||
|
|
||||||
You can also help with the development of Nim by making donations. You can do so
|
You can also help with the development of Nim by making donations. Donations can be
|
||||||
in many ways:
|
made using:
|
||||||
|
|
||||||
* [Gratipay](https://gratipay.com/nim/)
|
* [Gratipay][nim-gratipay]
|
||||||
* [Bountysource](https://www.bountysource.com/teams/nim)
|
* [Bountysource][nim-bountysource]
|
||||||
* Bitcoin - 1BXfuKM2uvoD6mbx4g5xM3eQhLzkCK77tJ
|
* [Bitcoin][nim-bitcoin]
|
||||||
|
|
||||||
Finally, if you have any questions feel free to submit a question on the issue tracker,
|
If you have any questions feel free to submit a question on the
|
||||||
on the [Nim forum](http://forum.nim-lang.org), or on IRC.
|
[Nim forum][nim-forum], or via IRC on [the \#nim channel][nim-irc].
|
||||||
|
|
||||||
## License
|
## License
|
||||||
The compiler and the standard library are licensed under the MIT license,
|
The compiler and the standard library are licensed under the MIT license, except
|
||||||
except for some modules where the documentation suggests otherwise. This means
|
for some modules which explicitly state otherwise. As a result you may use any
|
||||||
that you can use any license for your own programs developed with Nim,
|
compatible license (essentially any license) for your own programs developed with
|
||||||
allowing you to create commercial applications.
|
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.
|
Copyright © 2006-2017 Andreas Rumpf, all rights reserved.
|
||||||
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.
|
q(B()) # This call reported as ambiguous.
|
||||||
|
|
||||||
# bug #2219
|
# bug #2219
|
||||||
template testPred(a: expr) =
|
template testPred(a: untyped) =
|
||||||
block:
|
block:
|
||||||
type A = object of RootObj
|
type A = object of RootObj
|
||||||
type B = object of A
|
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 =
|
template mathPerComponent(op: untyped): untyped =
|
||||||
proc op*[N,T](v,u: array[N,T]): array[N,T] {.inline.} =
|
proc op*[N,T](v,u: array[N,T]): array[N,T] {.inline.} =
|
||||||
|
|
@ -19,3 +26,24 @@ proc foo(): void =
|
||||||
echo repr(v1 *** v2)
|
echo repr(v1 *** v2)
|
||||||
|
|
||||||
foo()
|
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:
|
# Test that parameters are properly gensym'ed finally:
|
||||||
|
|
||||||
template genNodeKind(kind, name: expr): stmt =
|
template genNodeKind(kind, name: untyped) =
|
||||||
proc name*(children: varargs[PNimrodNode]): PNimrodNode {.compiletime.}=
|
proc name*(children: varargs[NimNode]): NimNode {.compiletime.}=
|
||||||
result = newNimNode(kind)
|
result = newNimNode(kind)
|
||||||
for c in children:
|
for c in children:
|
||||||
result.add(c)
|
result.add(c)
|
||||||
|
|
@ -22,7 +22,7 @@ type Something = object
|
||||||
|
|
||||||
proc testA(x: Something) = discard
|
proc testA(x: Something) = discard
|
||||||
|
|
||||||
template def(name: expr) {.immediate.} =
|
template def(name: untyped) =
|
||||||
proc testB[T](reallyUniqueName: T) =
|
proc testB[T](reallyUniqueName: T) =
|
||||||
`test name`(reallyUniqueName)
|
`test name`(reallyUniqueName)
|
||||||
def A
|
def A
|
||||||
|
|
@ -35,8 +35,7 @@ testB(x)
|
||||||
# Test that templates in generics still work (regression to fix the
|
# Test that templates in generics still work (regression to fix the
|
||||||
# regression...)
|
# regression...)
|
||||||
|
|
||||||
template forStatic(index: expr, slice: Slice[int], predicate: stmt):
|
template forStatic(index, slice, predicate: untyped) =
|
||||||
stmt {.immediate.} =
|
|
||||||
const a = slice.a
|
const a = slice.a
|
||||||
const b = slice.b
|
const b = slice.b
|
||||||
when a <= b:
|
when a <= b:
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,7 @@ proc gcTests(r: var TResults, cat: Category, options: string) =
|
||||||
testSpec r, makeTest("tests/gc" / filename, options &
|
testSpec r, makeTest("tests/gc" / filename, options &
|
||||||
" -d:release --gc:boehm", cat, actionRun)
|
" -d:release --gc:boehm", cat, actionRun)
|
||||||
|
|
||||||
|
testWithoutBoehm "foreign_thr"
|
||||||
test "gcemscripten"
|
test "gcemscripten"
|
||||||
test "growobjcrash"
|
test "growobjcrash"
|
||||||
test "gcbench"
|
test "gcbench"
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,235 @@ for i in 1..10:
|
||||||
discard db.getRow(
|
discard db.getRow(
|
||||||
SqlQuery("INSERT INTO tags(name) VALUES(\'$1\') RETURNING id" % [name]))
|
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!")
|
echo("All tests succeeded!")
|
||||||
|
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -209,6 +209,9 @@ proc main() =
|
||||||
of Manual:
|
of Manual:
|
||||||
echo "After download, move it to: ", dest
|
echo "After download, move it to: ", dest
|
||||||
if askBool("Download successful? (y/n) "):
|
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
|
if unzip(): retry = true
|
||||||
of Failure: discard
|
of Failure: discard
|
||||||
of Success:
|
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
|
logo, name, url, this_month, all_time, since, level
|
||||||
,bogen,,0,1010,"Jul 23, 2016",1
|
,bogen,,0,1010,"Jul 23, 2016",1
|
||||||
,mikra,,0,400,"Apr 28, 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
|
,avsej,,0,110,"Jun 10, 2016",1
|
||||||
,WilRubin,,0,100,"Aug 11, 2015",1
|
,WilRubin,,0,100,"Aug 11, 2015",1
|
||||||
,"Benny Luypaert",,0,100,"Apr 10, 2016",1
|
,"Benny Luypaert",,0,100,"Apr 10, 2016",1
|
||||||
,"Chris Heller",,0,100,"May 19, 2016",1
|
|
||||||
,PhilipWitte,,0,100,"Aug 5, 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
|
,Boxifier,,0,75,"Apr 12, 2016",1
|
||||||
,iolloyd,,0,75,"Apr 29, 2016",1
|
,iolloyd,,0,75,"Apr 29, 2016",1
|
||||||
|
,btbytes,,0,70,"Apr 6, 2016",1
|
||||||
,rb01,,0,50,"May 4, 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
|
,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
|
,martinbbjerregaard,,0,35,"Jun 9, 2016",1
|
||||||
,RationalG,,0,30,"Jun 17, 2016",1
|
,RationalG,,0,30,"Jun 17, 2016",1
|
||||||
,benbve,,0,30,"Jul 12, 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
|
,"Landon Bass",,0,25,"Jun 7, 2016",1
|
||||||
,jimrichards,,0,25,"Jun 8, 2016",1
|
,jimrichards,,0,25,"Jun 8, 2016",1
|
||||||
,jjzazuet,,0,25,"Jul 10, 2016",1
|
,jjzazuet,,0,25,"Jul 10, 2016",1
|
||||||
,moigagoo,,0,20,"May 13, 2016",1
|
|
||||||
,kteza1,,0,20,"Jun 10, 2016",1
|
,kteza1,,0,20,"Jun 10, 2016",1
|
||||||
,tomkeus,,0,20,"Sep 4, 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
|
,mirek,,0,15,"Apr 9, 2016",1
|
||||||
,DateinAsia,,0,15,"Jul 30, 2016",1
|
,DateinAsia,,0,15,"Jul 30, 2016",1
|
||||||
,rickc,,0,15,"Jul 31, 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
|
,Blumenversand,,0,10,"Jul 21, 2016",1
|
||||||
,cinnabardk,,0,10,"Aug 6, 2016",1
|
,cinnabardk,,0,10,"Aug 6, 2016",1
|
||||||
,reddec,,0,10,"Aug 31, 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
|
,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.
|
- 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
|
``EOFError`` is a subtype of ``IOError`` and so it's easier to distinguish
|
||||||
between "error during read" and "error due to EOF".
|
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
|
Library Additions
|
||||||
-----------------
|
-----------------
|
||||||
|
|
|
||||||
|
|
@ -1,34 +1,40 @@
|
||||||
logo, name, url, this_month, all_time, since, level
|
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/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,"Jun 20, 2016",250
|
assets/bountysource/xored.svg,"Xored Software, Inc.",http://xored.com/,250,1000,250,2000,"Jun 20, 2016",250
|
||||||
,shkolnick-kun,https://github.com/shkolnick-kun,75,225,"Jul 6, 2016",75
|
,Varriount,https://github.com/Varriount,250,750,"Nov 18, 2016",250
|
||||||
,flyx,http://flyx.org,35,210,"Apr 7, 2016",75
|
,flyx,http://flyx.org,35,350,"Apr 7, 2016",75
|
||||||
,"Yuriy Glukhov",,25,150,"Apr 6, 2016",25
|
,"Yuriy Glukhov",,25,250,"Apr 6, 2016",25
|
||||||
,endragor,https://github.com/endragor,25,150,"Apr 7, 2016",25
|
,endragor,https://github.com/endragor,25,250,"Apr 7, 2016",25
|
||||||
,FedericoCeratto,http://firelet.net,25,150,"Apr 7, 2016",25
|
,FedericoCeratto,http://firelet.net,25,250,"Apr 7, 2016",25
|
||||||
,"Adrian Veith",,25,150,"Apr 20, 2016",25
|
,"Adrian Veith",,25,250,"Apr 20, 2016",25
|
||||||
,skunkiferous,https://github.com/skunkiferous,100,100,"Oct 2, 2016",150
|
,euantorano,http://euantorano.co.uk,25,200,"Jun 7, 2016",25
|
||||||
,euantorano,http://euantorano.co.uk,25,100,"Jun 7, 2016",25
|
,xxlabaza,https://github.com/xxlabaza,25,170,"Jun 17, 2016",25
|
||||||
,xxlabaza,https://github.com/xxlabaza,25,95,"Jun 17, 2016",25
|
,devted,https://github.com/devted,25,100,"Oct 19, 2016",25
|
||||||
,btbytes,https://www.btbytes.com/,10,60,"Apr 6, 2016",10
|
,"pyloor ",https://schwarz-weiss.cc/,10,95,"May 16, 2016",10
|
||||||
,niebaopeng,https://github.com/niebaopeng,10,50,"Apr 15, 2016",10
|
,niebaopeng,https://github.com/niebaopeng,10,90,"Apr 15, 2016",10
|
||||||
,"Jonathan Arnett",,10,50,"May 20, 2016",10
|
,zolern,https://github.com/zolern,10,80,"Apr 15, 2016",10
|
||||||
,swalf,https://github.com/swalf,5,45,"May 9, 2016",5
|
,"Oskari Timperi",,10,80,"Jun 8, 2016",10
|
||||||
,zolern,https://github.com/zolern,10,40,"Apr 15, 2016",10
|
,jcosborn,https://github.com/jcosborn,25,75,"Nov 21, 2016",25
|
||||||
,"pyloor ",https://schwarz-weiss.cc/,10,40,"May 16, 2016",10
|
,swalf,https://github.com/swalf,5,65,"May 9, 2016",5
|
||||||
,zachaysan,http://venn.lc,10,40,"Jun 7, 2016",10
|
,"Handojo Goenadi",,5,55,"Apr 19, 2016",5
|
||||||
,"Matthew Baulch",,10,40,"Jun 7, 2016",10
|
,cpunion,https://github.com/cpunion,10,50,"Sep 9, 2016",10
|
||||||
,"Oskari Timperi",,10,40,"Jun 8, 2016",10
|
,D-L,https://github.com/D-L,5,50,"Apr 7, 2016",5
|
||||||
,"Handojo Goenadi",,5,35,"Apr 19, 2016",5
|
,moigagoo,http://sloth-ci.com,10,40,"May 13, 2016",10
|
||||||
,"Matthew Newton",,5,30,"Apr 20, 2016",5
|
,enthus1ast,http://code0.xyz/,10,40,"Oct 28, 2016",10
|
||||||
,johnnovak,http://www.johnnovak.net/,5,30,"Apr 29, 2016",5
|
,RyanMarcus,http://rmarcus.info,5,35,"Jul 19, 2016",5
|
||||||
,RyanMarcus,http://rmarcus.info,5,15,"Jul 19, 2016",5
|
,lenzenmi,https://github.com/lenzenmi,5,35,"Jul 28, 2016",5
|
||||||
,lenzenmi,https://github.com/lenzenmi,5,15,"Jul 28, 2016",5
|
,"Christian Bagley",,10,30,"Oct 11, 2016",10
|
||||||
,cpunion,https://github.com/cpunion,10,10,"Sep 9, 2016",10
|
,pandada8,https://github.com/pandada8,5,30,"Aug 12, 2016",5
|
||||||
,pandada8,https://github.com/pandada8,5,10,"Aug 12, 2016",5
|
,abeaumont,http://alfredobeaumont.org/blog,5,30,"Aug 12, 2016",5
|
||||||
,abeaumont,http://alfredobeaumont.org/blog,5,10,"Aug 12, 2016",5
|
,opendragon,http://www.opendragon.com,25,25,"Jan 18, 2017",25
|
||||||
,"Svend Knudsen",,1,6,"Apr 11, 2016",1
|
,"Eric Raible",,10,20,"Dec 23, 2016",10
|
||||||
,"Michael D. Sklaroff",,1,6,"Apr 27, 2016",1
|
,zefciu,http://pythonista.net,10,20,"Dec 29, 2016",10
|
||||||
,csoriano89,https://github.com/csoriano89,5,5,"Sep 7, 2016",5
|
,"Andrey ",https://github.com/Andrey,5,20,"Oct 10, 2016",5
|
||||||
,nicck,,1,2,"Aug 9, 2016",1
|
,syrol,https://github.com/syrol,5,10,"Dec 12, 2016",5
|
||||||
,campbellr,,1,1,"Sep 4, 2016",1
|
,"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.
|
Loading…
Add table
Add a link
Reference in a new issue