Merge remote-tracking branch 'upstream/devel' into devel

This commit is contained in:
PhilipWitte 2015-02-19 21:16:39 -08:00
commit 8c5a47ee2b
148 changed files with 750 additions and 584 deletions

View file

@ -314,7 +314,7 @@ type
# XXX put this into an include file to avoid this issue! # XXX put this into an include file to avoid this issue!
tyNone, tyBool, tyChar, tyNone, tyBool, tyChar,
tyEmpty, tyArrayConstr, tyNil, tyExpr, tyStmt, tyTypeDesc, tyEmpty, tyArrayConstr, tyNil, tyExpr, tyStmt, tyTypeDesc,
tyGenericInvokation, # ``T[a, b]`` for types to invoke tyGenericInvocation, # ``T[a, b]`` for types to invoke
tyGenericBody, # ``T[a, b, body]`` last parameter is the body tyGenericBody, # ``T[a, b, body]`` last parameter is the body
tyGenericInst, # ``T[a, b, realInstance]`` instantiated generic type tyGenericInst, # ``T[a, b, realInstance]`` instantiated generic type
# realInstance will be a concrete type like tyObject # realInstance will be a concrete type like tyObject
@ -859,7 +859,7 @@ const
OverloadableSyms* = {skProc, skMethod, skIterator, skClosureIterator, OverloadableSyms* = {skProc, skMethod, skIterator, skClosureIterator,
skConverter, skModule, skTemplate, skMacro} skConverter, skModule, skTemplate, skMacro}
GenericTypes*: TTypeKinds = {tyGenericInvokation, tyGenericBody, GenericTypes*: TTypeKinds = {tyGenericInvocation, tyGenericBody,
tyGenericParam} tyGenericParam}
StructuralEquivTypes*: TTypeKinds = {tyArrayConstr, tyNil, tyTuple, tyArray, StructuralEquivTypes*: TTypeKinds = {tyArrayConstr, tyNil, tyTuple, tyArray,
@ -1298,6 +1298,12 @@ proc initIdTable(x: var TIdTable) =
x.counter = 0 x.counter = 0
newSeq(x.data, StartSize) newSeq(x.data, StartSize)
proc resetIdTable*(x: var TIdTable) =
x.counter = 0
# clear and set to old initial size:
setLen(x.data, 0)
setLen(x.data, StartSize)
proc initObjectSet(x: var TObjectSet) = proc initObjectSet(x: var TObjectSet) =
x.counter = 0 x.counter = 0
newSeq(x.data, StartSize) newSeq(x.data, StartSize)
@ -1350,7 +1356,7 @@ proc propagateToOwner*(owner, elem: PType) =
const HaveTheirOwnEmpty = {tySequence, tySet} const HaveTheirOwnEmpty = {tySequence, tySet}
owner.flags = owner.flags + (elem.flags * {tfHasMeta}) owner.flags = owner.flags + (elem.flags * {tfHasMeta})
if tfNotNil in elem.flags: if tfNotNil in elem.flags:
if owner.kind in {tyGenericInst, tyGenericBody, tyGenericInvokation}: if owner.kind in {tyGenericInst, tyGenericBody, tyGenericInvocation}:
owner.flags.incl tfNotNil owner.flags.incl tfNotNil
elif owner.kind notin HaveTheirOwnEmpty: elif owner.kind notin HaveTheirOwnEmpty:
owner.flags.incl tfNeedsInit owner.flags.incl tfNeedsInit

View file

@ -119,8 +119,8 @@ proc hashType(c: var MD5Context, t: PType) =
c.hashSym(t.sym) c.hashSym(t.sym)
case t.kind case t.kind
of tyGenericBody, tyGenericInst, tyGenericInvokation: of tyGenericBody, tyGenericInst, tyGenericInvocation:
for i in countup(0, sonsLen(t) -1 -ord(t.kind != tyGenericInvokation)): for i in countup(0, sonsLen(t) -1 -ord(t.kind != tyGenericInvocation)):
c.hashType t.sons[i] c.hashType t.sons[i]
of tyUserTypeClass: of tyUserTypeClass:
internalAssert t.sym != nil and t.sym.owner != nil internalAssert t.sym != nil and t.sym.owner != nil

View file

@ -1390,7 +1390,7 @@ proc genSwap(p: BProc, e: PNode, d: var TLoc) =
genAssignment(p, b, tmp, {}) genAssignment(p, b, tmp, {})
proc rdSetElemLoc(a: TLoc, setType: PType): PRope = proc rdSetElemLoc(a: TLoc, setType: PType): PRope =
# read a location of an set element; it may need a substraction operation # read a location of an set element; it may need a subtraction operation
# before the set operation # before the set operation
result = rdCharLoc(a) result = rdCharLoc(a)
assert(setType.kind == tySet) assert(setType.kind == tySet)

View file

@ -223,7 +223,7 @@ proc processMergeInfo(L: var TBaseLexer, m: BModule) =
of "typeInfo": readIntSet(L, m.typeInfoMarker) of "typeInfo": readIntSet(L, m.typeInfoMarker)
of "labels": m.labels = decodeVInt(L.buf, L.bufpos) of "labels": m.labels = decodeVInt(L.buf, L.bufpos)
of "hasframe": m.frameDeclared = decodeVInt(L.buf, L.bufpos) != 0 of "hasframe": m.frameDeclared = decodeVInt(L.buf, L.bufpos) != 0
else: internalError("ccgmerge: unkown key: " & k) else: internalError("ccgmerge: unknown key: " & k)
when not defined(nimhygiene): when not defined(nimhygiene):
{.pragma: inject.} {.pragma: inject.}

View file

@ -96,7 +96,7 @@ proc getUniqueType*(key: PType): PType =
#if obj.sym != nil and obj.sym.name.s == "TOption": #if obj.sym != nil and obj.sym.name.s == "TOption":
# echo "for ", typeToString(key), " I returned " # echo "for ", typeToString(key), " I returned "
# debug result # debug result
of tyArrayConstr, tyGenericInvokation, tyGenericBody, of tyArrayConstr, tyGenericInvocation, tyGenericBody,
tyOpenArray, tyArray, tySet, tyRange, tyTuple, tyOpenArray, tyArray, tySet, tyRange, tyTuple,
tyPtr, tyRef, tySequence, tyForward, tyVarargs, tyProxy, tyVar: tyPtr, tyRef, tySequence, tyForward, tyVarargs, tyProxy, tyVar:
# tuples are quite horrible as C does not support them directly and # tuples are quite horrible as C does not support them directly and

View file

@ -395,7 +395,7 @@ proc localVarDecl(p: BProc; s: PSym): PRope =
proc assignLocalVar(p: BProc, s: PSym) = proc assignLocalVar(p: BProc, s: PSym) =
#assert(s.loc.k == locNone) # not yet assigned #assert(s.loc.k == locNone) # not yet assigned
# this need not be fullfilled for inline procs; they are regenerated # this need not be fulfilled for inline procs; they are regenerated
# for each module that uses them! # for each module that uses them!
let decl = localVarDecl(p, s).con(";" & tnl) let decl = localVarDecl(p, s).con(";" & tnl)
line(p, cpsLocals, decl) line(p, cpsLocals, decl)

View file

@ -126,7 +126,7 @@ proc ropeFormatNamedVars(frmt: TFormatStr, varnames: openArray[string],
if not (frmt[i] in {'A'..'Z', '_', 'a'..'z', '\x80'..'\xFF'}): break if not (frmt[i] in {'A'..'Z', '_', 'a'..'z', '\x80'..'\xFF'}): break
var idx = getVarIdx(varnames, id) var idx = getVarIdx(varnames, id)
if idx >= 0: app(result, varvalues[idx]) if idx >= 0: app(result, varvalues[idx])
else: rawMessage(errUnkownSubstitionVar, id) else: rawMessage(errUnknownSubstitionVar, id)
of '{': of '{':
var id = "" var id = ""
inc(i) inc(i)
@ -138,7 +138,7 @@ proc ropeFormatNamedVars(frmt: TFormatStr, varnames: openArray[string],
# search for the variable: # search for the variable:
var idx = getVarIdx(varnames, id) var idx = getVarIdx(varnames, id)
if idx >= 0: app(result, varvalues[idx]) if idx >= 0: app(result, varvalues[idx])
else: rawMessage(errUnkownSubstitionVar, id) else: rawMessage(errUnknownSubstitionVar, id)
else: internalError("ropeFormatNamedVars") else: internalError("ropeFormatNamedVars")
var start = i var start = i
while i < L: while i < L:
@ -272,7 +272,7 @@ proc complexName(k: TSymKind, n: PNode, baseName: string): string =
## type)?(,param type)*``. The callable type part will be added only if the ## type)?(,param type)*``. The callable type part will be added only if the
## node is not a proc, as those are the common ones. The suffix will be a dot ## node is not a proc, as those are the common ones. The suffix will be a dot
## and a single letter representing the type of the callable. The parameter ## and a single letter representing the type of the callable. The parameter
## types will be added with a preceeding dash. Return types won't be added. ## types will be added with a preceding dash. Return types won't be added.
## ##
## If you modify the output of this proc, please update the anchor generation ## If you modify the output of this proc, please update the anchor generation
## section of ``doc/docgen.txt``. ## section of ``doc/docgen.txt``.

View file

@ -630,13 +630,13 @@ proc callCCompiler*(projectfile: string) =
res = execWithEcho(cmds[i]) res = execWithEcho(cmds[i])
if res != 0: rawMessage(errExecutionOfProgramFailed, []) if res != 0: rawMessage(errExecutionOfProgramFailed, [])
elif optListCmd in gGlobalOptions or gVerbosity > 1: elif optListCmd in gGlobalOptions or gVerbosity > 1:
res = execProcesses(cmds, {poEchoCmd, poUseShell, poParentStreams}, res = execProcesses(cmds, {poEchoCmd, poUsePath, poParentStreams},
gNumberOfProcessors) gNumberOfProcessors)
elif gVerbosity == 1: elif gVerbosity == 1:
res = execProcesses(cmds, {poUseShell, poParentStreams}, res = execProcesses(cmds, {poUsePath, poParentStreams},
gNumberOfProcessors, prettyCb) gNumberOfProcessors, prettyCb)
else: else:
res = execProcesses(cmds, {poUseShell, poParentStreams}, res = execProcesses(cmds, {poUsePath, poParentStreams},
gNumberOfProcessors) gNumberOfProcessors)
if res != 0: if res != 0:
if gNumberOfProcessors <= 1: if gNumberOfProcessors <= 1:

View file

@ -148,7 +148,7 @@ proc mapType(typ: PType): TJSTypeKind =
tyVarargs: tyVarargs:
result = etyObject result = etyObject
of tyNil: result = etyNull of tyNil: result = etyNull
of tyGenericInst, tyGenericParam, tyGenericBody, tyGenericInvokation, of tyGenericInst, tyGenericParam, tyGenericBody, tyGenericInvocation,
tyNone, tyFromExpr, tyForward, tyEmpty, tyFieldAccessor, tyNone, tyFromExpr, tyForward, tyEmpty, tyFieldAccessor,
tyExpr, tyStmt, tyStatic, tyTypeDesc, tyTypeClasses: tyExpr, tyStmt, tyStatic, tyTypeDesc, tyTypeClasses:
result = etyNone result = etyNone

View file

@ -15,7 +15,7 @@ import
discard """ discard """
The basic approach is that captured vars need to be put on the heap and The basic approach is that captured vars need to be put on the heap and
that the calling chain needs to be explicitely modelled. Things to consider: that the calling chain needs to be explicitly modelled. Things to consider:
proc a = proc a =
var v = 0 var v = 0
@ -583,7 +583,7 @@ proc searchForInnerProcs(o: POuterContext, n: PNode, env: PEnv) =
elif it.kind == nkIdentDefs: elif it.kind == nkIdentDefs:
var L = sonsLen(it) var L = sonsLen(it)
if it.sons[0].kind == nkSym: if it.sons[0].kind == nkSym:
# this can be false for recursive invokations that already # this can be false for recursive invocations that already
# transformed it into 'env.varName': # transformed it into 'env.varName':
env.vars.incl(it.sons[0].sym.id) env.vars.incl(it.sons[0].sym.id)
searchForInnerProcs(o, it.sons[L-1], env) searchForInnerProcs(o, it.sons[L-1], env)
@ -999,7 +999,7 @@ proc liftForLoop*(body: PNode): PNode =
# proc invoke(iter: iterator(): int) = # proc invoke(iter: iterator(): int) =
# for x in iter(): echo x # for x in iter(): echo x
# #
# --> When to create the closure? --> for the (count) occurence! # --> When to create the closure? --> for the (count) occurrence!
discard """ discard """
for i in foo(): ... for i in foo(): ...

View file

@ -107,7 +107,7 @@ type
TToken* = object # a Nim token TToken* = object # a Nim token
tokType*: TTokType # the type of the token tokType*: TTokType # the type of the token
indent*: int # the indentation; != -1 if the token has been indent*: int # the indentation; != -1 if the token has been
# preceeded with indentation # preceded with indentation
ident*: PIdent # the parsed identifier ident*: PIdent # the parsed identifier
iNumber*: BiggestInt # the parsed integer literal iNumber*: BiggestInt # the parsed integer literal
fNumber*: BiggestFloat # the parsed floating point literal fNumber*: BiggestFloat # the parsed floating point literal
@ -679,7 +679,7 @@ proc getOperator(L: var TLexer, tok: var TToken) =
inc(pos) inc(pos)
endOperator(L, tok, pos, h) endOperator(L, tok, pos, h)
# advance pos but don't store it in L.bufpos so the next token (which might # advance pos but don't store it in L.bufpos so the next token (which might
# be an operator too) gets the preceeding spaces: # be an operator too) gets the preceding spaces:
tok.strongSpaceB = 0 tok.strongSpaceB = 0
while buf[pos] == ' ': while buf[pos] == ' ':
inc pos inc pos

View file

@ -69,7 +69,7 @@ type
errInvalidOrderInArrayConstructor, errInvalidOrderInArrayConstructor,
errInvalidOrderInEnumX, errEnumXHasHoles, errExceptExpected, errInvalidTry, errInvalidOrderInEnumX, errEnumXHasHoles, errExceptExpected, errInvalidTry,
errOptionExpected, errXisNoLabel, errNotAllCasesCovered, errOptionExpected, errXisNoLabel, errNotAllCasesCovered,
errUnkownSubstitionVar, errComplexStmtRequiresInd, errXisNotCallable, errUnknownSubstitionVar, errComplexStmtRequiresInd, errXisNotCallable,
errNoPragmasAllowedForX, errNoGenericParamsAllowedForX, errNoPragmasAllowedForX, errNoGenericParamsAllowedForX,
errInvalidParamKindX, errDefaultArgumentInvalid, errNamedParamHasToBeIdent, errInvalidParamKindX, errDefaultArgumentInvalid, errNamedParamHasToBeIdent,
errNoReturnTypeForX, errConvNeedsOneArg, errInvalidPragmaX, errNoReturnTypeForX, errConvNeedsOneArg, errInvalidPragmaX,
@ -89,7 +89,7 @@ type
errTIsNotAConcreteType, errTIsNotAConcreteType,
errInvalidSectionStart, errGridTableNotImplemented, errGeneralParseError, errInvalidSectionStart, errGridTableNotImplemented, errGeneralParseError,
errNewSectionExpected, errWhitespaceExpected, errXisNoValidIndexFile, errNewSectionExpected, errWhitespaceExpected, errXisNoValidIndexFile,
errCannotRenderX, errVarVarTypeNotAllowed, errInstantiateXExplicitely, errCannotRenderX, errVarVarTypeNotAllowed, errInstantiateXExplicitly,
errOnlyACallOpCanBeDelegator, errUsingNoSymbol, errOnlyACallOpCanBeDelegator, errUsingNoSymbol,
errMacroBodyDependsOnGenericTypes, errMacroBodyDependsOnGenericTypes,
errDestructorNotGenericEnough, errDestructorNotGenericEnough,
@ -279,7 +279,7 @@ const
errOptionExpected: "option expected, but found \'$1\'", errOptionExpected: "option expected, but found \'$1\'",
errXisNoLabel: "\'$1\' is not a label", errXisNoLabel: "\'$1\' is not a label",
errNotAllCasesCovered: "not all cases are covered", errNotAllCasesCovered: "not all cases are covered",
errUnkownSubstitionVar: "unknown substitution variable: \'$1\'", errUnknownSubstitionVar: "unknown substitution variable: \'$1\'",
errComplexStmtRequiresInd: "complex statement requires indentation", errComplexStmtRequiresInd: "complex statement requires indentation",
errXisNotCallable: "\'$1\' is not callable", errXisNotCallable: "\'$1\' is not callable",
errNoPragmasAllowedForX: "no pragmas allowed for $1", errNoPragmasAllowedForX: "no pragmas allowed for $1",
@ -325,7 +325,7 @@ const
errXisNoValidIndexFile: "\'$1\' is no valid index file", errXisNoValidIndexFile: "\'$1\' is no valid index file",
errCannotRenderX: "cannot render reStructuredText element \'$1\'", errCannotRenderX: "cannot render reStructuredText element \'$1\'",
errVarVarTypeNotAllowed: "type \'var var\' is not allowed", errVarVarTypeNotAllowed: "type \'var var\' is not allowed",
errInstantiateXExplicitely: "instantiate '$1' explicitely", errInstantiateXExplicitly: "instantiate '$1' explicitly",
errOnlyACallOpCanBeDelegator: "only a call operator can be a delegator", errOnlyACallOpCanBeDelegator: "only a call operator can be a delegator",
errUsingNoSymbol: "'$1' is not a variable, constant or a proc name", errUsingNoSymbol: "'$1' is not a variable, constant or a proc name",
errMacroBodyDependsOnGenericTypes: "the macro body cannot be compiled, " & errMacroBodyDependsOnGenericTypes: "the macro body cannot be compiled, " &
@ -359,7 +359,7 @@ const
errCannotInferReturnType: "cannot infer the return type of the proc", errCannotInferReturnType: "cannot infer the return type of the proc",
errGenericLambdaNotAllowed: "A nested proc can have generic parameters only when " & errGenericLambdaNotAllowed: "A nested proc can have generic parameters only when " &
"it is used as an operand to another routine and the types " & "it is used as an operand to another routine and the types " &
"of the generic paramers can be infered from the expected signature.", "of the generic paramers can be inferred from the expected signature.",
errCompilerDoesntSupportTarget: "The current compiler \'$1\' doesn't support the requested compilation target", errCompilerDoesntSupportTarget: "The current compiler \'$1\' doesn't support the requested compilation target",
errUser: "$1", errUser: "$1",
warnCannotOpenFile: "cannot open \'$1\' [CannotOpenFile]", warnCannotOpenFile: "cannot open \'$1\' [CannotOpenFile]",
@ -723,7 +723,7 @@ proc handleError(msg: TMsgKind, eh: TErrorHandling, s: string) =
if stackTraceAvailable(): if stackTraceAvailable():
writeStackTrace() writeStackTrace()
else: else:
msgWriteln("No stack traceback available\nTo create a stacktrace, rerun compilation with ./koch temp c <file>") msgWriteln("No stack traceback available\nTo create a stacktrace, rerun compilation with ./koch temp " & options.command & " <file>")
quit 1 quit 1
if msg >= fatalMin and msg <= fatalMax: if msg >= fatalMin and msg <= fatalMax:

View file

@ -33,7 +33,7 @@ proc `<.`(a, b: string): bool =
while true: while true:
let ii = parseInt(a, verA, i) let ii = parseInt(a, verA, i)
let jj = parseInt(b, verB, j) let jj = parseInt(b, verB, j)
# if A has no number left, but B has, B is prefered: 0.8 vs 0.8.3 # if A has no number left, but B has, B is preferred: 0.8 vs 0.8.3
if ii <= 0 or jj <= 0: return jj > 0 if ii <= 0 or jj <= 0: return jj > 0
if verA < verB: return true if verA < verB: return true
elif verA > verB: return false elif verA > verB: return false

View file

@ -275,7 +275,7 @@ proc applyRule*(c: PContext, s: PSym, n: PNode): PNode =
if arg != rs and aliases.isPartOf(rs, arg) == arYes: if arg != rs and aliases.isPartOf(rs, arg) == arYes:
ok = true ok = true
break break
# constraint not fullfilled: # constraint not fulfilled:
if not ok: return nil if not ok: return nil
of aqNoAlias: of aqNoAlias:
# it MUST not alias with any other param: # it MUST not alias with any other param:
@ -284,7 +284,7 @@ proc applyRule*(c: PContext, s: PSym, n: PNode): PNode =
if arg != rs and aliases.isPartOf(rs, arg) != arNo: if arg != rs and aliases.isPartOf(rs, arg) != arNo:
ok = false ok = false
break break
# constraint not fullfilled: # constraint not fulfilled:
if not ok: return nil if not ok: return nil
markUsed(n.info, s) markUsed(n.info, s)

View file

@ -666,7 +666,7 @@ proc newRodReader(modfilename: string, crc: TCrc32,
r.readerIndex = readerIndex r.readerIndex = readerIndex
r.filename = modfilename r.filename = modfilename
initIdTable(r.syms) initIdTable(r.syms)
# we terminate the file explicitely with ``\0``, so the cast to `cstring` # we terminate the file explicitly with ``\0``, so the cast to `cstring`
# is safe: # is safe:
r.s = cast[cstring](r.memfile.mem) r.s = cast[cstring](r.memfile.mem)
if startsWith(r.s, "NIM:"): if startsWith(r.s, "NIM:"):

View file

@ -200,7 +200,7 @@ proc encodeType(w: PRodWriter, t: PType, result: var string) =
return return
# we need no surrounding [] here because the type is in a line of its own # we need no surrounding [] here because the type is in a line of its own
if t.kind == tyForward: internalError("encodeType: tyForward") if t.kind == tyForward: internalError("encodeType: tyForward")
# for the new rodfile viewer we use a preceeding [ so that the data section # for the new rodfile viewer we use a preceding [ so that the data section
# can easily be disambiguated: # can easily be disambiguated:
add(result, '[') add(result, '[')
encodeVInt(ord(t.kind), result) encodeVInt(ord(t.kind), result)

View file

@ -52,7 +52,7 @@
# Note that the left and right pointers are not needed for leaves. # Note that the left and right pointers are not needed for leaves.
# Leaves have relatively high memory overhead (~30 bytes on a 32 # Leaves have relatively high memory overhead (~30 bytes on a 32
# bit machines) and we produce many of them. This is why we cache and # bit machines) and we produce many of them. This is why we cache and
# share leaves accross different rope trees. # share leaves across different rope trees.
# To cache them they are inserted in a `cache` array. # To cache them they are inserted in a `cache` array.
import import

View file

@ -184,7 +184,7 @@ proc liftBodyAux(c: TLiftCtx; t: PType; x, y: PNode) =
of tyFromExpr, tyIter, tyProxy, tyBuiltInTypeClass, tyUserTypeClass, of tyFromExpr, tyIter, tyProxy, tyBuiltInTypeClass, tyUserTypeClass,
tyUserTypeClassInst, tyCompositeTypeClass, tyAnd, tyOr, tyNot, tyAnything, tyUserTypeClassInst, tyCompositeTypeClass, tyAnd, tyOr, tyNot, tyAnything,
tyMutable, tyGenericParam, tyGenericBody, tyNil, tyExpr, tyStmt, tyMutable, tyGenericParam, tyGenericBody, tyNil, tyExpr, tyStmt,
tyTypeDesc, tyGenericInvokation, tyBigNum, tyConst, tyForward: tyTypeDesc, tyGenericInvocation, tyBigNum, tyConst, tyForward:
internalError(c.info, "assignment requested for type: " & typeToString(t)) internalError(c.info, "assignment requested for type: " & typeToString(t))
of tyDistinct, tyOrdinal, tyRange, of tyDistinct, tyOrdinal, tyRange,
tyGenericInst, tyFieldAccessor, tyStatic, tyVar: tyGenericInst, tyFieldAccessor, tyStatic, tyVar:

View file

@ -264,7 +264,7 @@ proc inferWithMetatype(c: PContext, formal: PType,
instGenericConvertersArg(c, result, m) instGenericConvertersArg(c, result, m)
if result != nil: if result != nil:
# This almost exactly replicates the steps taken by the compiler during # This almost exactly replicates the steps taken by the compiler during
# param matching. It performs an embarassing ammount of back-and-forth # param matching. It performs an embarrassing amount of back-and-forth
# type jugling, but it's the price to pay for consistency and correctness # type jugling, but it's the price to pay for consistency and correctness
result.typ = generateTypeInstance(c, m.bindings, arg.info, result.typ = generateTypeInstance(c, m.bindings, arg.info,
formal.skipTypes({tyCompositeTypeClass})) formal.skipTypes({tyCompositeTypeClass}))

View file

@ -30,7 +30,7 @@ proc instantiateDestructor(c: PContext, typ: PType): PType
proc doDestructorStuff(c: PContext, s: PSym, n: PNode) = proc doDestructorStuff(c: PContext, s: PSym, n: PNode) =
var t = s.typ.sons[1].skipTypes({tyVar}) var t = s.typ.sons[1].skipTypes({tyVar})
if t.kind == tyGenericInvokation: if t.kind == tyGenericInvocation:
for i in 1 .. <t.sonsLen: for i in 1 .. <t.sonsLen:
if t.sons[i].kind != tyGenericParam: if t.sons[i].kind != tyGenericParam:
localError(n.info, errDestructorNotGenericEnough) localError(n.info, errDestructorNotGenericEnough)

View file

@ -1637,7 +1637,7 @@ proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode =
result = semDirectOp(c, n, flags) result = semDirectOp(c, n, flags)
proc createFlowVar(c: PContext; t: PType; info: TLineInfo): PType = proc createFlowVar(c: PContext; t: PType; info: TLineInfo): PType =
result = newType(tyGenericInvokation, c.module) result = newType(tyGenericInvocation, c.module)
addSonSkipIntLit(result, magicsys.getCompilerProc("FlowVar").typ) addSonSkipIntLit(result, magicsys.getCompilerProc("FlowVar").typ)
addSonSkipIntLit(result, t) addSonSkipIntLit(result, t)
result = instGenericContainer(c, info, result, allowMetaTypes = false) result = instGenericContainer(c, info, result, allowMetaTypes = false)
@ -1917,7 +1917,7 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
it.sons[0] = newSymNode(f) it.sons[0] = newSymNode(f)
e = fitNode(c, f.typ, e) e = fitNode(c, f.typ, e)
# small hack here in a nkObjConstr the ``nkExprColonExpr`` node can have # small hack here in a nkObjConstr the ``nkExprColonExpr`` node can have
# 3 childen the last being the field check # 3 children the last being the field check
if check != nil: if check != nil:
check.sons[0] = it.sons[0] check.sons[0] = it.sons[0]
it.add(check) it.add(check)
@ -2001,7 +2001,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
if result.kind == nkSym: if result.kind == nkSym:
markIndirect(c, result.sym) markIndirect(c, result.sym)
# if isGenericRoutine(result.sym): # if isGenericRoutine(result.sym):
# localError(n.info, errInstantiateXExplicitely, s.name.s) # localError(n.info, errInstantiateXExplicitly, s.name.s)
of nkSym: of nkSym:
# because of the changed symbol binding, this does not mean that we # because of the changed symbol binding, this does not mean that we
# don't have to check the symbol for semantics here again! # don't have to check the symbol for semantics here again!

View file

@ -243,7 +243,7 @@ proc semGenericStmt(c: PContext, n: PNode,
elif fn.kind == nkDotExpr: elif fn.kind == nkDotExpr:
result.sons[0] = fuzzyLookup(c, fn, flags, ctx, mixinContext) result.sons[0] = fuzzyLookup(c, fn, flags, ctx, mixinContext)
first = 1 first = 1
# Consider 'when defined(globalsSlot): ThreadVarSetValue(globalsSlot, ...)' # Consider 'when declared(globalsSlot): ThreadVarSetValue(globalsSlot, ...)'
# in threads.nim: the subtle preprocessing here binds 'globalsSlot' which # in threads.nim: the subtle preprocessing here binds 'globalsSlot' which
# is not exported and yet the generic 'threadProcWrapper' works correctly. # is not exported and yet the generic 'threadProcWrapper' works correctly.
let flags = if mixinContext: flags+{withinMixin} else: flags let flags = if mixinContext: flags+{withinMixin} else: flags

View file

@ -36,7 +36,7 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
elif t.kind == tyGenericParam: elif t.kind == tyGenericParam:
localError(a.info, errCannotInstantiateX, q.name.s) localError(a.info, errCannotInstantiateX, q.name.s)
t = errorType(c) t = errorType(c)
elif t.kind == tyGenericInvokation: elif t.kind == tyGenericInvocation:
#t = instGenericContainer(c, a, t) #t = instGenericContainer(c, a, t)
t = generateTypeInstance(c, pt, a, t) t = generateTypeInstance(c, pt, a, t)
#t = ReplaceTypeVarsT(cl, t) #t = ReplaceTypeVarsT(cl, t)
@ -174,17 +174,27 @@ proc instantiateProcType(c: PContext, pt: TIdTable,
result.n = originalParams.shallowCopy result.n = originalParams.shallowCopy
for i in 1 .. <result.len: for i in 1 .. <result.len:
# twrong_field_caching requires these 'resetIdTable' calls:
if i > 1: resetIdTable(cl.symMap)
result.sons[i] = replaceTypeVarsT(cl, result.sons[i]) result.sons[i] = replaceTypeVarsT(cl, result.sons[i])
propagateToOwner(result, result.sons[i]) propagateToOwner(result, result.sons[i])
let param = replaceTypeVarsN(cl, originalParams[i]) internalAssert originalParams[i].kind == nkSym
result.n.sons[i] = param when true:
if param.kind == nkSym: let oldParam = originalParams[i].sym
# XXX: this won't be true for void params let param = copySym(oldParam)
# implement pass-through of void params and param.owner = prc
# the "sort by distance to point" container param.typ = result.sons[i]
param.ast = oldParam.ast.copyTree
# don't be lazy here and call replaceTypeVarsN(cl, originalParams[i])!
result.n.sons[i] = newSymNode(param)
addDecl(c, param)
else:
let param = replaceTypeVarsN(cl, originalParams[i])
result.n.sons[i] = param
param.sym.owner = prc param.sym.owner = prc
addDecl(c, param.sym) addDecl(c, result.n.sons[i].sym)
resetIdTable(cl.symMap)
result.sons[0] = replaceTypeVarsT(cl, result.sons[0]) result.sons[0] = replaceTypeVarsT(cl, result.sons[0])
result.n.sons[0] = originalParams[0].copyTree result.n.sons[0] = originalParams[0].copyTree

View file

@ -23,7 +23,7 @@ import
# Predefined effects: # Predefined effects:
# io, time (time dependent), gc (performs GC'ed allocation), exceptions, # io, time (time dependent), gc (performs GC'ed allocation), exceptions,
# side effect (accesses global), store (stores into *type*), # side effect (accesses global), store (stores into *type*),
# store_unkown (performs some store) --> store(any)|store(x) # store_unknown (performs some store) --> store(any)|store(x)
# load (loads from *type*), recursive (recursive call), unsafe, # load (loads from *type*), recursive (recursive call), unsafe,
# endless (has endless loops), --> user effects are defined over *patterns* # endless (has endless loops), --> user effects are defined over *patterns*
# --> a TR macro can annotate the proc with user defined annotations # --> a TR macro can annotate the proc with user defined annotations

View file

@ -369,7 +369,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
typ = def.typ typ = def.typ
else: else:
# BUGFIX: ``fitNode`` is needed here! # BUGFIX: ``fitNode`` is needed here!
# check type compability between def.typ and typ # check type compatibility between def.typ and typ
def = fitNode(c, typ, def) def = fitNode(c, typ, def)
#changeType(def.skipConv, typ, check=true) #changeType(def.skipConv, typ, check=true)
else: else:
@ -667,8 +667,8 @@ proc checkForMetaFields(n: PNode) =
let t = n.sym.typ let t = n.sym.typ
case t.kind case t.kind
of tySequence, tySet, tyArray, tyOpenArray, tyVar, tyPtr, tyRef, of tySequence, tySet, tyArray, tyOpenArray, tyVar, tyPtr, tyRef,
tyProc, tyGenericInvokation, tyGenericInst: tyProc, tyGenericInvocation, tyGenericInst:
let start = ord(t.kind in {tyGenericInvokation, tyGenericInst}) let start = ord(t.kind in {tyGenericInvocation, tyGenericInst})
for i in start .. <t.sons.len: for i in start .. <t.sons.len:
checkMeta(t.sons[i]) checkMeta(t.sons[i])
else: else:
@ -912,7 +912,7 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
var t = s.typ.sons[1].skipTypes(abstractInst).lastSon.skipTypes(abstractInst) var t = s.typ.sons[1].skipTypes(abstractInst).lastSon.skipTypes(abstractInst)
while true: while true:
if t.kind == tyGenericBody: t = t.lastSon if t.kind == tyGenericBody: t = t.lastSon
elif t.kind == tyGenericInvokation: t = t.sons[0] elif t.kind == tyGenericInvocation: t = t.sons[0]
else: break else: break
if t.kind in {tyObject, tyDistinct, tyEnum}: if t.kind in {tyObject, tyDistinct, tyEnum}:
if t.deepCopy.isNil: t.deepCopy = s if t.deepCopy.isNil: t.deepCopy = s

View file

@ -436,7 +436,7 @@ proc semTemplBodyDirty(c: var TemplCtx, n: PNode): PNode =
of nkEmpty, nkSym..nkNilLit: of nkEmpty, nkSym..nkNilLit:
discard discard
else: else:
# dotExpr is ambiguous: note that we explicitely allow 'x.TemplateParam', # dotExpr is ambiguous: note that we explicitly allow 'x.TemplateParam',
# so we use the generic code for nkDotExpr too # so we use the generic code for nkDotExpr too
if n.kind == nkDotExpr or n.kind == nkAccQuoted: if n.kind == nkDotExpr or n.kind == nkAccQuoted:
let s = qualifiedLookUp(c.c, n, {}) let s = qualifiedLookUp(c.c, n, {})
@ -494,7 +494,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
semParamList(c, n.sons[paramsPos], gp, s) semParamList(c, n.sons[paramsPos], gp, s)
# a template's parameters are not gensym'ed even if that was originally the # a template's parameters are not gensym'ed even if that was originally the
# case as we determine whether it's a template parameter in the template # case as we determine whether it's a template parameter in the template
# body by the absense of the skGenSym flag: # body by the absence of the skGenSym flag:
for i in 1 .. s.typ.n.len-1: for i in 1 .. s.typ.n.len-1:
s.typ.n.sons[i].sym.flags.excl sfGenSym s.typ.n.sons[i].sym.flags.excl sfGenSym
if sonsLen(gp) > 0: if sonsLen(gp) > 0:
@ -640,7 +640,7 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
result.sons[i] = semPatternBody(c, n.sons[i]) result.sons[i] = semPatternBody(c, n.sons[i])
else: else:
# dotExpr is ambiguous: note that we explicitely allow 'x.TemplateParam', # dotExpr is ambiguous: note that we explicitly allow 'x.TemplateParam',
# so we use the generic code for nkDotExpr too # so we use the generic code for nkDotExpr too
case n.kind case n.kind
of nkDotExpr, nkAccQuoted: of nkDotExpr, nkAccQuoted:

View file

@ -609,9 +609,9 @@ proc addInheritedFieldsAux(c: PContext, check: var IntSet, pos: var int,
inc(pos) inc(pos)
else: internalError(n.info, "addInheritedFieldsAux()") else: internalError(n.info, "addInheritedFieldsAux()")
proc skipGenericInvokation(t: PType): PType {.inline.} = proc skipGenericInvocation(t: PType): PType {.inline.} =
result = t result = t
if result.kind == tyGenericInvokation: if result.kind == tyGenericInvocation:
result = result.sons[0] result = result.sons[0]
if result.kind == tyGenericBody: if result.kind == tyGenericBody:
result = lastSon(result) result = lastSon(result)
@ -620,7 +620,7 @@ proc addInheritedFields(c: PContext, check: var IntSet, pos: var int,
obj: PType) = obj: PType) =
assert obj.kind == tyObject assert obj.kind == tyObject
if (sonsLen(obj) > 0) and (obj.sons[0] != nil): if (sonsLen(obj) > 0) and (obj.sons[0] != nil):
addInheritedFields(c, check, pos, obj.sons[0].skipGenericInvokation) addInheritedFields(c, check, pos, obj.sons[0].skipGenericInvocation)
addInheritedFieldsAux(c, check, pos, obj.n) addInheritedFieldsAux(c, check, pos, obj.n)
proc semObjectNode(c: PContext, n: PNode, prev: PType): PType = proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
@ -632,7 +632,7 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
checkSonsLen(n, 3) checkSonsLen(n, 3)
if n.sons[1].kind != nkEmpty: if n.sons[1].kind != nkEmpty:
base = skipTypes(semTypeNode(c, n.sons[1].sons[0], nil), skipPtrs) base = skipTypes(semTypeNode(c, n.sons[1].sons[0], nil), skipPtrs)
var concreteBase = skipGenericInvokation(base).skipTypes(skipPtrs) var concreteBase = skipGenericInvocation(base).skipTypes(skipPtrs)
if concreteBase.kind == tyObject and tfFinal notin concreteBase.flags: if concreteBase.kind == tyObject and tfFinal notin concreteBase.flags:
addInheritedFields(c, check, pos, concreteBase) addInheritedFields(c, check, pos, concreteBase)
else: else:
@ -777,12 +777,12 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
result = paramType result = paramType
of tyGenericBody: of tyGenericBody:
result = newTypeS(tyGenericInvokation, c) result = newTypeS(tyGenericInvocation, c)
result.rawAddSon(paramType) result.rawAddSon(paramType)
for i in 0 .. paramType.sonsLen - 2: for i in 0 .. paramType.sonsLen - 2:
if paramType.sons[i].kind == tyStatic: if paramType.sons[i].kind == tyStatic:
result.rawAddSon makeTypeFromExpr(c, ast.emptyNode) # aka 'tyUnkown' result.rawAddSon makeTypeFromExpr(c, ast.emptyNode) # aka 'tyUnknown'
else: else:
result.rawAddSon newTypeS(tyAnything, c) result.rawAddSon newTypeS(tyAnything, c)
@ -823,7 +823,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
result = liftBody result = liftBody
result.shouldHaveMeta result.shouldHaveMeta
of tyGenericInvokation: of tyGenericInvocation:
for i in 1 .. <paramType.sonsLen: for i in 1 .. <paramType.sonsLen:
let lifted = liftingWalk(paramType.sons[i]) let lifted = liftingWalk(paramType.sons[i])
if lifted != nil: paramType.sons[i] = lifted if lifted != nil: paramType.sons[i] = lifted
@ -900,7 +900,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
if hasDefault: if hasDefault:
def = semExprWithType(c, a.sons[length-1]) def = semExprWithType(c, a.sons[length-1])
# check type compability between def.typ and typ: # check type compatibility between def.typ and typ:
if typ == nil: if typ == nil:
typ = def.typ typ = def.typ
elif def != nil: elif def != nil:
@ -991,7 +991,7 @@ proc semBlockType(c: PContext, n: PNode, prev: PType): PType =
closeScope(c) closeScope(c)
dec(c.p.nestedBlockCounter) dec(c.p.nestedBlockCounter)
proc semGenericParamInInvokation(c: PContext, n: PNode): PType = proc semGenericParamInInvocation(c: PContext, n: PNode): PType =
result = semTypeNode(c, n, nil) result = semTypeNode(c, n, nil)
proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType = proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
@ -1004,7 +1004,7 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
if t.kind == tyCompositeTypeClass and t.base.kind == tyGenericBody: if t.kind == tyCompositeTypeClass and t.base.kind == tyGenericBody:
t = t.base t = t.base
result = newOrPrevType(tyGenericInvokation, prev, c) result = newOrPrevType(tyGenericInvocation, prev, c)
addSonSkipIntLit(result, t) addSonSkipIntLit(result, t)
template addToResult(typ) = template addToResult(typ) =
@ -1015,7 +1015,7 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
if t.kind == tyForward: if t.kind == tyForward:
for i in countup(1, sonsLen(n)-1): for i in countup(1, sonsLen(n)-1):
var elem = semGenericParamInInvokation(c, n.sons[i]) var elem = semGenericParamInInvocation(c, n.sons[i])
addToResult(elem) addToResult(elem)
return return
elif t.kind != tyGenericBody: elif t.kind != tyGenericBody:

View file

@ -61,7 +61,7 @@ proc searchInstTypes*(key: PType): PType =
if inst.sons.len < key.sons.len: if inst.sons.len < key.sons.len:
# XXX: This happens for prematurely cached # XXX: This happens for prematurely cached
# types such as TChannel[empty]. Why? # types such as TChannel[empty]. Why?
# See the notes for PActor in handleGenericInvokation # See the notes for PActor in handleGenericInvocation
return return
block matchType: block matchType:
for j in 1 .. high(key.sons): for j in 1 .. high(key.sons):
@ -223,7 +223,7 @@ proc lookupTypeVar(cl: var TReplTypeVars, t: PType): PType =
result = errorType(cl.c) result = errorType(cl.c)
# In order to prevent endless recursions, we must remember # In order to prevent endless recursions, we must remember
# this bad lookup and replace it with errorType everywhere. # this bad lookup and replace it with errorType everywhere.
# These code paths are only active in nimrod check # These code paths are only active in "nim check"
idTablePut(cl.typeMap, t, result) idTablePut(cl.typeMap, t, result)
elif result.kind == tyGenericParam and not cl.allowMetaTypes: elif result.kind == tyGenericParam and not cl.allowMetaTypes:
internalError(cl.info, "substitution with generic parameter") internalError(cl.info, "substitution with generic parameter")
@ -234,8 +234,8 @@ proc instCopyType*(cl: var TReplTypeVars, t: PType): PType =
result.flags.incl tfFromGeneric result.flags.incl tfFromGeneric
result.flags.excl tfInstClearedFlags result.flags.excl tfInstClearedFlags
proc handleGenericInvokation(cl: var TReplTypeVars, t: PType): PType = proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
# tyGenericInvokation[A, tyGenericInvokation[A, B]] # tyGenericInvocation[A, tyGenericInvocation[A, B]]
# is difficult to handle: # is difficult to handle:
var body = t.sons[0] var body = t.sons[0]
if body.kind != tyGenericBody: internalError(cl.info, "no generic body") if body.kind != tyGenericBody: internalError(cl.info, "no generic body")
@ -278,7 +278,7 @@ proc handleGenericInvokation(cl: var TReplTypeVars, t: PType): PType =
for i in countup(1, sonsLen(t) - 1): for i in countup(1, sonsLen(t) - 1):
var x = replaceTypeVarsT(cl, t.sons[i]) var x = replaceTypeVarsT(cl, t.sons[i])
assert x.kind != tyGenericInvokation assert x.kind != tyGenericInvocation
header.sons[i] = x header.sons[i] = x
propagateToOwner(header, x) propagateToOwner(header, x)
idTablePut(cl.typeMap, body.sons[i-1], x) idTablePut(cl.typeMap, body.sons[i-1], x)
@ -295,7 +295,7 @@ proc handleGenericInvokation(cl: var TReplTypeVars, t: PType): PType =
#newbody.callConv = body.callConv #newbody.callConv = body.callConv
# This type may be a generic alias and we want to resolve it here. # This type may be a generic alias and we want to resolve it here.
# One step is enough, because the recursive nature of # One step is enough, because the recursive nature of
# handleGenericInvokation will handle the alias-to-alias-to-alias case # handleGenericInvocation will handle the alias-to-alias-to-alias case
if newbody.isGenericAlias: newbody = newbody.skipGenericAlias if newbody.isGenericAlias: newbody = newbody.skipGenericAlias
rawAddSon(result, newbody) rawAddSon(result, newbody)
checkPartialConstructedType(cl.info, newbody) checkPartialConstructedType(cl.info, newbody)
@ -359,8 +359,8 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
if lookup != nil: return lookup if lookup != nil: return lookup
case t.kind case t.kind
of tyGenericInvokation: of tyGenericInvocation:
result = handleGenericInvokation(cl, t) result = handleGenericInvocation(cl, t)
of tyGenericBody: of tyGenericBody:
localError(cl.info, errCannotInstantiateX, typeToString(t)) localError(cl.info, errCannotInstantiateX, typeToString(t))

View file

@ -153,8 +153,8 @@ proc sumGeneric(t: PType): int =
of tyVar: of tyVar:
# but do not make 'var T' more specific than 'T'! # but do not make 'var T' more specific than 'T'!
t = t.sons[0] t = t.sons[0]
of tyGenericInvokation, tyTuple: of tyGenericInvocation, tyTuple:
result = ord(t.kind == tyGenericInvokation) result = ord(t.kind == tyGenericInvocation)
for i in 0 .. <t.len: result += t.sons[i].sumGeneric for i in 0 .. <t.len: result += t.sons[i].sumGeneric
break break
of tyProc: of tyProc:
@ -262,7 +262,7 @@ proc concreteType(c: TCandidate, t: PType): PType =
# example code that triggers it: # example code that triggers it:
# proc sort[T](cmp: proc(a, b: T): int = cmp) # proc sort[T](cmp: proc(a, b: T): int = cmp)
if result.kind != tyGenericParam: break if result.kind != tyGenericParam: break
of tyGenericInvokation: of tyGenericInvocation:
internalError("cannot resolve type: " & typeToString(t)) internalError("cannot resolve type: " & typeToString(t))
result = t result = t
else: else:
@ -462,7 +462,7 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
openScope(c) openScope(c)
inc c.inTypeClass inc c.inTypeClass
finally: defer:
dec c.inTypeClass dec c.inTypeClass
closeScope(c) closeScope(c)
@ -585,7 +585,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
if a.kind == tyGenericInst and if a.kind == tyGenericInst and
skipTypes(f, {tyVar}).kind notin { skipTypes(f, {tyVar}).kind notin {
tyGenericBody, tyGenericInvokation, tyGenericBody, tyGenericInvocation,
tyGenericInst, tyGenericParam} + tyTypeClasses: tyGenericInst, tyGenericParam} + tyTypeClasses:
return typeRel(c, f, lastSon(a)) return typeRel(c, f, lastSon(a))
@ -877,10 +877,10 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
let ff = lastSon(f) let ff = lastSon(f)
if ff != nil: result = typeRel(c, ff, a) if ff != nil: result = typeRel(c, ff, a)
of tyGenericInvokation: of tyGenericInvocation:
var x = a.skipGenericAlias var x = a.skipGenericAlias
if x.kind == tyGenericInvokation or f.sons[0].kind != tyGenericBody: if x.kind == tyGenericInvocation or f.sons[0].kind != tyGenericBody:
#InternalError("typeRel: tyGenericInvokation -> tyGenericInvokation") #InternalError("typeRel: tyGenericInvocation -> tyGenericInvocation")
# simply no match for now: # simply no match for now:
discard discard
elif x.kind == tyGenericInst and elif x.kind == tyGenericInst and
@ -897,7 +897,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
# we steal the generic parameters from the tyGenericBody: # we steal the generic parameters from the tyGenericBody:
for i in countup(1, sonsLen(f) - 1): for i in countup(1, sonsLen(f) - 1):
var x = PType(idTableGet(c.bindings, f.sons[0].sons[i - 1])) var x = PType(idTableGet(c.bindings, f.sons[0].sons[i - 1]))
if x == nil or x.kind in {tyGenericInvokation, tyGenericParam}: if x == nil or x.kind in {tyGenericInvocation, tyGenericParam}:
internalError("wrong instantiated type!") internalError("wrong instantiated type!")
put(c.bindings, f.sons[i], x) put(c.bindings, f.sons[i], x)
@ -1261,12 +1261,20 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
result = implicitConv(nkHiddenStdConv, f, result, m, c) result = implicitConv(nkHiddenStdConv, f, result, m, c)
of isGeneric: of isGeneric:
inc(m.genericMatches) inc(m.genericMatches)
result = copyTree(arg) when false:
result.typ = getInstantiatedType(c, arg, m, f) if skipTypes(arg.typ, abstractVar-{tyTypeDesc}).kind == tyTuple:
# BUG: f may not be the right key! result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
if skipTypes(result.typ, abstractVar-{tyTypeDesc}).kind in {tyTuple}: else:
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c) result = arg.copyTree
# BUGFIX: use ``result.typ`` and not `f` here else:
# XXX Why is this ever necessary? arg's type should not be retrofitted
# to match formal's type in this way!
result = copyTree(arg)
result.typ = getInstantiatedType(c, arg, m, f)
# BUG: f may not be the right key!
if skipTypes(result.typ, abstractVar-{tyTypeDesc}).kind in {tyTuple}:
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
# BUGFIX: use ``result.typ`` and not `f` here
of isFromIntLit: of isFromIntLit:
# too lazy to introduce another ``*matches`` field, so we conflate # too lazy to introduce another ``*matches`` field, so we conflate
# ``isIntConv`` and ``isIntLit`` here: # ``isIntConv`` and ``isIntLit`` here:

View file

@ -250,7 +250,7 @@ proc containsObject(t: PType): bool =
proc isObjectWithTypeFieldPredicate(t: PType): bool = proc isObjectWithTypeFieldPredicate(t: PType): bool =
result = t.kind == tyObject and t.sons[0] == nil and result = t.kind == tyObject and t.sons[0] == nil and
not (t.sym != nil and sfPure in t.sym.flags) and not (t.sym != nil and {sfPure, sfInfixCall} * t.sym.flags != {}) and
tfFinal notin t.flags tfFinal notin t.flags
proc analyseObjectWithTypeFieldAux(t: PType, proc analyseObjectWithTypeFieldAux(t: PType,
@ -396,7 +396,7 @@ proc rangeToStr(n: PNode): string =
const const
typeToStr: array[TTypeKind, string] = ["None", "bool", "Char", "empty", typeToStr: array[TTypeKind, string] = ["None", "bool", "Char", "empty",
"Array Constructor [$1]", "nil", "expr", "stmt", "typeDesc", "Array Constructor [$1]", "nil", "expr", "stmt", "typeDesc",
"GenericInvokation", "GenericBody", "GenericInst", "GenericParam", "GenericInvocation", "GenericBody", "GenericInst", "GenericParam",
"distinct $1", "enum", "ordinal[$1]", "array[$1, $2]", "object", "tuple", "distinct $1", "enum", "ordinal[$1]", "array[$1, $2]", "object", "tuple",
"set[$1]", "range[$1]", "ptr ", "ref ", "var ", "seq[$1]", "proc", "set[$1]", "range[$1]", "ptr ", "ref ", "var ", "seq[$1]", "proc",
"pointer", "OpenArray[$1]", "string", "CString", "Forward", "pointer", "OpenArray[$1]", "string", "CString", "Forward",
@ -432,9 +432,9 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
result = $t.n.intVal result = $t.n.intVal
else: else:
result = "int literal(" & $t.n.intVal & ")" result = "int literal(" & $t.n.intVal & ")"
of tyGenericBody, tyGenericInst, tyGenericInvokation: of tyGenericBody, tyGenericInst, tyGenericInvocation:
result = typeToString(t.sons[0]) & '[' result = typeToString(t.sons[0]) & '['
for i in countup(1, sonsLen(t) -1 -ord(t.kind != tyGenericInvokation)): for i in countup(1, sonsLen(t) -1 -ord(t.kind != tyGenericInvocation)):
if i > 1: add(result, ", ") if i > 1: add(result, ", ")
add(result, typeToString(t.sons[i], preferGenericArg)) add(result, typeToString(t.sons[i], preferGenericArg))
add(result, ']') add(result, ']')
@ -649,7 +649,7 @@ proc lengthOrd(t: PType): BiggestInt =
type type
TDistinctCompare* = enum ## how distinct types are to be compared TDistinctCompare* = enum ## how distinct types are to be compared
dcEq, ## a and b should be the same type dcEq, ## a and b should be the same type
dcEqIgnoreDistinct, ## compare symetrically: (distinct a) == b, a == b dcEqIgnoreDistinct, ## compare symmetrically: (distinct a) == b, a == b
## or a == (distinct b) ## or a == (distinct b)
dcEqOrDistinctOf ## a equals b or a is distinct of b dcEqOrDistinctOf ## a equals b or a is distinct of b
@ -941,7 +941,7 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
result = sameChildrenAux(a, b, c) and sameFlags(a, b) result = sameChildrenAux(a, b, c) and sameFlags(a, b)
if result and ExactGenericParams in c.flags: if result and ExactGenericParams in c.flags:
result = a.sym.position == b.sym.position result = a.sym.position == b.sym.position
of tyGenericInvokation, tyGenericBody, tySequence, of tyGenericInvocation, tyGenericBody, tySequence,
tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyArrayConstr, tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyArrayConstr,
tyArray, tyProc, tyConst, tyMutable, tyVarargs, tyIter, tyArray, tyProc, tyConst, tyMutable, tyVarargs, tyIter,
tyOrdinal, tyTypeClasses, tyFieldAccessor: tyOrdinal, tyTypeClasses, tyFieldAccessor:
@ -1087,7 +1087,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
if taField notin flags: result = t if taField notin flags: result = t
of tyTypeClasses: of tyTypeClasses:
if not (tfGenericTypeParam in t.flags or taField notin flags): result = t if not (tfGenericTypeParam in t.flags or taField notin flags): result = t
of tyGenericBody, tyGenericParam, tyGenericInvokation, of tyGenericBody, tyGenericParam, tyGenericInvocation,
tyNone, tyForward, tyFromExpr, tyFieldAccessor: tyNone, tyForward, tyFromExpr, tyFieldAccessor:
result = t result = t
of tyNil: of tyNil:

View file

@ -19,7 +19,7 @@ proc readOutput(p: Process): string =
discard p.waitForExit discard p.waitForExit
proc opGorge*(cmd, input: string): string = proc opGorge*(cmd, input: string): string =
var p = startCmd(cmd) var p = startProcess(cmd, options={poEvalCommand})
if input.len != 0: if input.len != 0:
p.inputStream.write(input) p.inputStream.write(input)
p.inputStream.close() p.inputStream.close()

View file

@ -1246,7 +1246,7 @@ proc genGlobalInit(c: PCtx; n: PNode; s: PSym) =
c.globals.add(getNullValue(s.typ, n.info)) c.globals.add(getNullValue(s.typ, n.info))
s.position = c.globals.len s.position = c.globals.len
# This is rather hard to support, due to the laziness of the VM code # This is rather hard to support, due to the laziness of the VM code
# generator. See tests/compile/tmacro2 for why this is necesary: # generator. See tests/compile/tmacro2 for why this is necessary:
# var decls{.compileTime.}: seq[PNimrodNode] = @[] # var decls{.compileTime.}: seq[PNimrodNode] = @[]
let dest = c.getTemp(s.typ) let dest = c.getTemp(s.typ)
c.gABx(n, opcLdGlobal, dest, s.position) c.gABx(n, opcLdGlobal, dest, s.position)

View file

@ -105,8 +105,8 @@ path="$lib/pure/unidecode"
@if macosx or freebsd: @if macosx or freebsd:
cc = clang cc = clang
tlsEmulation:on tlsEmulation:on
gcc.options.always = "-w -fasm-blocks" gcc.options.always = "-w"
gcc.cpp.options.always = "-w -fasm-blocks -fpermissive" gcc.cpp.options.always = "-w -fpermissive"
@else: @else:
gcc.options.always = "-w" gcc.options.always = "-w"
gcc.cpp.options.always = "-w -fpermissive" gcc.cpp.options.always = "-w -fpermissive"

View file

@ -24,7 +24,7 @@ doc.section.toc = """
</li> </li>
""" """
# Chunk of HTML emmited for each entry in the HTML table of contents. # Chunk of HTML emitted for each entry in the HTML table of contents.
# Available variables are: # Available variables are:
# * $desc: the actual docstring of the item. # * $desc: the actual docstring of the item.
# * $header: the full version of name, including types, pragmas, tags, etc. # * $header: the full version of name, including types, pragmas, tags, etc.
@ -45,7 +45,7 @@ $seeSrc
</dd> </dd>
""" """
# Chunk of HTML emmited for each entry in the HTML table of contents. # Chunk of HTML emitted for each entry in the HTML table of contents.
# See doc.item for available substitution variables. # See doc.item for available substitution variables.
doc.item.toc = """ doc.item.toc = """
<li><a class="reference" href="#$itemSymOrID" <li><a class="reference" href="#$itemSymOrID"

View file

@ -18,7 +18,7 @@ Advanced commands:
track a file, currently not saved to disk track a file, currently not saved to disk
--suggest suggest all possible symbols at position --suggest suggest all possible symbols at position
--def list all possible definitions at position --def list all possible definitions at position
--context list possible invokation context --context list possible invocation context
--usages list all usages of the symbol at position --usages list all usages of the symbol at position
--eval evaluates an expression --eval evaluates an expression
//serve start the compiler as a service mode (CAAS) //serve start the compiler as a service mode (CAAS)
@ -85,7 +85,7 @@ Advanced options:
that --dynlibOverride:lua matches that --dynlibOverride:lua matches
dynlib: "liblua.so.3" dynlib: "liblua.so.3"
--listCmd list the commands used to execute external programs --listCmd list the commands used to execute external programs
--parallelBuild=0|1|... perform a parallel build --parallelBuild:0|1|... perform a parallel build
value = number of processors (0 for auto-detect) value = number of processors (0 for auto-detect)
--verbosity:0|1|2|3 set Nim's verbosity level (1 is default) --verbosity:0|1|2|3 set Nim's verbosity level (1 is default)
--cs:none|partial set case sensitivity level (default: none); --cs:none|partial set case sensitivity level (default: none);

View file

@ -79,10 +79,3 @@ string str
identifier ident identifier ident
indentation indent indentation indent
------------------- ------------ -------------------------------------- ------------------- ------------ --------------------------------------
Coding Guidelines
=================
For coding guidelines see the `Internals of the Nim Compiler
<intern.html#coding-guidelines>`_ documentation.

View file

@ -225,7 +225,7 @@ The JavaScript target doesn't have any further interfacing considerations
since it also has garbage collection, but the C targets require you to since it also has garbage collection, but the C targets require you to
initialize Nim's internals, which is done calling a ``NimMain`` function. initialize Nim's internals, which is done calling a ``NimMain`` function.
Also, C code requires you to specify a forward declaration for functions or Also, C code requires you to specify a forward declaration for functions or
the compiler will asume certain types for the return value and parameters the compiler will assume certain types for the return value and parameters
which will likely make your program crash at runtime. which will likely make your program crash at runtime.
The Nim compiler can generate a C interface header through the ``--header`` The Nim compiler can generate a C interface header through the ``--header``
@ -427,7 +427,7 @@ Custom data types
----------------- -----------------
Just like strings, custom data types that are to be shared between Nim and Just like strings, custom data types that are to be shared between Nim and
the backend will need careful consideration of who controlls who. If you want the backend will need careful consideration of who controls who. If you want
to hand a Nim reference to C code, you will need to use `GC_ref to hand a Nim reference to C code, you will need to use `GC_ref
<system.html#GC_ref>`_ to mark the reference as used, so it does not get <system.html#GC_ref>`_ to mark the reference as used, so it does not get
freed. And for the C backend you will need to expose the `GC_unref freed. And for the C backend you will need to expose the `GC_unref

View file

@ -27,7 +27,7 @@ integrations <https://github.com/Araq/Nim/wiki/Editor-Support>`_
already available. already available.
Idetools invokation Idetools invocation
=================== ===================
Specifying the location of the query Specifying the location of the query
@ -35,7 +35,7 @@ Specifying the location of the query
All of the available idetools commands require you to specify a All of the available idetools commands require you to specify a
query location through the ``--track`` or ``--trackDirty`` switches. query location through the ``--track`` or ``--trackDirty`` switches.
The general idetools invokations are:: The general idetools invocations are::
nim idetools --track:FILE,LINE,COL <switches> proj.nim nim idetools --track:FILE,LINE,COL <switches> proj.nim
@ -129,7 +129,7 @@ the suggestions sorted first by scope (from innermost to outermost)
and then by item name. and then by item name.
Invokation context Invocation context
------------------ ------------------
The ``--context`` idetools switch is very similar to the suggestions The ``--context`` idetools switch is very similar to the suggestions
@ -163,7 +163,7 @@ running/debugged user project.
Compiler as a service (CAAS) Compiler as a service (CAAS)
============================ ============================
The ocasional use of idetools is acceptable for things like The occasional use of idetools is acceptable for things like
definitions, where the user puts the cursor on a symbol or double definitions, where the user puts the cursor on a symbol or double
clicks it and after a second or two the IDE displays where that clicks it and after a second or two the IDE displays where that
symbol is defined. Such latencies would be terrible for features symbol is defined. Such latencies would be terrible for features
@ -533,10 +533,10 @@ run it manually. First you have to compile the tester::
Running the ``caasdriver`` without parameters will attempt to process Running the ``caasdriver`` without parameters will attempt to process
all the test cases in all three operation modes. If a test succeeds all the test cases in all three operation modes. If a test succeeds
nothing will be printed and the process will exit with zero. If any nothing will be printed and the process will exit with zero. If any
test fails, the specific line of the test preceeding the failure test fails, the specific line of the test preceding the failure
and the failure itself will be dumped to stdout, along with a final and the failure itself will be dumped to stdout, along with a final
indicator of the success state and operation mode. You can pass the indicator of the success state and operation mode. You can pass the
parameter ``verbose`` to force all output even on successfull tests. parameter ``verbose`` to force all output even on successful tests.
The normal operation mode is called ``ProcRun`` and it involves The normal operation mode is called ``ProcRun`` and it involves
starting a process for each command or query, similar to running starting a process for each command or query, similar to running

View file

@ -236,7 +236,7 @@ too. Type converters fall into this category:
If in the above example module ``B`` is re-compiled, but ``A`` is not then If in the above example module ``B`` is re-compiled, but ``A`` is not then
``B`` needs to be aware of ``toBool`` even though ``toBool`` is not referenced ``B`` needs to be aware of ``toBool`` even though ``toBool`` is not referenced
in ``B`` *explicitely*. in ``B`` *explicitly*.
Both the multi method and the type converter problems are solved by storing Both the multi method and the type converter problems are solved by storing
them in special sections in the ROD file that are loaded *unconditionally* them in special sections in the ROD file that are loaded *unconditionally*
@ -370,7 +370,7 @@ needed as the data structures needs to be rebuilt periodically anyway.
Complete traversal is done in this way:: Complete traversal is done in this way::
for each page decriptor d: for each page descriptor d:
for each bit in d: for each bit in d:
if bit == 1: if bit == 1:
traverse the pointer belonging to this bit traverse the pointer belonging to this bit
@ -406,7 +406,7 @@ The generated code looks roughly like this:
setRef(&r->left) setRef(&r->left)
} }
Note that for systems with a continous stack (which most systems have) Note that for systems with a continuous stack (which most systems have)
the check whether the ref is on the stack is very cheap (only two the check whether the ref is on the stack is very cheap (only two
comparisons). comparisons).

View file

@ -370,7 +370,7 @@ Miscellaneous
------------- -------------
* `events <events.html>`_ * `events <events.html>`_
This module implements an event system that is not dependant on external This module implements an event system that is not dependent on external
graphical toolkits. graphical toolkits.
* `oids <oids.html>`_ * `oids <oids.html>`_

View file

@ -25,9 +25,9 @@ with ``'``. An example::
ifStmt = 'if' expr ':' stmts ('elif' expr ':' stmts)* ('else' stmts)? ifStmt = 'if' expr ':' stmts ('elif' expr ':' stmts)* ('else' stmts)?
The binary ``^*`` operator is used as a shorthand for 0 or more occurances The binary ``^*`` operator is used as a shorthand for 0 or more occurrences
separated by its second argument; likewise ``^+`` means 1 or more separated by its second argument; likewise ``^+`` means 1 or more
occurances: ``a ^+ b`` is short for ``a (b a)*`` occurrences: ``a ^+ b`` is short for ``a (b a)*``
and ``a ^* b`` is short for ``(a (b a)*)?``. Example:: and ``a ^* b`` is short for ``(a (b a)*)?``. Example::
arrayConstructor = '[' expr ^* ',' ']' arrayConstructor = '[' expr ^* ',' ']'

View file

@ -59,7 +59,7 @@ Precedence level Operators First charact
Strong spaces Strong spaces
------------- -------------
The number of spaces preceeding a non-keyword operator affects precedence The number of spaces preceding a non-keyword operator affects precedence
if the experimental parser directive ``#!strongSpaces`` is used. Indentation if the experimental parser directive ``#!strongSpaces`` is used. Indentation
is not used to determine the number of spaces. If 2 or more operators have the is not used to determine the number of spaces. If 2 or more operators have the
same number of preceding spaces the precedence table applies, so ``1 + 3 * 4`` same number of preceding spaces the precedence table applies, so ``1 + 3 * 4``

View file

@ -1142,7 +1142,7 @@ modules like `db_sqlite <db_sqlite.html>`_.
Void type Void type
--------- ---------
The ``void`` type denotes the absense of any type. Parameters of The ``void`` type denotes the absence of any type. Parameters of
type ``void`` are treated as non-existent, ``void`` as a return type means that type ``void`` are treated as non-existent, ``void`` as a return type means that
the procedure does not return a value: the procedure does not return a value:

View file

@ -134,7 +134,7 @@ found an ambiguity error is produced.
``nim dump`` shows the contents of the PATH. ``nim dump`` shows the contents of the PATH.
However before the PATH is used the current directory is checked for the However before the PATH is used the current directory is checked for the
file's existance. So if PATH contains ``$lib`` and ``$lib/bar`` and the file's existence. So if PATH contains ``$lib`` and ``$lib/bar`` and the
directory structure looks like this:: directory structure looks like this::
$lib/x.nim $lib/x.nim

View file

@ -25,9 +25,9 @@ Compile nimgrep with the command::
And copy the executable somewhere in your ``$PATH``. And copy the executable somewhere in your ``$PATH``.
Command line switches Command line switches
===================== =====================
Usage: Usage:
nimgrep [options] [pattern] [replacement] (file/directory)* nimgrep [options] [pattern] [replacement] (file/directory)*
Options: Options:
@ -37,7 +37,7 @@ Options:
--re pattern is a regular expression (default); extended --re pattern is a regular expression (default); extended
syntax for the regular expression is always turned on syntax for the regular expression is always turned on
--recursive process directories recursively --recursive process directories recursively
--confirm confirm each occurence/replacement; there is a chance --confirm confirm each occurrence/replacement; there is a chance
to abort any time without touching the file to abort any time without touching the file
--stdin read pattern from stdin (to avoid the shell's confusing --stdin read pattern from stdin (to avoid the shell's confusing
quoting rules) quoting rules)

View file

@ -37,7 +37,7 @@ Object Oriented Programming
While Nim's support for object oriented programming (OOP) is minimalistic, While Nim's support for object oriented programming (OOP) is minimalistic,
powerful OOP techniques can be used. OOP is seen as *one* way to design a powerful OOP techniques can be used. OOP is seen as *one* way to design a
program, not *the only* way. Often a procedural approach leads to simpler program, not *the only* way. Often a procedural approach leads to simpler
and more efficient code. In particular, prefering composition over inheritance and more efficient code. In particular, preferring composition over inheritance
is often the better design. is often the better design.
@ -142,7 +142,7 @@ An example:
.. code-block:: nim .. code-block:: nim
# This is an example how an abstract syntax tree could be modeled in Nim # This is an example how an abstract syntax tree could be modelled in Nim
type type
NodeKind = enum # the different node types NodeKind = enum # the different node types
nkInt, # a leaf with an integer value nkInt, # a leaf with an integer value
@ -335,7 +335,7 @@ As the example demonstrates, invocation of a multi-method cannot be ambiguous:
Collide 2 is preferred over collide 1 because the resolution works from left to Collide 2 is preferred over collide 1 because the resolution works from left to
right. Thus ``Unit, Thing`` is preferred over ``Thing, Unit``. right. Thus ``Unit, Thing`` is preferred over ``Thing, Unit``.
**Perfomance note**: Nim does not produce a virtual method table, but **Performance note**: Nim does not produce a virtual method table, but
generates dispatch trees. This avoids the expensive indirect branch for method generates dispatch trees. This avoids the expensive indirect branch for method
calls and enables inlining. However, other optimizations like compile time calls and enables inlining. However, other optimizations like compile time
evaluation or dead code elimination do not work with methods. evaluation or dead code elimination do not work with methods.

View file

@ -10,7 +10,7 @@ just declared as a native method which will be resolved at runtime. The scripts
nimbuild.sh and jnibuild.sh are in charge of building the Nim code and nimbuild.sh and jnibuild.sh are in charge of building the Nim code and
generating the jni bridge from the java code respectively. Finally, the generating the jni bridge from the java code respectively. Finally, the
ndk-build command from the android ndk tools has to be run to build the binary ndk-build command from the android ndk tools has to be run to build the binary
libary which will be installed along the final apk. library which will be installed along the final apk.
All these steps are wrapped in the ant build script through the customization All these steps are wrapped in the ant build script through the customization
of the -post-compile rule. If you have the android ndk tools installed and you of the -post-compile rule. If you have the android ndk tools installed and you

View file

@ -55,7 +55,7 @@
[self.bText resignFirstResponder]; [self.bText resignFirstResponder];
} }
/** Custom loadView method for backwards compatiblity. /** Custom loadView method for backwards compatibility.
* Unfortunately I've been unable to coerce Xcode 4.4 to generate nib files * Unfortunately I've been unable to coerce Xcode 4.4 to generate nib files
* which are compatible with my trusty iOS 3.0 ipod touch so in order to be * which are compatible with my trusty iOS 3.0 ipod touch so in order to be
* fully compatible for all devices we have to build the interface manually in * fully compatible for all devices we have to build the interface manually in

View file

@ -91,7 +91,7 @@ proc update*(todo: var TTodo; conn: TDbConn): bool =
## ##
## Use this method if you (or another entity) have modified the database and ## Use this method if you (or another entity) have modified the database and
## want to update the object you have with whatever the database has stored. ## want to update the object you have with whatever the database has stored.
## Returns true if the update suceeded, or false if the object was not found ## Returns true if the update succeeded, or false if the object was not found
## in the database any more, in which case you should probably get rid of the ## in the database any more, in which case you should probably get rid of the
## TTodo object. ## TTodo object.
assert(todo.id >= 0, "The identifier of the todo entry can't be negative") assert(todo.id >= 0, "The identifier of the todo entry can't be negative")

View file

@ -14,7 +14,7 @@ template optRe{re(x)}(x: string{lit}): Regex =
g g
template `=~`(s: string, pattern: Regex): bool = template `=~`(s: string, pattern: Regex): bool =
when not definedInScope(matches): when not declaredInScope(matches):
var matches {.inject.}: array[maxSubPatterns, string] var matches {.inject.}: array[maxSubPatterns, string]
match(s, pattern, matches) match(s, pattern, matches)

View file

@ -270,13 +270,13 @@ when defined(withUpdate):
echo("Fetching updates from repo...") echo("Fetching updates from repo...")
var pullout = execCmdEx(git & " pull origin master") var pullout = execCmdEx(git & " pull origin master")
if pullout[1] != 0: if pullout[1] != 0:
quit("An error has occured.") quit("An error has occurred.")
else: else:
if pullout[0].startsWith("Already up-to-date."): if pullout[0].startsWith("Already up-to-date."):
quit("No new changes fetched from the repo. " & quit("No new changes fetched from the repo. " &
"Local branch must be ahead of it. Exiting...") "Local branch must be ahead of it. Exiting...")
else: else:
quit("An error has occured.") quit("An error has occurred.")
else: else:
echo("No repo or executable found!") echo("No repo or executable found!")
@ -360,7 +360,7 @@ of cmdArgument:
of "boot": boot(op.cmdLineRest) of "boot": boot(op.cmdLineRest)
of "clean": clean(op.cmdLineRest) of "clean": clean(op.cmdLineRest)
of "web": web(op.cmdLineRest) of "web": web(op.cmdLineRest)
of "website": website(op.cmdLineRest) of "website": website(op.cmdLineRest & " --googleAnalytics:UA-48159761-1")
of "web0": of "web0":
# undocumented command for Araq-the-merciful: # undocumented command for Araq-the-merciful:
web(op.cmdLineRest & " --googleAnalytics:UA-48159761-1") web(op.cmdLineRest & " --googleAnalytics:UA-48159761-1")

View file

@ -21,7 +21,7 @@ type
## is performed. Deprecated, do not use anymore! ## is performed. Deprecated, do not use anymore!
AquireEffect* {.deprecated.} = object of LockEffect ## \ AquireEffect* {.deprecated.} = object of LockEffect ## \
## effect that denotes that some lock is ## effect that denotes that some lock is
## aquired. Deprecated, do not use anymore! ## acquired. Deprecated, do not use anymore!
ReleaseEffect* {.deprecated.} = object of LockEffect ## \ ReleaseEffect* {.deprecated.} = object of LockEffect ## \
## effect that denotes that some lock is ## effect that denotes that some lock is
## released. Deprecated, do not use anymore! ## released. Deprecated, do not use anymore!

View file

@ -76,7 +76,7 @@ type
TNimrodTypeKind* = enum TNimrodTypeKind* = enum
ntyNone, ntyBool, ntyChar, ntyEmpty, ntyNone, ntyBool, ntyChar, ntyEmpty,
ntyArrayConstr, ntyNil, ntyExpr, ntyStmt, ntyArrayConstr, ntyNil, ntyExpr, ntyStmt,
ntyTypeDesc, ntyGenericInvokation, ntyGenericBody, ntyGenericInst, ntyTypeDesc, ntyGenericInvocation, ntyGenericBody, ntyGenericInst,
ntyGenericParam, ntyDistinct, ntyEnum, ntyOrdinal, ntyGenericParam, ntyDistinct, ntyEnum, ntyOrdinal,
ntyArray, ntyObject, ntyTuple, ntySet, ntyArray, ntyObject, ntyTuple, ntySet,
ntyRange, ntyPtr, ntyRef, ntyVar, ntyRange, ntyPtr, ntyRef, ntyVar,

View file

@ -1145,7 +1145,7 @@ proc formatNamedVars*(frmt: string, varnames: openArray[string],
proc defaultConfig*(): StringTableRef = proc defaultConfig*(): StringTableRef =
## Returns a default configuration for embedded HTML generation. ## Returns a default configuration for embedded HTML generation.
## ##
## The returned ``StringTableRef`` contains the paramters used by the HTML ## The returned ``StringTableRef`` contains the parameters used by the HTML
## engine to build the final output. For information on what these parameters ## engine to build the final output. For information on what these parameters
## are and their purpose, please look up the file ``config/nimdoc.cfg`` ## are and their purpose, please look up the file ``config/nimdoc.cfg``
## bundled with the compiler. ## bundled with the compiler.

View file

@ -1732,12 +1732,10 @@ when hasSpawnH:
when defined(linux): when defined(linux):
# better be safe than sorry; Linux has this flag, macosx doesn't, don't # better be safe than sorry; Linux has this flag, macosx doesn't, don't
# know about the other OSes # know about the other OSes
when defined(tcc):
# TCC doesn't define __USE_GNU, so we can't get the magic number from # Non-GNU systems like TCC and musl-libc don't define __USE_GNU, so we
# spawn.h # can't get the magic number from spawn.h
const POSIX_SPAWN_USEVFORK* = cint(0x40) const POSIX_SPAWN_USEVFORK* = cint(0x40)
else:
var POSIX_SPAWN_USEVFORK* {.importc, header: "<spawn.h>".}: cint
else: else:
# macosx lacks this, so we define the constant to be 0 to not affect # macosx lacks this, so we define the constant to be 0 to not affect
# OR'ing of flags: # OR'ing of flags:

View file

@ -200,7 +200,7 @@ template schedule =
if minIdx >= 0: if minIdx >= 0:
p.actors[minIdx].i.send(t) p.actors[minIdx].i.send(t)
else: else:
raise newException(EDeadThread, "cannot send message; thread died") raise newException(DeadThreadError, "cannot send message; thread died")
proc spawn*[TIn, TOut](p: var TActorPool[TIn, TOut], input: TIn, proc spawn*[TIn, TOut](p: var TActorPool[TIn, TOut], input: TIn,
action: proc (input: TIn): TOut {.thread.} action: proc (input: TIn): TOut {.thread.}

View file

@ -606,7 +606,7 @@ when defined(windows) or defined(nimdoc):
retFuture.fail(newException(OSError, osErrorMsg(err))) retFuture.fail(newException(OSError, osErrorMsg(err)))
elif ret == 0 and bytesReceived == 0 and dataBuf.buf[0] == '\0': elif ret == 0 and bytesReceived == 0 and dataBuf.buf[0] == '\0':
# We have to ensure that the buffer is empty because WSARecv will tell # We have to ensure that the buffer is empty because WSARecv will tell
# us immediatelly when it was disconnected, even when there is still # us immediately when it was disconnected, even when there is still
# data in the buffer. # data in the buffer.
# We want to give the user as much data as we can. So we only return # We want to give the user as much data as we can. So we only return
# the empty string (which signals a disconnection) when there is # the empty string (which signals a disconnection) when there is

View file

@ -35,7 +35,7 @@ type
offset: int64 offset: int64
when defined(windows): when defined(windows):
proc getDesiredAccess(mode: TFileMode): int32 = proc getDesiredAccess(mode: FileMode): int32 =
case mode case mode
of fmRead: of fmRead:
result = GENERIC_READ result = GENERIC_READ
@ -44,7 +44,7 @@ when defined(windows):
of fmReadWrite, fmReadWriteExisting: of fmReadWrite, fmReadWriteExisting:
result = GENERIC_READ or GENERIC_WRITE result = GENERIC_READ or GENERIC_WRITE
proc getCreationDisposition(mode: TFileMode, filename: string): int32 = proc getCreationDisposition(mode: FileMode, filename: string): int32 =
case mode case mode
of fmRead, fmReadWriteExisting: of fmRead, fmReadWriteExisting:
OPEN_EXISTING OPEN_EXISTING
@ -54,7 +54,7 @@ when defined(windows):
else: else:
CREATE_NEW CREATE_NEW
else: else:
proc getPosixFlags(mode: TFileMode): cint = proc getPosixFlags(mode: FileMode): cint =
case mode case mode
of fmRead: of fmRead:
result = O_RDONLY result = O_RDONLY
@ -74,7 +74,7 @@ proc getFileSize(f: AsyncFile): int64 =
var high: DWord var high: DWord
let low = getFileSize(f.fd.THandle, addr high) let low = getFileSize(f.fd.THandle, addr high)
if low == INVALID_FILE_SIZE: if low == INVALID_FILE_SIZE:
raiseOSError() raiseOSError(osLastError())
return (high shl 32) or low return (high shl 32) or low
proc openAsync*(filename: string, mode = fmRead): AsyncFile = proc openAsync*(filename: string, mode = fmRead): AsyncFile =
@ -95,7 +95,7 @@ proc openAsync*(filename: string, mode = fmRead): AsyncFile =
nil, creationDisposition, flags, 0).TAsyncFd nil, creationDisposition, flags, 0).TAsyncFd
if result.fd.THandle == INVALID_HANDLE_VALUE: if result.fd.THandle == INVALID_HANDLE_VALUE:
raiseOSError() raiseOSError(osLastError())
register(result.fd) register(result.fd)
@ -108,7 +108,7 @@ proc openAsync*(filename: string, mode = fmRead): AsyncFile =
let perm = S_IRUSR or S_IWUSR or S_IRGRP or S_IWGRP or S_IROTH let perm = S_IRUSR or S_IWUSR or S_IRGRP or S_IWGRP or S_IROTH
result.fd = open(filename, flags, perm).TAsyncFD result.fd = open(filename, flags, perm).TAsyncFD
if result.fd.cint == -1: if result.fd.cint == -1:
raiseOSError() raiseOSError(osLastError())
register(result.fd) register(result.fd)
@ -185,7 +185,7 @@ proc read*(f: AsyncFile, size: int): Future[string] =
if res < 0: if res < 0:
let lastError = osLastError() let lastError = osLastError()
if lastError.int32 != EAGAIN: if lastError.int32 != EAGAIN:
retFuture.fail(newException(EOS, osErrorMsg(lastError))) retFuture.fail(newException(OSError, osErrorMsg(lastError)))
else: else:
result = false # We still want this callback to be called. result = false # We still want this callback to be called.
elif res == 0: elif res == 0:
@ -227,7 +227,7 @@ proc setFilePos*(f: AsyncFile, pos: int64) =
when not defined(windows): when not defined(windows):
let ret = lseek(f.fd.cint, pos, SEEK_SET) let ret = lseek(f.fd.cint, pos, SEEK_SET)
if ret == -1: if ret == -1:
raiseOSError() raiseOSError(osLastError())
proc readAll*(f: AsyncFile): Future[string] {.async.} = proc readAll*(f: AsyncFile): Future[string] {.async.} =
## Reads all data from the specified file. ## Reads all data from the specified file.
@ -299,7 +299,7 @@ proc write*(f: AsyncFile, data: string): Future[void] =
if res < 0: if res < 0:
let lastError = osLastError() let lastError = osLastError()
if lastError.int32 != EAGAIN: if lastError.int32 != EAGAIN:
retFuture.fail(newException(EOS, osErrorMsg(lastError))) retFuture.fail(newException(OSError, osErrorMsg(lastError)))
else: else:
result = false # We still want this callback to be called. result = false # We still want this callback to be called.
else: else:
@ -318,8 +318,8 @@ proc close*(f: AsyncFile) =
## Closes the file specified. ## Closes the file specified.
when defined(windows): when defined(windows):
if not closeHandle(f.fd.THandle).bool: if not closeHandle(f.fd.THandle).bool:
raiseOSError() raiseOSError(osLastError())
else: else:
if close(f.fd.cint) == -1: if close(f.fd.cint) == -1:
raiseOSError() raiseOSError(osLastError())

View file

@ -149,7 +149,7 @@ proc createDir*(ftp: AsyncFtpClient, dir: string, recursive = false){.async.} =
assertReply reply, "257" assertReply reply, "257"
proc chmod*(ftp: AsyncFtpClient, path: string, proc chmod*(ftp: AsyncFtpClient, path: string,
permissions: set[TFilePermission]) {.async.} = permissions: set[FilePermission]) {.async.} =
## Changes permission of ``path`` to ``permissions``. ## Changes permission of ``path`` to ``permissions``.
var userOctal = 0 var userOctal = 0
var groupOctal = 0 var groupOctal = 0
@ -188,7 +188,7 @@ proc retrText*(ftp: AsyncFtpClient, file: string): Future[string] {.async.} =
result = await ftp.getLines() result = await ftp.getLines()
proc getFile(ftp: AsyncFtpClient, file: TFile, total: BiggestInt, proc getFile(ftp: AsyncFtpClient, file: File, total: BiggestInt,
onProgressChanged: ProgressChangedProc) {.async.} = onProgressChanged: ProgressChangedProc) {.async.} =
assert ftp.dsockConnected assert ftp.dsockConnected
var progress = 0 var progress = 0
@ -240,7 +240,7 @@ proc retrFile*(ftp: AsyncFtpClient, file, dest: string,
await getFile(ftp, destFile, fileSize, onProgressChanged) await getFile(ftp, destFile, fileSize, onProgressChanged)
proc doUpload(ftp: AsyncFtpClient, file: TFile, proc doUpload(ftp: AsyncFtpClient, file: File,
onProgressChanged: ProgressChangedProc) {.async.} = onProgressChanged: ProgressChangedProc) {.async.} =
assert ftp.dsockConnected assert ftp.dsockConnected

View file

@ -675,7 +675,7 @@ when isMainModule:
echo(data) echo(data)
echo("Finished reading! " & $no) echo("Finished reading! " & $no)
proc testAccept(s: AsyncSocket, disp: PDispatcher, no: int) = proc testAccept(s: AsyncSocket, disp: Dispatcher, no: int) =
echo("Accepting client! " & $no) echo("Accepting client! " & $no)
var client: AsyncSocket var client: AsyncSocket
new(client) new(client)
@ -691,7 +691,7 @@ when isMainModule:
var d = newDispatcher() var d = newDispatcher()
var s = asyncSocket() var s = asyncSocket()
s.connect("amber.tenthbit.net", TPort(6667)) s.connect("amber.tenthbit.net", Port(6667))
s.handleConnect = s.handleConnect =
proc (s: AsyncSocket) = proc (s: AsyncSocket) =
testConnect(s, 1) testConnect(s, 1)
@ -704,7 +704,7 @@ when isMainModule:
server.handleAccept = server.handleAccept =
proc (s: AsyncSocket) = proc (s: AsyncSocket) =
testAccept(s, d, 78) testAccept(s, d, 78)
server.bindAddr(TPort(5555)) server.bindAddr(Port(5555))
server.listen() server.listen()
d.register(server) d.register(server)

View file

@ -18,7 +18,7 @@ import strutils
## ##
## Quick start example: ## Quick start example:
## ##
## # Create a matrix wich first rotates, then scales and at last translates ## # Create a matrix which first rotates, then scales and at last translates
## ##
## var m:TMatrix2d=rotate(DEG90) & scale(2.0) & move(100.0,200.0) ## var m:TMatrix2d=rotate(DEG90) & scale(2.0) & move(100.0,200.0)
## ##
@ -256,7 +256,7 @@ proc `$`* (t:TMatrix2d):string {.noInit.} =
proc isUniform*(t:TMatrix2d,tol=1.0e-6):bool= proc isUniform*(t:TMatrix2d,tol=1.0e-6):bool=
## Checks if the transform is uniform, that is ## Checks if the transform is uniform, that is
## perpendicular axes of equal lenght, which means (for example) ## perpendicular axes of equal length, which means (for example)
## it cannot transform a circle into an ellipse. ## it cannot transform a circle into an ellipse.
## `tol` is used as tolerance for both equal length comparison ## `tol` is used as tolerance for both equal length comparison
## and perp. comparison. ## and perp. comparison.
@ -305,7 +305,7 @@ proc equals*(m1:TMatrix2d,m2:TMatrix2d,tol=1.0e-6):bool=
abs(m1.ty-m2.ty)<=tol abs(m1.ty-m2.ty)<=tol
proc `=~`*(m1,m2:TMatrix2d):bool= proc `=~`*(m1,m2:TMatrix2d):bool=
## Checks if `m1`and `m2` is aproximately equal, using a ## Checks if `m1`and `m2` is approximately equal, using a
## tolerance of 1e-6. ## tolerance of 1e-6.
equals(m1,m2) equals(m1,m2)

View file

@ -23,7 +23,7 @@ import times
## ##
## Quick start example: ## Quick start example:
## ##
## # Create a matrix wich first rotates, then scales and at last translates ## # Create a matrix which first rotates, then scales and at last translates
## ##
## var m:TMatrix3d=rotate(PI,vector3d(1,1,2.5)) & scale(2.0) & move(100.0,200.0,300.0) ## var m:TMatrix3d=rotate(PI,vector3d(1,1,2.5)) & scale(2.0) & move(100.0,200.0,300.0)
## ##
@ -320,7 +320,7 @@ proc rotateZ*(angle:float):TMatrix3d {.noInit.}=
proc isUniform*(m:TMatrix3d,tol=1.0e-6):bool= proc isUniform*(m:TMatrix3d,tol=1.0e-6):bool=
## Checks if the transform is uniform, that is ## Checks if the transform is uniform, that is
## perpendicular axes of equal lenght, which means (for example) ## perpendicular axes of equal length, which means (for example)
## it cannot transform a sphere into an ellipsoid. ## it cannot transform a sphere into an ellipsoid.
## `tol` is used as tolerance for both equal length comparison ## `tol` is used as tolerance for both equal length comparison
## and perpendicular comparison. ## and perpendicular comparison.
@ -483,7 +483,7 @@ proc equals*(m1:TMatrix3d,m2:TMatrix3d,tol=1.0e-6):bool=
abs(m1.tw-m2.tw)<=tol abs(m1.tw-m2.tw)<=tol
proc `=~`*(m1,m2:TMatrix3d):bool= proc `=~`*(m1,m2:TMatrix3d):bool=
## Checks if `m1` and `m2` is aproximately equal, using a ## Checks if `m1` and `m2` is approximately equal, using a
## tolerance of 1e-6. ## tolerance of 1e-6.
equals(m1,m2) equals(m1,m2)
@ -788,7 +788,7 @@ proc angleTo*(v1,v2:TVector3d):float=
proc arbitraryAxis*(norm:TVector3d):TMatrix3d {.noInit.}= proc arbitraryAxis*(norm:TVector3d):TMatrix3d {.noInit.}=
## Computes the rotation matrix that would transform ## Computes the rotation matrix that would transform
## world z vector into `norm`. The inverse of this matrix ## world z vector into `norm`. The inverse of this matrix
## is useful to tranform a planar 3d object to 2d space. ## is useful to transform a planar 3d object to 2d space.
## This is the same algorithm used to interpret DXF and DWG files. ## This is the same algorithm used to interpret DXF and DWG files.
const lim=1.0/64.0 const lim=1.0/64.0
var ax,ay,az:TVector3d var ax,ay,az:TVector3d

View file

@ -42,7 +42,7 @@ proc openDefaultBrowser*(url: string) =
for b in getEnv("BROWSER").string.split(PathSep): for b in getEnv("BROWSER").string.split(PathSep):
try: try:
# we use ``startProcess`` here because we don't want to block! # we use ``startProcess`` here because we don't want to block!
discard startProcess(command=b, args=[url], options={poUseShell}) discard startProcess(command=b, args=[url], options={poUsePath})
return return
except OSError: except OSError:
discard discard

View file

@ -404,7 +404,7 @@ proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int,
#echo("tomb old slot then set in new table") #echo("tomb old slot then set in new table")
nextTable = copySlotAndCheck(table,idx) nextTable = copySlotAndCheck(table,idx)
return setVal(nextTable, key, val, expVal, match) return setVal(nextTable, key, val, expVal, match)
# Finaly ready to add new val to table # Finally ready to add new val to table
while true: while true:
if match and oldVal != expVal: if match and oldVal != expVal:
#echo("set failed, no match oldVal= " & $oldVal & " expVal= " & $expVal) #echo("set failed, no match oldVal= " & $oldVal & " expVal= " & $expVal)

View file

@ -174,7 +174,7 @@ proc excl*[T](c: var CritBitTree[T], key: string) =
iterator leaves[T](n: Node[T]): Node[T] = iterator leaves[T](n: Node[T]): Node[T] =
if n != nil: if n != nil:
# XXX actually we could compute the necessary stack size in advance: # XXX actually we could compute the necessary stack size in advance:
# it's rougly log2(c.count). # it's roughly log2(c.count).
var stack = @[n] var stack = @[n]
while stack.len > 0: while stack.len > 0:
var it = stack.pop var it = stack.pop

View file

@ -191,9 +191,10 @@ proc `$`*(s: IntSet): string =
## The `$` operator for int sets. ## The `$` operator for int sets.
dollarImpl() dollarImpl()
proc empty*(s: IntSet): bool {.inline.} = proc empty*(s: IntSet): bool {.inline, deprecated.} =
## returns true if `s` is empty. This is safe to call even before ## returns true if `s` is empty. This is safe to call even before
## the set has been initialized with `initIntSet`. ## the set has been initialized with `initIntSet`. Note this never
## worked reliably and so is deprecated.
result = s.counter == 0 result = s.counter == 0
when isMainModule: when isMainModule:

View file

@ -320,7 +320,7 @@ template foldl*(sequence, operation: expr): expr =
## ##
## The ``operation`` parameter should be an expression which uses the ## The ``operation`` parameter should be an expression which uses the
## variables ``a`` and ``b`` for each step of the fold. Since this is a left ## variables ``a`` and ``b`` for each step of the fold. Since this is a left
## fold, for non associative binary operations like substraction think that ## fold, for non associative binary operations like subtraction think that
## the sequence of numbers 1, 2 and 3 will be parenthesized as (((1) - 2) - ## the sequence of numbers 1, 2 and 3 will be parenthesized as (((1) - 2) -
## 3). Example: ## 3). Example:
## ##
@ -328,12 +328,12 @@ template foldl*(sequence, operation: expr): expr =
## let ## let
## numbers = @[5, 9, 11] ## numbers = @[5, 9, 11]
## addition = foldl(numbers, a + b) ## addition = foldl(numbers, a + b)
## substraction = foldl(numbers, a - b) ## subtraction = foldl(numbers, a - b)
## multiplication = foldl(numbers, a * b) ## multiplication = foldl(numbers, a * b)
## words = @["nim", "is", "cool"] ## words = @["nim", "is", "cool"]
## concatenation = foldl(words, a & b) ## concatenation = foldl(words, a & b)
## assert addition == 25, "Addition is (((5)+9)+11)" ## assert addition == 25, "Addition is (((5)+9)+11)"
## assert substraction == -15, "Substraction is (((5)-9)-11)" ## assert subtraction == -15, "Subtraction is (((5)-9)-11)"
## assert multiplication == 495, "Multiplication is (((5)*9)*11)" ## assert multiplication == 495, "Multiplication is (((5)*9)*11)"
## assert concatenation == "nimiscool" ## assert concatenation == "nimiscool"
assert sequence.len > 0, "Can't fold empty sequences" assert sequence.len > 0, "Can't fold empty sequences"
@ -356,7 +356,7 @@ template foldr*(sequence, operation: expr): expr =
## ##
## The ``operation`` parameter should be an expression which uses the ## The ``operation`` parameter should be an expression which uses the
## variables ``a`` and ``b`` for each step of the fold. Since this is a right ## variables ``a`` and ``b`` for each step of the fold. Since this is a right
## fold, for non associative binary operations like substraction think that ## fold, for non associative binary operations like subtraction think that
## the sequence of numbers 1, 2 and 3 will be parenthesized as (1 - (2 - ## the sequence of numbers 1, 2 and 3 will be parenthesized as (1 - (2 -
## (3))). Example: ## (3))). Example:
## ##
@ -364,12 +364,12 @@ template foldr*(sequence, operation: expr): expr =
## let ## let
## numbers = @[5, 9, 11] ## numbers = @[5, 9, 11]
## addition = foldr(numbers, a + b) ## addition = foldr(numbers, a + b)
## substraction = foldr(numbers, a - b) ## subtraction = foldr(numbers, a - b)
## multiplication = foldr(numbers, a * b) ## multiplication = foldr(numbers, a * b)
## words = @["nim", "is", "cool"] ## words = @["nim", "is", "cool"]
## concatenation = foldr(words, a & b) ## concatenation = foldr(words, a & b)
## assert addition == 25, "Addition is (5+(9+(11)))" ## assert addition == 25, "Addition is (5+(9+(11)))"
## assert substraction == 7, "Substraction is (5-(9-(11)))" ## assert subtraction == 7, "Subtraction is (5-(9-(11)))"
## assert multiplication == 495, "Multiplication is (5*(9*(11)))" ## assert multiplication == 495, "Multiplication is (5*(9*(11)))"
## assert concatenation == "nimiscool" ## assert concatenation == "nimiscool"
assert sequence.len > 0, "Can't fold empty sequences" assert sequence.len > 0, "Can't fold empty sequences"
@ -507,12 +507,12 @@ when isMainModule:
let let
numbers = @[5, 9, 11] numbers = @[5, 9, 11]
addition = foldl(numbers, a + b) addition = foldl(numbers, a + b)
substraction = foldl(numbers, a - b) subtraction = foldl(numbers, a - b)
multiplication = foldl(numbers, a * b) multiplication = foldl(numbers, a * b)
words = @["nim", "is", "cool"] words = @["nim", "is", "cool"]
concatenation = foldl(words, a & b) concatenation = foldl(words, a & b)
assert addition == 25, "Addition is (((5)+9)+11)" assert addition == 25, "Addition is (((5)+9)+11)"
assert substraction == -15, "Substraction is (((5)-9)-11)" assert subtraction == -15, "Subtraction is (((5)-9)-11)"
assert multiplication == 495, "Multiplication is (((5)*9)*11)" assert multiplication == 495, "Multiplication is (((5)*9)*11)"
assert concatenation == "nimiscool" assert concatenation == "nimiscool"
@ -520,12 +520,12 @@ when isMainModule:
let let
numbers = @[5, 9, 11] numbers = @[5, 9, 11]
addition = foldr(numbers, a + b) addition = foldr(numbers, a + b)
substraction = foldr(numbers, a - b) subtraction = foldr(numbers, a - b)
multiplication = foldr(numbers, a * b) multiplication = foldr(numbers, a * b)
words = @["nim", "is", "cool"] words = @["nim", "is", "cool"]
concatenation = foldr(words, a & b) concatenation = foldr(words, a & b)
assert addition == 25, "Addition is (5+(9+(11)))" assert addition == 25, "Addition is (5+(9+(11)))"
assert substraction == 7, "Substraction is (5-(9-(11)))" assert subtraction == 7, "Subtraction is (5-(9-(11)))"
assert multiplication == 495, "Multiplication is (5*(9*(11)))" assert multiplication == 495, "Multiplication is (5*(9*(11)))"
assert concatenation == "nimiscool" assert concatenation == "nimiscool"

View file

@ -11,7 +11,7 @@
## (also often named `dictionary`:idx: in other programming languages) that is ## (also often named `dictionary`:idx: in other programming languages) that is
## a mapping from keys to values. ``Table`` is the usual hash table, ## a mapping from keys to values. ``Table`` is the usual hash table,
## ``OrderedTable`` is like ``Table`` but remembers insertion order ## ``OrderedTable`` is like ``Table`` but remembers insertion order
## and ``CountTable`` is a mapping from a key to its number of occurances. ## and ``CountTable`` is a mapping from a key to its number of occurrences.
## For consistency with every other data type in Nim these have **value** ## For consistency with every other data type in Nim these have **value**
## semantics, this means that ``=`` performs a copy of the hash table. ## semantics, this means that ``=`` performs a copy of the hash table.
## For **reference** semantics use the ``Ref`` variant: ``TableRef``, ## For **reference** semantics use the ``Ref`` variant: ``TableRef``,
@ -231,31 +231,42 @@ template addImpl() {.dirty.} =
rawInsert(t, t.data, key, val, hc, j) rawInsert(t, t.data, key, val, hc, j)
inc(t.counter) inc(t.counter)
template maybeRehashPutImpl() {.dirty.} =
if mustRehash(len(t.data), t.counter):
enlarge(t)
index = rawGetKnownHC(t, key, hc)
index = -1 - index # important to transform for mgetOrPutImpl
rawInsert(t, t.data, key, val, hc, index)
inc(t.counter)
template putImpl() {.dirty.} = template putImpl() {.dirty.} =
var hc: THash var hc: THash
var index = rawGet(t, key, hc) var index = rawGet(t, key, hc)
if index >= 0: if index >= 0: t.data[index].val = val
t.data[index].val = val else: maybeRehashPutImpl()
else:
if mustRehash(len(t.data), t.counter):
enlarge(t)
index = rawGetKnownHC(t, key, hc)
rawInsert(t, t.data, key, val, hc, -1 - index)
inc(t.counter)
when false: template mgetOrPutImpl() {.dirty.} =
# not yet used: var hc: THash
template hasKeyOrPutImpl() {.dirty.} = var index = rawGet(t, key, hc)
var hc: THash if index < 0: maybeRehashPutImpl() # not present: insert (flipping index)
var index = rawGet(t, key, hc) result = t.data[index].val # either way return modifiable val
if index >= 0:
t.data[index].val = val template hasKeyOrPutImpl() {.dirty.} =
result = true var hc: THash
else: var index = rawGet(t, key, hc)
if mustRehash(len(t.data), t.counter): enlarge(t) if index < 0:
rawInsert(t, t.data, key, val) result = false
inc(t.counter) maybeRehashPutImpl()
result = false else: result = true
proc mgetOrPut*[A, B](t: var Table[A, B], key: A, val: B): var B =
## retrieves value at ``t[key]`` or puts ``val`` if not present, either way
## returning a value which can be modified.
mgetOrPutImpl()
proc hasKeyOrPut*[A, B](t: var Table[A, B], key: A, val: B): bool =
## returns true iff `key` is in the table, otherwise inserts `value`.
hasKeyOrPutImpl()
proc `[]=`*[A, B](t: var Table[A, B], key: A, val: B) = proc `[]=`*[A, B](t: var Table[A, B], key: A, val: B) =
## puts a (key, value)-pair into `t`. ## puts a (key, value)-pair into `t`.
@ -383,6 +394,15 @@ proc mget*[A, B](t: TableRef[A, B], key: A): var B =
## If `key` is not in `t`, the ``EInvalidKey`` exception is raised. ## If `key` is not in `t`, the ``EInvalidKey`` exception is raised.
t[].mget(key) t[].mget(key)
proc mgetOrPut*[A, B](t: TableRef[A, B], key: A, val: B): var B =
## retrieves value at ``t[key]`` or puts ``val`` if not present, either way
## returning a value which can be modified.
t[].mgetOrPut(key, val)
proc hasKeyOrPut*[A, B](t: var TableRef[A, B], key: A, val: B): bool =
## returns true iff `key` is in the table, otherwise inserts `value`.
t[].hasKeyOrPut(key, val)
proc hasKey*[A, B](t: TableRef[A, B], key: A): bool = proc hasKey*[A, B](t: TableRef[A, B], key: A): bool =
## returns true iff `key` is in the table `t`. ## returns true iff `key` is in the table `t`.
result = t[].hasKey(key) result = t[].hasKey(key)
@ -539,6 +559,15 @@ proc add*[A, B](t: var OrderedTable[A, B], key: A, val: B) =
## puts a new (key, value)-pair into `t` even if ``t[key]`` already exists. ## puts a new (key, value)-pair into `t` even if ``t[key]`` already exists.
addImpl() addImpl()
proc mgetOrPut*[A, B](t: var OrderedTable[A, B], key: A, val: B): var B =
## retrieves value at ``t[key]`` or puts ``value`` if not present, either way
## returning a value which can be modified.
mgetOrPutImpl()
proc hasKeyOrPut*[A, B](t: var OrderedTable[A, B], key: A, val: B): bool =
## returns true iff `key` is in the table, otherwise inserts `value`.
hasKeyOrPutImpl()
proc initOrderedTable*[A, B](initialSize=64): OrderedTable[A, B] = proc initOrderedTable*[A, B](initialSize=64): OrderedTable[A, B] =
## creates a new ordered hash table that is empty. ## creates a new ordered hash table that is empty.
## ##
@ -658,6 +687,15 @@ proc mget*[A, B](t: OrderedTableRef[A, B], key: A): var B =
## If `key` is not in `t`, the ``EInvalidKey`` exception is raised. ## If `key` is not in `t`, the ``EInvalidKey`` exception is raised.
result = t[].mget(key) result = t[].mget(key)
proc mgetOrPut*[A, B](t: OrderedTableRef[A, B], key: A, val: B): var B =
## retrieves value at ``t[key]`` or puts ``val`` if not present, either way
## returning a value which can be modified.
result = t[].mgetOrPut(key, val)
proc hasKeyOrPut*[A, B](t: var OrderedTableRef[A, B], key: A, val: B): bool =
## returns true iff `key` is in the table, otherwise inserts `val`.
result = t[].hasKeyOrPut(key, val)
proc hasKey*[A, B](t: OrderedTableRef[A, B], key: A): bool = proc hasKey*[A, B](t: OrderedTableRef[A, B], key: A): bool =
## returns true iff `key` is in the table `t`. ## returns true iff `key` is in the table `t`.
result = t[].hasKey(key) result = t[].hasKey(key)

View file

@ -46,7 +46,7 @@ proc `+`*(a, b: Color): Color =
colorOp(satPlus) colorOp(satPlus)
proc `-`*(a, b: Color): Color = proc `-`*(a, b: Color): Color =
## substracts two colors: This uses saturated artithmetic, so that each color ## subtracts two colors: This uses saturated artithmetic, so that each color
## component cannot overflow (255 is used as a maximum). ## component cannot overflow (255 is used as a maximum).
colorOp(satMinus) colorOp(satMinus)
@ -392,7 +392,7 @@ proc parseColor*(name: string): Color =
result = Color(parseHexInt(name)) result = Color(parseHexInt(name))
else: else:
var idx = binaryStrSearch(colorNames, name) var idx = binaryStrSearch(colorNames, name)
if idx < 0: raise newException(ValueError, "unkown color: " & name) if idx < 0: raise newException(ValueError, "unknown color: " & name)
result = colorNames[idx][1] result = colorNames[idx][1]
proc isColor*(name: string): bool = proc isColor*(name: string): bool =

View file

@ -301,7 +301,7 @@ proc getCurrentEncoding*(): string =
proc open*(destEncoding = "UTF-8", srcEncoding = "CP1252"): EncodingConverter = proc open*(destEncoding = "UTF-8", srcEncoding = "CP1252"): EncodingConverter =
## opens a converter that can convert from `srcEncoding` to `destEncoding`. ## opens a converter that can convert from `srcEncoding` to `destEncoding`.
## Raises `EIO` if it cannot fullfill the request. ## Raises `EIO` if it cannot fulfill the request.
when not defined(windows): when not defined(windows):
result = iconvOpen(destEncoding, srcEncoding) result = iconvOpen(destEncoding, srcEncoding)
if result == nil: if result == nil:

View file

@ -9,7 +9,7 @@
## :Author: Alex Mitchell ## :Author: Alex Mitchell
## ##
## This module implements an event system that is not dependant on external ## This module implements an event system that is not dependent on external
## graphical toolkits. It was originally called ``NimEE`` because ## graphical toolkits. It was originally called ``NimEE`` because
## it was inspired by Python's PyEE module. There are two ways you can use ## it was inspired by Python's PyEE module. There are two ways you can use
## events: one is a python-inspired way; the other is more of a C-style way. ## events: one is a python-inspired way; the other is more of a C-style way.

View file

@ -29,7 +29,7 @@ type
FSMonitorObj = object of RootObj FSMonitorObj = object of RootObj
fd: cint fd: cint
handleEvent: proc (m: FSMonitor, ev: MonitorEvent) {.closure.} handleEvent: proc (m: FSMonitor, ev: MonitorEvent) {.closure.}
targets: TTable[cint, string] targets: Table[cint, string]
MonitorEventType* = enum ## Monitor event type MonitorEventType* = enum ## Monitor event type
MonitorAccess, ## File was accessed. MonitorAccess, ## File was accessed.
@ -64,7 +64,7 @@ type
const const
MaxEvents = 100 MaxEvents = 100
proc newMonitor*(): PFSMonitor = proc newMonitor*(): FSMonitor =
## Creates a new file system monitor. ## Creates a new file system monitor.
new(result) new(result)
result.targets = initTable[cint, string]() result.targets = initTable[cint, string]()
@ -72,7 +72,7 @@ proc newMonitor*(): PFSMonitor =
if result.fd < 0: if result.fd < 0:
raiseOSError(osLastError()) raiseOSError(osLastError())
proc add*(monitor: PFSMonitor, target: string, proc add*(monitor: FSMonitor, target: string,
filters = {MonitorAll}): cint {.discardable.} = filters = {MonitorAll}): cint {.discardable.} =
## Adds ``target`` which may be a directory or a file to the list of ## Adds ``target`` which may be a directory or a file to the list of
## watched paths of ``monitor``. ## watched paths of ``monitor``.
@ -99,14 +99,14 @@ proc add*(monitor: PFSMonitor, target: string,
raiseOSError(osLastError()) raiseOSError(osLastError())
monitor.targets.add(result, target) monitor.targets.add(result, target)
proc del*(monitor: PFSMonitor, wd: cint) = proc del*(monitor: FSMonitor, wd: cint) =
## Removes watched directory or file as specified by ``wd`` from ``monitor``. ## Removes watched directory or file as specified by ``wd`` from ``monitor``.
## ##
## If ``wd`` is not a part of ``monitor`` an EOS error is raised. ## If ``wd`` is not a part of ``monitor`` an EOS error is raised.
if inotifyRmWatch(monitor.fd, wd) < 0: if inotifyRmWatch(monitor.fd, wd) < 0:
raiseOSError(osLastError()) raiseOSError(osLastError())
proc getEvent(m: PFSMonitor, fd: cint): seq[TMonitorEvent] = proc getEvent(m: FSMonitor, fd: cint): seq[MonitorEvent] =
result = @[] result = @[]
let size = (sizeof(TINotifyEvent)+2000)*MaxEvents let size = (sizeof(TINotifyEvent)+2000)*MaxEvents
var buffer = newString(size) var buffer = newString(size)
@ -118,7 +118,7 @@ proc getEvent(m: PFSMonitor, fd: cint): seq[TMonitorEvent] =
var i = 0 var i = 0
while i < le: while i < le:
var event = cast[ptr TINotifyEvent](addr(buffer[i])) var event = cast[ptr TINotifyEvent](addr(buffer[i]))
var mev: TMonitorEvent var mev: MonitorEvent
mev.wd = event.wd mev.wd = event.wd
if event.len.int != 0: if event.len.int != 0:
let cstr = event.name.addr.cstring let cstr = event.name.addr.cstring
@ -137,7 +137,7 @@ proc getEvent(m: PFSMonitor, fd: cint): seq[TMonitorEvent] =
# Find the MovedFrom event. # Find the MovedFrom event.
mev.oldPath = movedFrom[event.cookie.cint].old mev.oldPath = movedFrom[event.cookie.cint].old
mev.newPath = "" # Set later mev.newPath = "" # Set later
# Delete it from the TTable # Delete it from the Table
movedFrom.del(event.cookie.cint) movedFrom.del(event.cookie.cint)
elif (event.mask.int and IN_ACCESS) != 0: mev.kind = MonitorAccess elif (event.mask.int and IN_ACCESS) != 0: mev.kind = MonitorAccess
elif (event.mask.int and IN_ATTRIB) != 0: mev.kind = MonitorAttrib elif (event.mask.int and IN_ATTRIB) != 0: mev.kind = MonitorAttrib
@ -164,26 +164,26 @@ proc getEvent(m: PFSMonitor, fd: cint): seq[TMonitorEvent] =
# If movedFrom events have not been matched with a moveTo. File has # If movedFrom events have not been matched with a moveTo. File has
# been moved to an unwatched location, emit a MonitorDelete. # been moved to an unwatched location, emit a MonitorDelete.
for cookie, t in pairs(movedFrom): for cookie, t in pairs(movedFrom):
var mev: TMonitorEvent var mev: MonitorEvent
mev.kind = MonitorDelete mev.kind = MonitorDelete
mev.wd = t.wd mev.wd = t.wd
mev.name = t.old mev.name = t.old
result.add(mev) result.add(mev)
proc FSMonitorRead(h: PObject) = proc FSMonitorRead(h: RootRef) =
var events = PFSMonitor(h).getEvent(PFSMonitor(h).fd) var events = FSMonitor(h).getEvent(FSMonitor(h).fd)
#var newEv: TMonitorEvent #var newEv: MonitorEvent
for ev in events: for ev in events:
var target = PFSMonitor(h).targets[ev.wd] var target = FSMonitor(h).targets[ev.wd]
var newEv = ev var newEv = ev
if newEv.kind == MonitorMoved: if newEv.kind == MonitorMoved:
newEv.oldPath = target / newEv.oldPath newEv.oldPath = target / newEv.oldPath
newEv.newPath = target / newEv.name newEv.newPath = target / newEv.name
else: else:
newEv.fullName = target / newEv.name newEv.fullName = target / newEv.name
PFSMonitor(h).handleEvent(PFSMonitor(h), newEv) FSMonitor(h).handleEvent(FSMonitor(h), newEv)
proc toDelegate(m: PFSMonitor): PDelegate = proc toDelegate(m: FSMonitor): Delegate =
result = newDelegate() result = newDelegate()
result.deleVal = m result.deleVal = m
result.fd = (type(result.fd))(m.fd) result.fd = (type(result.fd))(m.fd)
@ -191,8 +191,8 @@ proc toDelegate(m: PFSMonitor): PDelegate =
result.handleRead = FSMonitorRead result.handleRead = FSMonitorRead
result.open = true result.open = true
proc register*(d: PDispatcher, monitor: PFSMonitor, proc register*(d: Dispatcher, monitor: FSMonitor,
handleEvent: proc (m: PFSMonitor, ev: TMonitorEvent) {.closure.}) = handleEvent: proc (m: FSMonitor, ev: MonitorEvent) {.closure.}) =
## Registers ``monitor`` with dispatcher ``d``. ## Registers ``monitor`` with dispatcher ``d``.
monitor.handleEvent = handleEvent monitor.handleEvent = handleEvent
var deleg = toDelegate(monitor) var deleg = toDelegate(monitor)
@ -204,7 +204,7 @@ when isMainModule:
var monitor = newMonitor() var monitor = newMonitor()
echo monitor.add("/home/dom/inotifytests/") echo monitor.add("/home/dom/inotifytests/")
disp.register(monitor, disp.register(monitor,
proc (m: PFSMonitor, ev: TMonitorEvent) = proc (m: FSMonitor, ev: MonitorEvent) =
echo("Got event: ", ev.kind) echo("Got event: ", ev.kind)
if ev.kind == MonitorMoved: if ev.kind == MonitorMoved:
echo("From ", ev.oldPath, " to ", ev.newPath) echo("From ", ev.oldPath, " to ", ev.newPath)

View file

@ -107,7 +107,7 @@ type
EInvalidReply: ReplyError, EFTP: FTPError EInvalidReply: ReplyError, EFTP: FTPError
].} ].}
proc ftpClient*(address: string, port = TPort(21), proc ftpClient*(address: string, port = Port(21),
user, pass = ""): FtpClient = user, pass = ""): FtpClient =
## Create a ``FtpClient`` object. ## Create a ``FtpClient`` object.
new(result) new(result)
@ -120,10 +120,10 @@ proc ftpClient*(address: string, port = TPort(21),
result.csock = socket() result.csock = socket()
if result.csock == invalidSocket: raiseOSError(osLastError()) if result.csock == invalidSocket: raiseOSError(osLastError())
template blockingOperation(sock: TSocket, body: stmt) {.immediate.} = template blockingOperation(sock: Socket, body: stmt) {.immediate.} =
body body
template blockingOperation(sock: asyncio.PAsyncSocket, body: stmt) {.immediate.} = template blockingOperation(sock: asyncio.AsyncSocket, body: stmt) {.immediate.} =
sock.setBlocking(true) sock.setBlocking(true)
body body
sock.setBlocking(false) sock.setBlocking(false)
@ -145,14 +145,14 @@ proc send*[T](ftp: FtpBase[T], m: string): TaintedString =
proc assertReply(received: TaintedString, expected: string) = proc assertReply(received: TaintedString, expected: string) =
if not received.string.startsWith(expected): if not received.string.startsWith(expected):
raise newException(EInvalidReply, raise newException(ReplyError,
"Expected reply '$1' got: $2" % [ "Expected reply '$1' got: $2" % [
expected, received.string]) expected, received.string])
proc assertReply(received: TaintedString, expected: varargs[string]) = proc assertReply(received: TaintedString, expected: varargs[string]) =
for i in items(expected): for i in items(expected):
if received.string.startsWith(i): return if received.string.startsWith(i): return
raise newException(EInvalidReply, raise newException(ReplyError,
"Expected reply '$1' got: $2" % "Expected reply '$1' got: $2" %
[expected.join("' or '"), received.string]) [expected.join("' or '"), received.string])
@ -161,7 +161,7 @@ proc createJob[T](ftp: FtpBase[T],
nimcall,gcsafe.}, nimcall,gcsafe.},
cmd: FTPJobType) = cmd: FTPJobType) =
if ftp.jobInProgress: if ftp.jobInProgress:
raise newException(EFTP, "Unable to do two jobs at once.") raise newException(FTPError, "Unable to do two jobs at once.")
ftp.jobInProgress = true ftp.jobInProgress = true
new(ftp.job) new(ftp.job)
ftp.job.prc = prc ftp.job.prc = prc
@ -182,11 +182,11 @@ proc deleteJob[T](ftp: FtpBase[T]) =
ftp.job.file.close() ftp.job.file.close()
ftp.dsock.close() ftp.dsock.close()
proc handleTask(s: PAsyncSocket, ftp: PAsyncFTPClient) = proc handleTask(s: AsyncSocket, ftp: AsyncFTPClient) =
if ftp.jobInProgress: if ftp.jobInProgress:
if ftp.job.typ in {JRetr, JStore}: if ftp.job.typ in {JRetr, JStore}:
if epochTime() - ftp.job.lastProgressReport >= 1.0: if epochTime() - ftp.job.lastProgressReport >= 1.0:
var r: TFTPEvent var r: FTPEvent
ftp.job.lastProgressReport = epochTime() ftp.job.lastProgressReport = epochTime()
r.typ = EvTransferProgress r.typ = EvTransferProgress
r.bytesTotal = ftp.job.total r.bytesTotal = ftp.job.total
@ -195,22 +195,22 @@ proc handleTask(s: PAsyncSocket, ftp: PAsyncFTPClient) =
r.filename = ftp.job.filename r.filename = ftp.job.filename
r.currentJob = ftp.job.typ r.currentJob = ftp.job.typ
ftp.job.oneSecond = 0 ftp.job.oneSecond = 0
ftp.handleEvent(PAsyncFTPClient(ftp), r) ftp.handleEvent(ftp, r)
proc handleWrite(s: PAsyncSocket, ftp: PAsyncFTPClient) = proc handleWrite(s: AsyncSocket, ftp: AsyncFTPClient) =
if ftp.jobInProgress: if ftp.jobInProgress:
if ftp.job.typ == JStore: if ftp.job.typ == JStore:
assert (not ftp.job.prc(ftp, true)) assert (not ftp.job.prc(ftp, true))
proc handleConnect(s: PAsyncSocket, ftp: PAsyncFTPClient) = proc handleConnect(s: AsyncSocket, ftp: AsyncFTPClient) =
ftp.dsockConnected = true ftp.dsockConnected = true
assert(ftp.jobInProgress) assert(ftp.jobInProgress)
if ftp.job.typ == JStore: if ftp.job.typ == JStore:
s.setHandleWrite(proc (s: PAsyncSocket) = handleWrite(s, ftp)) s.setHandleWrite(proc (s: AsyncSocket) = handleWrite(s, ftp))
else: else:
s.delHandleWrite() s.delHandleWrite()
proc handleRead(s: PAsyncSocket, ftp: PAsyncFTPClient) = proc handleRead(s: AsyncSocket, ftp: AsyncFTPClient) =
assert ftp.jobInProgress assert ftp.jobInProgress
assert ftp.job.typ != JStore assert ftp.job.typ != JStore
# This can never return true, because it shouldn't check for code # This can never return true, because it shouldn't check for code
@ -219,19 +219,19 @@ proc handleRead(s: PAsyncSocket, ftp: PAsyncFTPClient) =
proc pasv[T](ftp: FtpBase[T]) = proc pasv[T](ftp: FtpBase[T]) =
## Negotiate a data connection. ## Negotiate a data connection.
when T is TSocket: when T is Socket:
ftp.dsock = socket() ftp.dsock = socket()
if ftp.dsock == invalidSocket: raiseOSError(osLastError()) if ftp.dsock == invalidSocket: raiseOSError(osLastError())
elif T is PAsyncSocket: elif T is AsyncSocket:
ftp.dsock = asyncSocket() ftp.dsock = asyncSocket()
ftp.dsock.handleRead = ftp.dsock.handleRead =
proc (s: PAsyncSocket) = proc (s: AsyncSocket) =
handleRead(s, ftp) handleRead(s, ftp)
ftp.dsock.handleConnect = ftp.dsock.handleConnect =
proc (s: PAsyncSocket) = proc (s: AsyncSocket) =
handleConnect(s, ftp) handleConnect(s, ftp)
ftp.dsock.handleTask = ftp.dsock.handleTask =
proc (s: PAsyncSocket) = proc (s: AsyncSocket) =
handleTask(s, ftp) handleTask(s, ftp)
ftp.disp.register(ftp.dsock) ftp.disp.register(ftp.dsock)
else: else:
@ -244,8 +244,8 @@ proc pasv[T](ftp: FtpBase[T]) =
var ip = nums[0.. -3] var ip = nums[0.. -3]
var port = nums[-2.. -1] var port = nums[-2.. -1]
var properPort = port[0].parseInt()*256+port[1].parseInt() var properPort = port[0].parseInt()*256+port[1].parseInt()
ftp.dsock.connect(ip.join("."), TPort(properPort.toU16)) ftp.dsock.connect(ip.join("."), Port(properPort.toU16))
when T is PAsyncSocket: when T is AsyncSocket:
ftp.dsockConnected = false ftp.dsockConnected = false
else: else:
ftp.dsockConnected = true ftp.dsockConnected = true
@ -255,10 +255,10 @@ proc normalizePathSep(path: string): string =
proc connect*[T](ftp: FtpBase[T]) = proc connect*[T](ftp: FtpBase[T]) =
## Connect to the FTP server specified by ``ftp``. ## Connect to the FTP server specified by ``ftp``.
when T is PAsyncSocket: when T is AsyncSocket:
blockingOperation(ftp.csock): blockingOperation(ftp.csock):
ftp.csock.connect(ftp.address, ftp.port) ftp.csock.connect(ftp.address, ftp.port)
elif T is TSocket: elif T is Socket:
ftp.csock.connect(ftp.address, ftp.port) ftp.csock.connect(ftp.address, ftp.port)
else: else:
{.fatal: "Incorrect socket instantiation".} {.fatal: "Incorrect socket instantiation".}
@ -292,13 +292,13 @@ proc getLines[T](ftp: FtpBase[T], async: bool = false): bool =
## It doesn't if `async` is true, because it doesn't check for 226 then. ## It doesn't if `async` is true, because it doesn't check for 226 then.
if ftp.dsockConnected: if ftp.dsockConnected:
var r = TaintedString"" var r = TaintedString""
when T is PAsyncSocket: when T is AsyncSocket:
if ftp.asyncDSock.readLine(r): if ftp.asyncDSock.readLine(r):
if r.string == "": if r.string == "":
ftp.dsockConnected = false ftp.dsockConnected = false
else: else:
ftp.job.lines.add(r.string & "\n") ftp.job.lines.add(r.string & "\n")
elif T is TSocket: elif T is Socket:
assert(not async) assert(not async)
ftp.dsock.readLine(r) ftp.dsock.readLine(r)
if r.string == "": if r.string == "":
@ -309,7 +309,7 @@ proc getLines[T](ftp: FtpBase[T], async: bool = false): bool =
{.fatal: "Incorrect socket instantiation".} {.fatal: "Incorrect socket instantiation".}
if not async: if not async:
var readSocks: seq[TSocket] = @[ftp.csock] var readSocks: seq[Socket] = @[ftp.csock]
# This is only needed here. Asyncio gets this socket... # This is only needed here. Asyncio gets this socket...
blockingOperation(ftp.csock): blockingOperation(ftp.csock):
if readSocks.select(1) != 0 and ftp.csock in readSocks: if readSocks.select(1) != 0 and ftp.csock in readSocks:
@ -372,7 +372,7 @@ proc createDir*[T](ftp: FtpBase[T], dir: string, recursive: bool = false) =
assertReply reply, "257" assertReply reply, "257"
proc chmod*[T](ftp: FtpBase[T], path: string, proc chmod*[T](ftp: FtpBase[T], path: string,
permissions: set[TFilePermission]) = permissions: set[FilePermission]) =
## Changes permission of ``path`` to ``permissions``. ## Changes permission of ``path`` to ``permissions``.
var userOctal = 0 var userOctal = 0
var groupOctal = 0 var groupOctal = 0
@ -431,8 +431,8 @@ proc getFile[T](ftp: FtpBase[T], async = false): bool =
var bytesRead = 0 var bytesRead = 0
var returned = false var returned = false
if async: if async:
when T is TSocket: when T is Socket:
raise newException(EFTP, "FTPClient must be async.") raise newException(FTPError, "FTPClient must be async.")
else: else:
bytesRead = ftp.dsock.recvAsync(r, BufferSize) bytesRead = ftp.dsock.recvAsync(r, BufferSize)
returned = bytesRead != -1 returned = bytesRead != -1
@ -447,9 +447,9 @@ proc getFile[T](ftp: FtpBase[T], async = false): bool =
elif returned and r2 == "": elif returned and r2 == "":
ftp.dsockConnected = false ftp.dsockConnected = false
when T is TSocket: when T is Socket:
if not async: if not async:
var readSocks: seq[TSocket] = @[ftp.csock] var readSocks: seq[Socket] = @[ftp.csock]
blockingOperation(ftp.csock): blockingOperation(ftp.csock):
if readSocks.select(1) != 0 and ftp.csock in readSocks: if readSocks.select(1) != 0 and ftp.csock in readSocks:
assertReply ftp.expectReply(), "226" assertReply ftp.expectReply(), "226"
@ -467,10 +467,10 @@ proc retrFile*[T](ftp: FtpBase[T], file, dest: string, async = false) =
var reply = ftp.send("RETR " & file.normalizePathSep) var reply = ftp.send("RETR " & file.normalizePathSep)
assertReply reply, ["125", "150"] assertReply reply, ["125", "150"]
if {'(', ')'} notin reply.string: if {'(', ')'} notin reply.string:
raise newException(EInvalidReply, "Reply has no file size.") raise newException(ReplyError, "Reply has no file size.")
var fileSize: BiggestInt var fileSize: BiggestInt
if reply.string.captureBetween('(', ')').parseBiggestInt(fileSize) == 0: if reply.string.captureBetween('(', ')').parseBiggestInt(fileSize) == 0:
raise newException(EInvalidReply, "Reply has no file size.") raise newException(ReplyError, "Reply has no file size.")
ftp.job.total = fileSize ftp.job.total = fileSize
ftp.job.lastProgressReport = epochTime() ftp.job.lastProgressReport = epochTime()
@ -545,10 +545,10 @@ proc close*[T](ftp: FtpBase[T]) =
ftp.csock.close() ftp.csock.close()
ftp.dsock.close() ftp.dsock.close()
proc csockHandleRead(s: PAsyncSocket, ftp: PAsyncFTPClient) = proc csockHandleRead(s: AsyncSocket, ftp: AsyncFTPClient) =
if ftp.jobInProgress: if ftp.jobInProgress:
assertReply ftp.expectReply(), "226" # Make sure the transfer completed. assertReply ftp.expectReply(), "226" # Make sure the transfer completed.
var r: TFTPEvent var r: FTPEvent
case ftp.job.typ case ftp.job.typ
of JRetrText: of JRetrText:
r.typ = EvLines r.typ = EvLines
@ -557,21 +557,21 @@ proc csockHandleRead(s: PAsyncSocket, ftp: PAsyncFTPClient) =
r.typ = EvRetr r.typ = EvRetr
r.filename = ftp.job.filename r.filename = ftp.job.filename
if ftp.job.progress != ftp.job.total: if ftp.job.progress != ftp.job.total:
raise newException(EFTP, "Didn't download full file.") raise newException(FTPError, "Didn't download full file.")
of JStore: of JStore:
r.typ = EvStore r.typ = EvStore
r.filename = ftp.job.filename r.filename = ftp.job.filename
if ftp.job.progress != ftp.job.total: if ftp.job.progress != ftp.job.total:
raise newException(EFTP, "Didn't upload full file.") raise newException(FTPError, "Didn't upload full file.")
ftp.deleteJob() ftp.deleteJob()
ftp.handleEvent(ftp, r) ftp.handleEvent(ftp, r)
proc asyncFTPClient*(address: string, port = TPort(21), proc asyncFTPClient*(address: string, port = Port(21),
user, pass = "", user, pass = "",
handleEvent: proc (ftp: PAsyncFTPClient, ev: TFTPEvent) {.closure,gcsafe.} = handleEvent: proc (ftp: AsyncFTPClient, ev: FTPEvent) {.closure,gcsafe.} =
(proc (ftp: PAsyncFTPClient, ev: TFTPEvent) = discard)): PAsyncFTPClient = (proc (ftp: AsyncFTPClient, ev: FTPEvent) = discard)): AsyncFTPClient =
## Create a ``PAsyncFTPClient`` object. ## Create a ``AsyncFTPClient`` object.
## ##
## Use this if you want to use asyncio's dispatcher. ## Use this if you want to use asyncio's dispatcher.
var dres: AsyncFtpClient var dres: AsyncFtpClient
@ -588,7 +588,7 @@ proc asyncFTPClient*(address: string, port = TPort(21),
csockHandleRead(s, dres) csockHandleRead(s, dres)
result = dres result = dres
proc register*(d: PDispatcher, ftp: PAsyncFTPClient): PDelegate {.discardable.} = proc register*(d: Dispatcher, ftp: AsyncFTPClient): Delegate {.discardable.} =
## Registers ``ftp`` with dispatcher ``d``. ## Registers ``ftp`` with dispatcher ``d``.
ftp.disp = d ftp.disp = d
return ftp.disp.register(ftp.csock) return ftp.disp.register(ftp.csock)

View file

@ -552,7 +552,7 @@ proc parse(x: var XmlParser, errors: var seq[string]): XmlNode =
proc parseHtml*(s: Stream, filename: string, proc parseHtml*(s: Stream, filename: string,
errors: var seq[string]): XmlNode = errors: var seq[string]): XmlNode =
## parses the XML from stream `s` and returns a ``PXmlNode``. Every ## parses the XML from stream `s` and returns a ``PXmlNode``. Every
## occured parsing error is added to the `errors` sequence. ## occurred parsing error is added to the `errors` sequence.
var x: XmlParser var x: XmlParser
open(x, s, filename, {reportComments, reportWhitespace}) open(x, s, filename, {reportComments, reportWhitespace})
next(x) next(x)
@ -581,7 +581,7 @@ proc parseHtml*(s: Stream): XmlNode =
proc loadHtml*(path: string, errors: var seq[string]): XmlNode = proc loadHtml*(path: string, errors: var seq[string]): XmlNode =
## Loads and parses HTML from file specified by ``path``, and returns ## Loads and parses HTML from file specified by ``path``, and returns
## a ``PXmlNode``. Every occured parsing error is added to ## a ``PXmlNode``. Every occurred parsing error is added to
## the `errors` sequence. ## the `errors` sequence.
var s = newFileStream(path, fmRead) var s = newFileStream(path, fmRead)
if s == nil: raise newException(IOError, "Unable to read file: " & path) if s == nil: raise newException(IOError, "Unable to read file: " & path)

View file

@ -385,7 +385,7 @@ proc request*(url: string, httpMethod: string, extraHeaders = "",
userAgent = defUserAgent, proxy: Proxy = nil): Response = userAgent = defUserAgent, proxy: Proxy = nil): Response =
## | Requests ``url`` with the custom method string specified by the ## | Requests ``url`` with the custom method string specified by the
## | ``httpMethod`` parameter. ## | ``httpMethod`` parameter.
## | Extra headers can be specified and must be seperated by ``\c\L`` ## | Extra headers can be specified and must be separated by ``\c\L``
## | An optional timeout can be specified in miliseconds, if reading from the ## | An optional timeout can be specified in miliseconds, if reading from the
## server takes longer than specified an ETimeout exception will be raised. ## server takes longer than specified an ETimeout exception will be raised.
var r = if proxy == nil: parseUri(url) else: proxy.url var r = if proxy == nil: parseUri(url) else: proxy.url
@ -436,7 +436,7 @@ proc request*(url: string, httpMethod = httpGET, extraHeaders = "",
body = "", sslContext = defaultSSLContext, timeout = -1, body = "", sslContext = defaultSSLContext, timeout = -1,
userAgent = defUserAgent, proxy: Proxy = nil): Response = userAgent = defUserAgent, proxy: Proxy = nil): Response =
## | Requests ``url`` with the specified ``httpMethod``. ## | Requests ``url`` with the specified ``httpMethod``.
## | Extra headers can be specified and must be seperated by ``\c\L`` ## | Extra headers can be specified and must be separated by ``\c\L``
## | An optional timeout can be specified in miliseconds, if reading from the ## | An optional timeout can be specified in miliseconds, if reading from the
## server takes longer than specified an ETimeout exception will be raised. ## server takes longer than specified an ETimeout exception will be raised.
result = request(url, $httpMethod, extraHeaders, body, sslContext, timeout, result = request(url, $httpMethod, extraHeaders, body, sslContext, timeout,

View file

@ -55,7 +55,7 @@ import
type type
JsonEventKind* = enum ## enumeration of all events that may occur when parsing JsonEventKind* = enum ## enumeration of all events that may occur when parsing
jsonError, ## an error ocurred during parsing jsonError, ## an error occurred during parsing
jsonEof, ## end of file reached jsonEof, ## end of file reached
jsonString, ## a string literal jsonString, ## a string literal
jsonInt, ## an integer literal jsonInt, ## an integer literal

View file

@ -8,7 +8,7 @@
# #
## This module implements a simple logger. It has been designed to be as simple ## This module implements a simple logger. It has been designed to be as simple
## as possible to avoid bloat, if this library does not fullfill your needs, ## as possible to avoid bloat, if this library does not fulfill your needs,
## write your own. ## write your own.
## ##
## Format strings support the following variables which must be prefixed with ## Format strings support the following variables which must be prefixed with

View file

@ -258,7 +258,7 @@ proc socketError*(socket: Socket, err: int = -1, async = false,
of SSL_ERROR_WANT_X509_LOOKUP: of SSL_ERROR_WANT_X509_LOOKUP:
raiseSSLError("Function for x509 lookup has been called.") raiseSSLError("Function for x509 lookup has been called.")
of SSL_ERROR_SYSCALL: of SSL_ERROR_SYSCALL:
var errStr = "IO error has occured " var errStr = "IO error has occurred "
let sslErr = ErrPeekLastError() let sslErr = ErrPeekLastError()
if sslErr == 0 and err == 0: if sslErr == 0 and err == 0:
errStr.add "because an EOF was observed that violates the protocol" errStr.add "because an EOF was observed that violates the protocol"
@ -887,7 +887,7 @@ proc connectAsync(socket: Socket, name: string, port = Port(0),
af: Domain = AF_INET) {.tags: [ReadIOEffect].} = af: Domain = AF_INET) {.tags: [ReadIOEffect].} =
## A variant of ``connect`` for non-blocking sockets. ## A variant of ``connect`` for non-blocking sockets.
## ##
## This procedure will immediatelly return, it will not block until a connection ## This procedure will immediately return, it will not block until a connection
## is made. It is up to the caller to make sure the connection has been established ## is made. It is up to the caller to make sure the connection has been established
## by checking (using ``select``) whether the socket is writeable. ## by checking (using ``select``) whether the socket is writeable.
## ##

View file

@ -185,7 +185,7 @@ const
proc osErrorMsg*(): string {.rtl, extern: "nos$1", deprecated.} = proc osErrorMsg*(): string {.rtl, extern: "nos$1", deprecated.} =
## Retrieves the operating system's error flag, ``errno``. ## Retrieves the operating system's error flag, ``errno``.
## On Windows ``GetLastError`` is checked before ``errno``. ## On Windows ``GetLastError`` is checked before ``errno``.
## Returns "" if no error occured. ## Returns "" if no error occurred.
## ##
## **Deprecated since version 0.9.4**: use the other ``osErrorMsg`` proc. ## **Deprecated since version 0.9.4**: use the other ``osErrorMsg`` proc.
@ -1099,7 +1099,7 @@ when defined(windows):
var var
env = getEnvironmentStringsW() env = getEnvironmentStringsW()
e = env e = env
if e == nil: return # an error occured if e == nil: return # an error occurred
while true: while true:
var eend = strEnd(e) var eend = strEnd(e)
add(environment, $e) add(environment, $e)
@ -1110,7 +1110,7 @@ when defined(windows):
var var
env = getEnvironmentStringsA() env = getEnvironmentStringsA()
e = env e = env
if e == nil: return # an error occured if e == nil: return # an error occurred
while true: while true:
var eend = strEnd(e) var eend = strEnd(e)
add(environment, $e) add(environment, $e)
@ -1182,7 +1182,7 @@ proc putEnv*(key, val: string) {.tags: [WriteEnvEffect].} =
## If an error occurs, `EInvalidEnvVar` is raised. ## If an error occurs, `EInvalidEnvVar` is raised.
# Note: by storing the string in the environment sequence, # Note: by storing the string in the environment sequence,
# we gurantee that we don't free the memory before the program # we guarantee that we don't free the memory before the program
# ends (this is needed for POSIX compliance). It is also needed so that # ends (this is needed for POSIX compliance). It is also needed so that
# the process itself may access its modified environment variables! # the process itself may access its modified environment variables!
var indx = findEnvVar(key) var indx = findEnvVar(key)
@ -1454,7 +1454,7 @@ proc createHardlink*(src, dest: string) =
proc parseCmdLine*(c: string): seq[string] {. proc parseCmdLine*(c: string): seq[string] {.
noSideEffect, rtl, extern: "nos$1".} = noSideEffect, rtl, extern: "nos$1".} =
## Splits a command line into several components; ## Splits a command line into several components;
## This proc is only occassionally useful, better use the `parseopt` module. ## This proc is only occasionally useful, better use the `parseopt` module.
## ##
## On Windows, it uses the following parsing rules ## On Windows, it uses the following parsing rules
## (see http://msdn.microsoft.com/en-us/library/17w5ykft.aspx ): ## (see http://msdn.microsoft.com/en-us/library/17w5ykft.aspx ):

View file

@ -146,7 +146,7 @@ proc startProcess*(command: string,
## of `args` to `command` carefully escaping/quoting any special characters, ## of `args` to `command` carefully escaping/quoting any special characters,
## since it will be passed *as is* to the system shell. Each system/shell may ## since it will be passed *as is* to the system shell. Each system/shell may
## feature different escaping rules, so try to avoid this kind of shell ## feature different escaping rules, so try to avoid this kind of shell
## invokation if possible as it leads to non portable software. ## invocation if possible as it leads to non portable software.
## ##
## Return value: The newly created process object. Nil is never returned, ## Return value: The newly created process object. Nil is never returned,
## but ``EOS`` is raised in case of an error. ## but ``EOS`` is raised in case of an error.
@ -260,7 +260,7 @@ proc execProcesses*(cmds: openArray[string],
for i in 0..m-1: for i in 0..m-1:
if beforeRunEvent != nil: if beforeRunEvent != nil:
beforeRunEvent(i) beforeRunEvent(i)
q[i] = startCmd(cmds[i], options=options) q[i] = startProcess(cmds[i], options=options + {poEvalCommand})
when defined(noBusyWaiting): when defined(noBusyWaiting):
var r = 0 var r = 0
for i in m..high(cmds): for i in m..high(cmds):
@ -275,7 +275,7 @@ proc execProcesses*(cmds: openArray[string],
if q[r] != nil: close(q[r]) if q[r] != nil: close(q[r])
if beforeRunEvent != nil: if beforeRunEvent != nil:
beforeRunEvent(i) beforeRunEvent(i)
q[r] = startCmd(cmds[i], options=options) q[r] = startProcess(cmds[i], options=options + {poEvalCommand})
r = (r + 1) mod n r = (r + 1) mod n
else: else:
var i = m var i = m
@ -288,7 +288,7 @@ proc execProcesses*(cmds: openArray[string],
if q[r] != nil: close(q[r]) if q[r] != nil: close(q[r])
if beforeRunEvent != nil: if beforeRunEvent != nil:
beforeRunEvent(i) beforeRunEvent(i)
q[r] = startCmd(cmds[i], options=options) q[r] = startProcess(cmds[i], options=options + {poEvalCommand})
inc(i) inc(i)
if i > high(cmds): break if i > high(cmds): break
for j in 0..m-1: for j in 0..m-1:
@ -298,7 +298,7 @@ proc execProcesses*(cmds: openArray[string],
for i in 0..high(cmds): for i in 0..high(cmds):
if beforeRunEvent != nil: if beforeRunEvent != nil:
beforeRunEvent(i) beforeRunEvent(i)
var p = startCmd(cmds[i], options=options) var p = startProcess(cmds[i], options=options + {poEvalCommand})
result = max(waitForExit(p), result) result = max(waitForExit(p), result)
close(p) close(p)
@ -644,14 +644,14 @@ elif not defined(useNimRtl):
var pid: TPid var pid: TPid
var sysArgs = allocCStringArray(sysArgsRaw) var sysArgs = allocCStringArray(sysArgsRaw)
finally: deallocCStringArray(sysArgs) defer: deallocCStringArray(sysArgs)
var sysEnv = if env == nil: var sysEnv = if env == nil:
envToCStringArray() envToCStringArray()
else: else:
envToCStringArray(env) envToCStringArray(env)
finally: deallocCStringArray(sysEnv) defer: deallocCStringArray(sysEnv)
var data: TStartProcessData var data: TStartProcessData
data.sysCommand = sysCommand data.sysCommand = sysCommand
@ -748,7 +748,7 @@ elif not defined(useNimRtl):
if pipe(data.pErrorPipe) != 0: if pipe(data.pErrorPipe) != 0:
raiseOSError(osLastError()) raiseOSError(osLastError())
finally: defer:
discard close(data.pErrorPipe[readIdx]) discard close(data.pErrorPipe[readIdx])
var pid: TPid var pid: TPid
@ -956,7 +956,7 @@ proc execCmdEx*(command: string, options: set[ProcessOption] = {
exitCode: int] {.tags: [ExecIOEffect, ReadIOEffect], gcsafe.} = exitCode: int] {.tags: [ExecIOEffect, ReadIOEffect], gcsafe.} =
## a convenience proc that runs the `command`, grabs all its output and ## a convenience proc that runs the `command`, grabs all its output and
## exit code and returns both. ## exit code and returns both.
var p = startCmd(command, options) var p = startProcess(command, options=options + {poEvalCommand})
var outp = outputStream(p) var outp = outputStream(p)
result = (TaintedString"", -1) result = (TaintedString"", -1)
var line = newStringOfCap(120).TaintedString var line = newStringOfCap(120).TaintedString

View file

@ -35,7 +35,7 @@ type
cfgSectionStart, ## a ``[section]`` has been parsed cfgSectionStart, ## a ``[section]`` has been parsed
cfgKeyValuePair, ## a ``key=value`` pair has been detected cfgKeyValuePair, ## a ``key=value`` pair has been detected
cfgOption, ## a ``--key=value`` command line option cfgOption, ## a ``--key=value`` command line option
cfgError ## an error ocurred during parsing cfgError ## an error occurred during parsing
CfgEvent* = object of RootObj ## describes a parsing event CfgEvent* = object of RootObj ## describes a parsing event
case kind*: CfgEventKind ## the kind of the event case kind*: CfgEventKind ## the kind of the event

View file

@ -60,7 +60,7 @@ proc initOptParser*(cmdline: string): OptParser {.rtl, deprecated.} =
## Initalizes option parses with cmdline. Splits cmdline in on spaces ## Initalizes option parses with cmdline. Splits cmdline in on spaces
## and calls initOptParser(openarray[string]) ## and calls initOptParser(openarray[string])
## Do not use. ## Do not use.
if cmdline == "": # backward compatibilty if cmdline == "": # backward compatibility
return initOptParser(seq[string](nil)) return initOptParser(seq[string](nil))
else: else:
return initOptParser(cmdline.split) return initOptParser(cmdline.split)

View file

@ -181,7 +181,7 @@ proc parseWhile*(s: string, token: var string, validChars: set[char],
token = substr(s, start, i-1) token = substr(s, start, i-1)
proc captureBetween*(s: string, first: char, second = '\0', start = 0): string = proc captureBetween*(s: string, first: char, second = '\0', start = 0): string =
## Finds the first occurence of ``first``, then returns everything from there ## Finds the first occurrence of ``first``, then returns everything from there
## up to ``second``(if ``second`` is '\0', then ``first`` is used). ## up to ``second``(if ``second`` is '\0', then ``first`` is used).
var i = skipUntil(s, first, start)+1+start var i = skipUntil(s, first, start)+1+start
result = "" result = ""
@ -240,7 +240,7 @@ proc parseBiggestFloat*(s: string, number: var BiggestFloat, start = 0): int {.
proc parseFloat*(s: string, number: var float, start = 0): int {. proc parseFloat*(s: string, number: var float, start = 0): int {.
rtl, extern: "npuParseFloat", noSideEffect.} = rtl, extern: "npuParseFloat", noSideEffect.} =
## parses a float starting at `start` and stores the value into `number`. ## parses a float starting at `start` and stores the value into `number`.
## Result is the number of processed chars or 0 if there occured a parsing ## Result is the number of processed chars or 0 if there occurred a parsing
## error. ## error.
var bf: BiggestFloat var bf: BiggestFloat
result = parseBiggestFloat(s, bf, start) result = parseBiggestFloat(s, bf, start)

View file

@ -57,7 +57,7 @@ import
type type
XmlEventKind* = enum ## enumation of all events that may occur when parsing XmlEventKind* = enum ## enumation of all events that may occur when parsing
xmlError, ## an error ocurred during parsing xmlError, ## an error occurred during parsing
xmlEof, ## end of file reached xmlEof, ## end of file reached
xmlCharData, ## character data xmlCharData, ## character data
xmlWhitespace, ## whitespace has been parsed xmlWhitespace, ## whitespace has been parsed

View file

@ -43,7 +43,7 @@ proc isConc(r: Rope): bool {.inline.} = return isNil(r.data)
# Note that the left and right pointers are not needed for leafs. # Note that the left and right pointers are not needed for leafs.
# Leaves have relatively high memory overhead (~30 bytes on a 32 # Leaves have relatively high memory overhead (~30 bytes on a 32
# bit machine) and we produce many of them. This is why we cache and # bit machine) and we produce many of them. This is why we cache and
# share leafs accross different rope trees. # share leafs across different rope trees.
# To cache them they are inserted in another tree, a splay tree for best # To cache them they are inserted in another tree, a splay tree for best
# performance. But for the caching tree we use the leaf's left and right # performance. But for the caching tree we use the leaf's left and right
# pointers. # pointers.

View file

@ -35,7 +35,7 @@ type
when defined(nimdoc): when defined(nimdoc):
type type
Selector* = ref object Selector* = ref object
## An object which holds file descripters to be checked for read/write ## An object which holds file descriptors to be checked for read/write
## status. ## status.
fds: Table[SocketHandle, SelectorKey] fds: Table[SocketHandle, SelectorKey]

View file

@ -851,7 +851,7 @@ proc connectAsync*(socket: Socket, name: string, port = Port(0),
af: Domain = AF_INET) {.tags: [ReadIOEffect].} = af: Domain = AF_INET) {.tags: [ReadIOEffect].} =
## A variant of ``connect`` for non-blocking sockets. ## A variant of ``connect`` for non-blocking sockets.
## ##
## This procedure will immediatelly return, it will not block until a connection ## This procedure will immediately return, it will not block until a connection
## is made. It is up to the caller to make sure the connection has been established ## is made. It is up to the caller to make sure the connection has been established
## by checking (using ``select``) whether the socket is writeable. ## by checking (using ``select``) whether the socket is writeable.
## ##
@ -1467,7 +1467,7 @@ proc recvAsync*(socket: Socket, s: var TaintedString): bool {.
of SSL_ERROR_ZERO_RETURN: of SSL_ERROR_ZERO_RETURN:
raiseSslError("TLS/SSL connection failed to initiate, socket closed prematurely.") raiseSslError("TLS/SSL connection failed to initiate, socket closed prematurely.")
of SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT: of SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT:
raiseSslError("Unexpected error occured.") # This should just not happen. raiseSslError("Unexpected error occurred.") # This should just not happen.
of SSL_ERROR_WANT_WRITE, SSL_ERROR_WANT_READ: of SSL_ERROR_WANT_WRITE, SSL_ERROR_WANT_READ:
return false return false
of SSL_ERROR_WANT_X509_LOOKUP: of SSL_ERROR_WANT_X509_LOOKUP:
@ -1610,7 +1610,7 @@ proc sendAsync*(socket: Socket, data: string): int {.tags: [WriteIOEffect].} =
of SSL_ERROR_ZERO_RETURN: of SSL_ERROR_ZERO_RETURN:
raiseSslError("TLS/SSL connection failed to initiate, socket closed prematurely.") raiseSslError("TLS/SSL connection failed to initiate, socket closed prematurely.")
of SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT: of SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT:
raiseSslError("Unexpected error occured.") # This should just not happen. raiseSslError("Unexpected error occurred.") # This should just not happen.
of SSL_ERROR_WANT_WRITE, SSL_ERROR_WANT_READ: of SSL_ERROR_WANT_WRITE, SSL_ERROR_WANT_READ:
return 0 return 0
of SSL_ERROR_WANT_X509_LOOKUP: of SSL_ERROR_WANT_X509_LOOKUP:

View file

@ -122,41 +122,41 @@ proc read[T](s: Stream, result: var T) =
raise newEIO("cannot read from stream") raise newEIO("cannot read from stream")
proc readChar*(s: Stream): char = proc readChar*(s: Stream): char =
## reads a char from the stream `s`. Raises `EIO` if an error occured. ## reads a char from the stream `s`. Raises `EIO` if an error occurred.
## Returns '\0' as an EOF marker. ## Returns '\0' as an EOF marker.
if readData(s, addr(result), sizeof(result)) != 1: result = '\0' if readData(s, addr(result), sizeof(result)) != 1: result = '\0'
proc readBool*(s: Stream): bool = proc readBool*(s: Stream): bool =
## reads a bool from the stream `s`. Raises `EIO` if an error occured. ## reads a bool from the stream `s`. Raises `EIO` if an error occurred.
read(s, result) read(s, result)
proc readInt8*(s: Stream): int8 = proc readInt8*(s: Stream): int8 =
## reads an int8 from the stream `s`. Raises `EIO` if an error occured. ## reads an int8 from the stream `s`. Raises `EIO` if an error occurred.
read(s, result) read(s, result)
proc readInt16*(s: Stream): int16 = proc readInt16*(s: Stream): int16 =
## reads an int16 from the stream `s`. Raises `EIO` if an error occured. ## reads an int16 from the stream `s`. Raises `EIO` if an error occurred.
read(s, result) read(s, result)
proc readInt32*(s: Stream): int32 = proc readInt32*(s: Stream): int32 =
## reads an int32 from the stream `s`. Raises `EIO` if an error occured. ## reads an int32 from the stream `s`. Raises `EIO` if an error occurred.
read(s, result) read(s, result)
proc readInt64*(s: Stream): int64 = proc readInt64*(s: Stream): int64 =
## reads an int64 from the stream `s`. Raises `EIO` if an error occured. ## reads an int64 from the stream `s`. Raises `EIO` if an error occurred.
read(s, result) read(s, result)
proc readFloat32*(s: Stream): float32 = proc readFloat32*(s: Stream): float32 =
## reads a float32 from the stream `s`. Raises `EIO` if an error occured. ## reads a float32 from the stream `s`. Raises `EIO` if an error occurred.
read(s, result) read(s, result)
proc readFloat64*(s: Stream): float64 = proc readFloat64*(s: Stream): float64 =
## reads a float64 from the stream `s`. Raises `EIO` if an error occured. ## reads a float64 from the stream `s`. Raises `EIO` if an error occurred.
read(s, result) read(s, result)
proc readStr*(s: Stream, length: int): TaintedString = proc readStr*(s: Stream, length: int): TaintedString =
## reads a string of length `length` from the stream `s`. Raises `EIO` if ## reads a string of length `length` from the stream `s`. Raises `EIO` if
## an error occured. ## an error occurred.
result = newString(length).TaintedString result = newString(length).TaintedString
var L = readData(s, addr(string(result)[0]), length) var L = readData(s, addr(string(result)[0]), length)
if L != length: setLen(result.string, L) if L != length: setLen(result.string, L)
@ -183,7 +183,7 @@ proc readLine*(s: Stream, line: var TaintedString): bool =
proc readLine*(s: Stream): TaintedString = proc readLine*(s: Stream): TaintedString =
## Reads a line from a stream `s`. Note: This is not very efficient. Raises ## Reads a line from a stream `s`. Note: This is not very efficient. Raises
## `EIO` if an error occured. ## `EIO` if an error occurred.
result = TaintedString"" result = TaintedString""
while true: while true:
var c = readChar(s) var c = readChar(s)

View file

@ -395,11 +395,13 @@ proc toHex*(x: BiggestInt, len: int): string {.noSideEffect,
const const
HexChars = "0123456789ABCDEF" HexChars = "0123456789ABCDEF"
var var
shift: BiggestInt n = x
result = newString(len) result = newString(len)
for j in countdown(len-1, 0): for j in countdown(len-1, 0):
result[j] = HexChars[toU32(x shr shift) and 0xF'i32] result[j] = HexChars[n and 0xF]
shift = shift + 4 n = n shr 4
# handle negative overflow
if n == 0 and x < 0: n = -1
proc intToStr*(x: int, minchars: int = 1): string {.noSideEffect, proc intToStr*(x: int, minchars: int = 1): string {.noSideEffect,
rtl, extern: "nsuIntToStr".} = rtl, extern: "nsuIntToStr".} =
@ -815,8 +817,8 @@ proc rfind*(s: string, sub: char, start: int = -1): int {.noSideEffect,
proc count*(s: string, sub: string, overlapping: bool = false): int {.noSideEffect, proc count*(s: string, sub: string, overlapping: bool = false): int {.noSideEffect,
rtl, extern: "nsuCountString".} = rtl, extern: "nsuCountString".} =
## Count the occurences of a substring `sub` in the string `s`. ## Count the occurrences of a substring `sub` in the string `s`.
## Overlapping occurences of `sub` only count when `overlapping` ## Overlapping occurrences of `sub` only count when `overlapping`
## is set to true. ## is set to true.
var i = 0 var i = 0
while true: while true:
@ -831,14 +833,14 @@ proc count*(s: string, sub: string, overlapping: bool = false): int {.noSideEffe
proc count*(s: string, sub: char): int {.noSideEffect, proc count*(s: string, sub: char): int {.noSideEffect,
rtl, extern: "nsuCountChar".} = rtl, extern: "nsuCountChar".} =
## Count the occurences of the character `sub` in the string `s`. ## Count the occurrences of the character `sub` in the string `s`.
for c in s: for c in s:
if c == sub: if c == sub:
inc result inc result
proc count*(s: string, subs: set[char]): int {.noSideEffect, proc count*(s: string, subs: set[char]): int {.noSideEffect,
rtl, extern: "nsuCountCharSet".} = rtl, extern: "nsuCountCharSet".} =
## Count the occurences of the group of character `subs` in the string `s`. ## Count the occurrences of the group of character `subs` in the string `s`.
for c in s: for c in s:
if c in subs: if c in subs:
inc result inc result
@ -898,7 +900,7 @@ proc replaceWord*(s, sub: string, by = ""): string {.noSideEffect,
rtl, extern: "nsuReplaceWord".} = rtl, extern: "nsuReplaceWord".} =
## Replaces `sub` in `s` by the string `by`. ## Replaces `sub` in `s` by the string `by`.
## ##
## Each occurance of `sub` has to be surrounded by word boundaries ## Each occurrence of `sub` has to be surrounded by word boundaries
## (comparable to ``\\w`` in regular expressions), otherwise it is not ## (comparable to ``\\w`` in regular expressions), otherwise it is not
## replaced. ## replaced.
const wordChars = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\128'..'\255'} const wordChars = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\128'..'\255'}

View file

@ -353,11 +353,11 @@ when isMainModule:
proc `%`(formatstr: string, a: openarray[string]): string = proc `%`(formatstr: string, a: openarray[string]): string =
result = newStringOfCap(formatstr.len + a.len shl 4) result = newStringOfCap(formatstr.len + a.len shl 4)
addf(result, formatstr.TSubex, a) addf(result, formatstr.Subex, a)
proc `%`(formatstr: string, a: string): string = proc `%`(formatstr: string, a: string): string =
result = newStringOfCap(formatstr.len + a.len) result = newStringOfCap(formatstr.len + a.len)
addf(result, formatstr.TSubex, [a]) addf(result, formatstr.Subex, [a])
doAssert "$# $3 $# $#" % ["a", "b", "c"] == "a c b c" doAssert "$# $3 $# $#" % ["a", "b", "c"] == "a c b c"

View file

@ -20,6 +20,7 @@ type
{.deprecated: [TUrl: Url, TUri: Uri].} {.deprecated: [TUrl: Url, TUri: Uri].}
{.push warning[deprecated]: off.}
proc `$`*(url: Url): string {.deprecated.} = proc `$`*(url: Url): string {.deprecated.} =
## **Deprecated since 0.9.6**: Use ``Uri`` instead. ## **Deprecated since 0.9.6**: Use ``Uri`` instead.
return string(url) return string(url)
@ -44,6 +45,7 @@ proc add*(url: var Url, a: Url) {.deprecated.} =
## ##
## **Deprecated since 0.9.6**: Use ``Uri`` instead. ## **Deprecated since 0.9.6**: Use ``Uri`` instead.
url = url / a url = url / a
{.pop.}
proc parseAuthority(authority: string, result: var Uri) = proc parseAuthority(authority: string, result: var Uri) =
var i = 0 var i = 0

View file

@ -642,7 +642,7 @@ proc isEmpty(s: string): bool =
return true return true
proc normalize*(n: PNode) = proc normalize*(n: PNode) =
## Merges all seperated TextNodes together, and removes any empty TextNodes ## Merges all separated TextNodes together, and removes any empty TextNodes
var curTextNode: PNode = nil var curTextNode: PNode = nil
var i: int = 0 var i: int = 0

View file

@ -103,7 +103,7 @@ proc parse(x: var XmlParser, errors: var seq[string]): XmlNode =
proc parseXml*(s: Stream, filename: string, proc parseXml*(s: Stream, filename: string,
errors: var seq[string]): XmlNode = errors: var seq[string]): XmlNode =
## parses the XML from stream `s` and returns a ``PXmlNode``. Every ## parses the XML from stream `s` and returns a ``PXmlNode``. Every
## occured parsing error is added to the `errors` sequence. ## occurred parsing error is added to the `errors` sequence.
var x: XmlParser var x: XmlParser
open(x, s, filename, {reportComments}) open(x, s, filename, {reportComments})
while true: while true:
@ -129,7 +129,7 @@ proc parseXml*(s: Stream): XmlNode =
proc loadXml*(path: string, errors: var seq[string]): XmlNode = proc loadXml*(path: string, errors: var seq[string]): XmlNode =
## Loads and parses XML from file specified by ``path``, and returns ## Loads and parses XML from file specified by ``path``, and returns
## a ``PXmlNode``. Every occured parsing error is added to the `errors` ## a ``PXmlNode``. Every occurred parsing error is added to the `errors`
## sequence. ## sequence.
var s = newFileStream(path, fmRead) var s = newFileStream(path, fmRead)
if s == nil: raise newException(IOError, "Unable to read file: " & path) if s == nil: raise newException(IOError, "Unable to read file: " & path)

View file

@ -73,7 +73,7 @@ type
expr* {.magic: Expr.} ## meta type to denote an expression (for templates) expr* {.magic: Expr.} ## meta type to denote an expression (for templates)
stmt* {.magic: Stmt.} ## meta type to denote a statement (for templates) stmt* {.magic: Stmt.} ## meta type to denote a statement (for templates)
typedesc* {.magic: TypeDesc.} ## meta type to denote a type description typedesc* {.magic: TypeDesc.} ## meta type to denote a type description
void* {.magic: "VoidType".} ## meta type to denote the absense of any type void* {.magic: "VoidType".} ## meta type to denote the absence of any type
auto* = expr auto* = expr
any* = distinct auto any* = distinct auto
@ -124,7 +124,7 @@ proc declared*(x: expr): bool {.magic: "Defined", noSideEffect.}
## feature or not: ## feature or not:
## ##
## .. code-block:: Nim ## .. code-block:: Nim
## when not defined(strutils.toUpper): ## when not declared(strutils.toUpper):
## # provide our own toUpper proc here, because strutils is ## # provide our own toUpper proc here, because strutils is
## # missing it. ## # missing it.
@ -357,7 +357,7 @@ type
## ##
## See the full `exception hierarchy`_. ## See the full `exception hierarchy`_.
IOError* = object of SystemError ## \ IOError* = object of SystemError ## \
## Raised if an IO error occured. ## Raised if an IO error occurred.
## ##
## See the full `exception hierarchy`_. ## See the full `exception hierarchy`_.
OSError* = object of SystemError ## \ OSError* = object of SystemError ## \
@ -370,11 +370,11 @@ type
## ##
## See the full `exception hierarchy`_. ## See the full `exception hierarchy`_.
ResourceExhaustedError* = object of SystemError ## \ ResourceExhaustedError* = object of SystemError ## \
## Raised if a resource request could not be fullfilled. ## Raised if a resource request could not be fulfilled.
## ##
## See the full `exception hierarchy`_. ## See the full `exception hierarchy`_.
ArithmeticError* = object of Exception ## \ ArithmeticError* = object of Exception ## \
## Raised if any kind of arithmetic error occured. ## Raised if any kind of arithmetic error occurred.
## ##
## See the full `exception hierarchy`_. ## See the full `exception hierarchy`_.
DivByZeroError* = object of ArithmeticError ## \ DivByZeroError* = object of ArithmeticError ## \
@ -578,7 +578,7 @@ proc len*(x: cstring): int {.magic: "LengthStr", noSideEffect.}
proc len*[I, T](x: array[I, T]): int {.magic: "LengthArray", noSideEffect.} proc len*[I, T](x: array[I, T]): int {.magic: "LengthArray", noSideEffect.}
proc len*[T](x: seq[T]): int {.magic: "LengthSeq", noSideEffect.} proc len*[T](x: seq[T]): int {.magic: "LengthSeq", noSideEffect.}
## returns the length of an array, an openarray, a sequence or a string. ## returns the length of an array, an openarray, a sequence or a string.
## This is rougly the same as ``high(T)-low(T)+1``, but its resulting type is ## This is roughly the same as ``high(T)-low(T)+1``, but its resulting type is
## always an int. ## always an int.
# set routines: # set routines:
@ -865,7 +865,7 @@ proc contains*[T](x: set[T], y: T): bool {.magic: "InSet", noSideEffect.}
## passes its arguments in reverse order. ## passes its arguments in reverse order.
proc contains*[T](s: Slice[T], value: T): bool {.noSideEffect, inline.} = proc contains*[T](s: Slice[T], value: T): bool {.noSideEffect, inline.} =
## Checks if `value` is withing the range of `s`; returns true iff ## Checks if `value` is within the range of `s`; returns true iff
## `value >= s.a and value <= s.b` ## `value >= s.a and value <= s.b`
## ##
## .. code-block:: Nim ## .. code-block:: Nim
@ -2457,7 +2457,7 @@ when not defined(JS): #and not defined(NimrodVM):
proc getFileSize*(f: File): int64 {.tags: [ReadIOEffect], benign.} proc getFileSize*(f: File): int64 {.tags: [ReadIOEffect], benign.}
## retrieves the file size (in bytes) of `f`. ## retrieves the file size (in bytes) of `f`.
proc readBytes*(f: File, a: var openArray[int8], start, len: int): int {. proc readBytes*(f: File, a: var openArray[int8|uint8], start, len: int): int {.
tags: [ReadIOEffect], benign.} tags: [ReadIOEffect], benign.}
## reads `len` bytes into the buffer `a` starting at ``a[start]``. Returns ## reads `len` bytes into the buffer `a` starting at ``a[start]``. Returns
## the actual number of bytes that have been read which may be less than ## the actual number of bytes that have been read which may be less than
@ -2475,7 +2475,7 @@ when not defined(JS): #and not defined(NimrodVM):
## the actual number of bytes that have been read which may be less than ## the actual number of bytes that have been read which may be less than
## `len` (if not as many bytes are remaining), but not greater. ## `len` (if not as many bytes are remaining), but not greater.
proc writeBytes*(f: File, a: openArray[int8], start, len: int): int {. proc writeBytes*(f: File, a: openArray[int8|uint8], start, len: int): int {.
tags: [WriteIOEffect], benign.} tags: [WriteIOEffect], benign.}
## writes the bytes of ``a[start..start+len-1]`` to the file `f`. Returns ## writes the bytes of ``a[start..start+len-1]`` to the file `f`. Returns
## the number of actual written bytes, which may be less than `len` in case ## the number of actual written bytes, which may be less than `len` in case

View file

@ -15,7 +15,7 @@ proc raiseOverflow {.compilerproc, noinline, noreturn.} =
sysFatal(OverflowError, "over- or underflow") sysFatal(OverflowError, "over- or underflow")
proc raiseDivByZero {.compilerproc, noinline, noreturn.} = proc raiseDivByZero {.compilerproc, noinline, noreturn.} =
sysFatal(DivByZeroError, "divison by zero") sysFatal(DivByZeroError, "division by zero")
proc addInt64(a, b: int64): int64 {.compilerProc, inline.} = proc addInt64(a, b: int64): int64 {.compilerProc, inline.} =
result = a +% b result = a +% b

View file

@ -13,7 +13,7 @@ proc addChar(s: NimString, c: char): NimString {.compilerProc, benign.}
type type
TLibHandle = pointer # private type TLibHandle = pointer # private type
TProcAddr = pointer # libary loading and loading of procs: TProcAddr = pointer # library loading and loading of procs:
proc nimLoadLibrary(path: string): TLibHandle {.compilerproc.} proc nimLoadLibrary(path: string): TLibHandle {.compilerproc.}
proc nimUnloadLibrary(lib: TLibHandle) {.compilerproc.} proc nimUnloadLibrary(lib: TLibHandle) {.compilerproc.}

View file

@ -8,7 +8,7 @@
# #
# This file implements the ability to call native procs from libraries. # This file implements the ability to call native procs from libraries.
# It is not possible to do this in a platform independant way, unfortunately. # It is not possible to do this in a platform independent way, unfortunately.
# However, the interface has been designed to take platform differences into # However, the interface has been designed to take platform differences into
# account and been ported to all major platforms. # account and been ported to all major platforms.

View file

@ -884,7 +884,7 @@ elif stackIncreases:
var var
jmpbufSize {.importc: "sizeof(jmp_buf)", nodecl.}: int jmpbufSize {.importc: "sizeof(jmp_buf)", nodecl.}: int
# a little hack to get the size of a TJmpBuf in the generated C code # a little hack to get the size of a TJmpBuf in the generated C code
# in a platform independant way # in a platform independent way
template forEachStackSlot(gch, gcMark: expr) {.immediate, dirty.} = template forEachStackSlot(gch, gcMark: expr) {.immediate, dirty.} =
var registers: C_JmpBuf var registers: C_JmpBuf

View file

@ -128,7 +128,7 @@ type
# cycle roots table that uses a cheap linear scan # cycle roots table that uses a cheap linear scan
# to find only possitively dead objects. # to find only possitively dead objects.
# One strategy is to perform it only for new objects # One strategy is to perform it only for new objects
# allocated between the invocations of CollectZCT. # allocated between the invocations of collectZCT.
# This index indicates the start of the range of # This index indicates the start of the range of
# such new objects within the table. # such new objects within the table.
when withRealTime: when withRealTime:
@ -140,7 +140,7 @@ var
gch* {.rtlThreadVar.}: TGcHeap gch* {.rtlThreadVar.}: TGcHeap
when not defined(useNimRtl): when not defined(useNimRtl):
InstantiateForRegion(gch.region) instantiateForRegion(gch.region)
template acquire(gch: TGcHeap) = template acquire(gch: TGcHeap) =
when hasThreadSupport and hasSharedHeap: when hasThreadSupport and hasSharedHeap:
@ -233,11 +233,11 @@ template addCycleRoot(cycleRoots: var TCellSeq, c: PCell) =
proc cellToUsr(cell: PCell): pointer {.inline.} = proc cellToUsr(cell: PCell): pointer {.inline.} =
# convert object (=pointer to refcount) to pointer to userdata # convert object (=pointer to refcount) to pointer to userdata
result = cast[pointer](cast[TAddress](cell)+%TAddress(sizeof(TCell))) result = cast[pointer](cast[ByteAddress](cell)+%ByteAddress(sizeof(TCell)))
proc usrToCell*(usr: pointer): PCell {.inline.} = proc usrToCell*(usr: pointer): PCell {.inline.} =
# convert pointer to userdata to object (=pointer to refcount) # convert pointer to userdata to object (=pointer to refcount)
result = cast[PCell](cast[TAddress](usr)-%TAddress(sizeof(TCell))) result = cast[PCell](cast[ByteAddress](usr)-%ByteAddress(sizeof(TCell)))
proc canbeCycleRoot(c: PCell): bool {.inline.} = proc canbeCycleRoot(c: PCell): bool {.inline.} =
result = ntfAcyclic notin c.typ.flags result = ntfAcyclic notin c.typ.flags
@ -255,10 +255,10 @@ when BitsPerPage mod (sizeof(int)*8) != 0:
# forward declarations: # forward declarations:
proc collectCT(gch: var TGcHeap) proc collectCT(gch: var TGcHeap)
proc IsOnStack*(p: pointer): bool {.noinline.} proc isOnStack*(p: pointer): bool {.noinline.}
proc forAllChildren(cell: PCell, op: TWalkOp) proc forAllChildren(cell: PCell, op: TWalkOp)
proc doOperation(p: pointer, op: TWalkOp) proc doOperation(p: pointer, op: TWalkOp)
proc forAllChildrenAux(dest: Pointer, mt: PNimType, op: TWalkOp) proc forAllChildrenAux(dest: pointer, mt: PNimType, op: TWalkOp)
# we need the prototype here for debugging purposes # we need the prototype here for debugging purposes
proc prepareDealloc(cell: PCell) = proc prepareDealloc(cell: PCell) =
@ -432,7 +432,7 @@ proc nimGCunrefNoCycle(p: pointer) {.compilerProc, inline.} =
sysAssert(allocInv(gch.region), "end nimGCunrefNoCycle 2") sysAssert(allocInv(gch.region), "end nimGCunrefNoCycle 2")
sysAssert(allocInv(gch.region), "end nimGCunrefNoCycle 5") sysAssert(allocInv(gch.region), "end nimGCunrefNoCycle 5")
template doAsgnRef(dest: ppointer, src: pointer, template doAsgnRef(dest: PPointer, src: pointer,
heapType = LocalHeap, cycleFlag = MaybeCyclic): stmt = heapType = LocalHeap, cycleFlag = MaybeCyclic): stmt =
sysAssert(not isOnStack(dest), "asgnRef") sysAssert(not isOnStack(dest), "asgnRef")
# BUGFIX: first incRef then decRef! # BUGFIX: first incRef then decRef!
@ -440,20 +440,20 @@ template doAsgnRef(dest: ppointer, src: pointer,
if dest[] != nil: doDecRef(usrToCell(dest[]), heapType, cycleFlag) if dest[] != nil: doDecRef(usrToCell(dest[]), heapType, cycleFlag)
dest[] = src dest[] = src
proc asgnRef(dest: ppointer, src: pointer) {.compilerProc, inline.} = proc asgnRef(dest: PPointer, src: pointer) {.compilerProc, inline.} =
# the code generator calls this proc! # the code generator calls this proc!
doAsgnRef(dest, src, LocalHeap, MaybeCyclic) doAsgnRef(dest, src, LocalHeap, MaybeCyclic)
proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerProc, inline.} = proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerProc, inline.} =
# the code generator calls this proc if it is known at compile time that no # the code generator calls this proc if it is known at compile time that no
# cycle is possible. # cycle is possible.
doAsgnRef(dest, src, LocalHeap, Acyclic) doAsgnRef(dest, src, LocalHeap, Acyclic)
proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerProc.} = proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerProc.} =
# unsureAsgnRef updates the reference counters only if dest is not on the # unsureAsgnRef updates the reference counters only if dest is not on the
# stack. It is used by the code generator if it cannot decide wether a # stack. It is used by the code generator if it cannot decide wether a
# reference is in the stack or not (this can happen for var parameters). # reference is in the stack or not (this can happen for var parameters).
if not IsOnStack(dest): if not isOnStack(dest):
if src != nil: doIncRef(usrToCell(src)) if src != nil: doIncRef(usrToCell(src))
# XXX we must detect a shared heap here # XXX we must detect a shared heap here
# better idea may be to just eliminate the need for unsureAsgnRef # better idea may be to just eliminate the need for unsureAsgnRef
@ -470,16 +470,16 @@ proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerProc.} =
when hasThreadSupport and hasSharedHeap: when hasThreadSupport and hasSharedHeap:
# shared heap version of the above procs # shared heap version of the above procs
proc asgnRefSh(dest: ppointer, src: pointer) {.compilerProc, inline.} = proc asgnRefSh(dest: PPointer, src: pointer) {.compilerProc, inline.} =
doAsgnRef(dest, src, SharedHeap, MaybeCyclic) doAsgnRef(dest, src, SharedHeap, MaybeCyclic)
proc asgnRefNoCycleSh(dest: ppointer, src: pointer) {.compilerProc, inline.} = proc asgnRefNoCycleSh(dest: PPointer, src: pointer) {.compilerProc, inline.} =
doAsgnRef(dest, src, SharedHeap, Acyclic) doAsgnRef(dest, src, SharedHeap, Acyclic)
proc initGC() = proc initGC() =
when not defined(useNimRtl): when not defined(useNimRtl):
when traceGC: when traceGC:
for i in low(TCellState)..high(TCellState): Init(states[i]) for i in low(TCellState)..high(TCellState): init(states[i])
gch.cycleThreshold = InitialCycleThreshold gch.cycleThreshold = InitialCycleThreshold
gch.stat.stackScans = 0 gch.stat.stackScans = 0
gch.stat.cycleCollections = 0 gch.stat.cycleCollections = 0
@ -491,11 +491,11 @@ proc initGC() =
init(gch.zct) init(gch.zct)
init(gch.tempStack) init(gch.tempStack)
init(gch.freeStack) init(gch.freeStack)
Init(gch.cycleRoots) init(gch.cycleRoots)
Init(gch.decStack) init(gch.decStack)
proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) = proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) =
var d = cast[TAddress](dest) var d = cast[ByteAddress](dest)
case n.kind case n.kind
of nkSlot: forAllChildrenAux(cast[pointer](d +% n.offset), n.typ, op) of nkSlot: forAllChildrenAux(cast[pointer](d +% n.offset), n.typ, op)
of nkList: of nkList:
@ -503,7 +503,7 @@ proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) =
# inlined for speed # inlined for speed
if n.sons[i].kind == nkSlot: if n.sons[i].kind == nkSlot:
if n.sons[i].typ.kind in {tyRef, tyString, tySequence}: if n.sons[i].typ.kind in {tyRef, tyString, tySequence}:
doOperation(cast[ppointer](d +% n.sons[i].offset)[], op) doOperation(cast[PPointer](d +% n.sons[i].offset)[], op)
else: else:
forAllChildrenAux(cast[pointer](d +% n.sons[i].offset), forAllChildrenAux(cast[pointer](d +% n.sons[i].offset),
n.sons[i].typ, op) n.sons[i].typ, op)
@ -514,19 +514,19 @@ proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) =
if m != nil: forAllSlotsAux(dest, m, op) if m != nil: forAllSlotsAux(dest, m, op)
of nkNone: sysAssert(false, "forAllSlotsAux") of nkNone: sysAssert(false, "forAllSlotsAux")
proc forAllChildrenAux(dest: Pointer, mt: PNimType, op: TWalkOp) = proc forAllChildrenAux(dest: pointer, mt: PNimType, op: TWalkOp) =
var d = cast[TAddress](dest) var d = cast[ByteAddress](dest)
if dest == nil: return # nothing to do if dest == nil: return # nothing to do
if ntfNoRefs notin mt.flags: if ntfNoRefs notin mt.flags:
case mt.Kind case mt.kind
of tyRef, tyString, tySequence: # leaf: of tyRef, tyString, tySequence: # leaf:
doOperation(cast[ppointer](d)[], op) doOperation(cast[PPointer](d)[], op)
of tyObject, tyTuple: of tyObject, tyTuple:
forAllSlotsAux(dest, mt.node, op) forAllSlotsAux(dest, mt.node, op)
of tyArray, tyArrayConstr, tyOpenArray: of tyArray, tyArrayConstr, tyOpenArray:
for i in 0..(mt.size div mt.base.size)-1: for i in 0..(mt.size div mt.base.size)-1:
forAllChildrenAux(cast[pointer](d +% i *% mt.base.size), mt.base, op) forAllChildrenAux(cast[pointer](d +% i *% mt.base.size), mt.base, op)
else: nil else: discard
proc forAllChildren(cell: PCell, op: TWalkOp) = proc forAllChildren(cell: PCell, op: TWalkOp) =
sysAssert(cell != nil, "forAllChildren: 1") sysAssert(cell != nil, "forAllChildren: 1")
@ -536,18 +536,18 @@ proc forAllChildren(cell: PCell, op: TWalkOp) =
if marker != nil: if marker != nil:
marker(cellToUsr(cell), op.int) marker(cellToUsr(cell), op.int)
else: else:
case cell.typ.Kind case cell.typ.kind
of tyRef: # common case of tyRef: # common case
forAllChildrenAux(cellToUsr(cell), cell.typ.base, op) forAllChildrenAux(cellToUsr(cell), cell.typ.base, op)
of tySequence: of tySequence:
var d = cast[TAddress](cellToUsr(cell)) var d = cast[ByteAddress](cellToUsr(cell))
var s = cast[PGenericSeq](d) var s = cast[PGenericSeq](d)
if s != nil: if s != nil:
let baseAddr = d +% GenericSeqSize let baseAddr = d +% GenericSeqSize
for i in 0..s.len-1: for i in 0..s.len-1:
forAllChildrenAux(cast[pointer](baseAddr +% i *% cell.typ.base.size), forAllChildrenAux(cast[pointer](baseAddr +% i *% cell.typ.base.size),
cell.typ.base, op) cell.typ.base, op)
else: nil else: discard
proc addNewObjToZCT(res: PCell, gch: var TGcHeap) {.inline.} = proc addNewObjToZCT(res: PCell, gch: var TGcHeap) {.inline.} =
# we check the last 8 entries (cache line) for a slot that could be reused. # we check the last 8 entries (cache line) for a slot that could be reused.
@ -605,7 +605,7 @@ proc rawNewObj(typ: PNimType, size: int, gch: var TGcHeap, rc1: bool): pointer =
var res = cast[PCell](rawAlloc(gch.region, size + sizeof(TCell))) var res = cast[PCell](rawAlloc(gch.region, size + sizeof(TCell)))
sysAssert(allocInv(gch.region), "rawNewObj after rawAlloc") sysAssert(allocInv(gch.region), "rawNewObj after rawAlloc")
sysAssert((cast[TAddress](res) and (MemAlign-1)) == 0, "newObj: 2") sysAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "newObj: 2")
res.typ = typ res.typ = typ
@ -708,10 +708,10 @@ proc growObj(old: pointer, newsize: int, gch: var TGcHeap): pointer =
# call user-defined move code # call user-defined move code
# call user-defined default constructor # call user-defined default constructor
copyMem(res, ol, oldsize + sizeof(TCell)) copyMem(res, ol, oldsize + sizeof(TCell))
zeroMem(cast[pointer](cast[TAddress](res)+% oldsize +% sizeof(TCell)), zeroMem(cast[pointer](cast[ByteAddress](res)+% oldsize +% sizeof(TCell)),
newsize-oldsize) newsize-oldsize)
sysAssert((cast[TAddress](res) and (MemAlign-1)) == 0, "growObj: 3") sysAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "growObj: 3")
sysAssert(res.refcount shr rcShift <=% 1, "growObj: 4") sysAssert(res.refcount shr rcShift <=% 1, "growObj: 4")
when false: when false:
@ -786,10 +786,10 @@ type
FromChildren, FromChildren,
FromRoot FromRoot
proc CollectZCT(gch: var TGcHeap): bool proc collectZCT(gch: var TGcHeap): bool
template pseudoRecursion(typ: TRecursionType, body: stmt): stmt = template pseudoRecursion(typ: TRecursionType, body: stmt): stmt =
# discard
proc trimCycleRoots(gch: var TGcHeap, startIdx = gch.cycleRootsTrimIdx) = proc trimCycleRoots(gch: var TGcHeap, startIdx = gch.cycleRootsTrimIdx) =
var i = startIdx var i = startIdx
@ -967,17 +967,17 @@ proc collectCycles(gch: var TGcHeap) =
maybedeads, maybedeads,
collected collected
Deinit(gch.cycleRoots) deinit(gch.cycleRoots)
Init(gch.cycleRoots) init(gch.cycleRoots)
Deinit(gch.freeStack) deinit(gch.freeStack)
Init(gch.freeStack) init(gch.freeStack)
when MarkingSkipsAcyclicObjects: when MarkingSkipsAcyclicObjects:
# Collect the acyclic objects that became unreachable due to collected # Collect the acyclic objects that became unreachable due to collected
# cyclic objects. # cyclic objects.
discard CollectZCT(gch) discard collectZCT(gch)
# CollectZCT may add new cycle candidates and we may decide to loop here # collectZCT may add new cycle candidates and we may decide to loop here
# if gch.cycleRoots.len > 0: repeat # if gch.cycleRoots.len > 0: repeat
var gcDebugging* = false var gcDebugging* = false
@ -988,7 +988,7 @@ proc gcMark(gch: var TGcHeap, p: pointer) {.inline.} =
# the addresses are not as cells on the stack, so turn them to cells: # the addresses are not as cells on the stack, so turn them to cells:
sysAssert(allocInv(gch.region), "gcMark begin") sysAssert(allocInv(gch.region), "gcMark begin")
var cell = usrToCell(p) var cell = usrToCell(p)
var c = cast[TAddress](cell) var c = cast[ByteAddress](cell)
if c >% PageSize: if c >% PageSize:
# fast check: does it look like a cell? # fast check: does it look like a cell?
var objStart = cast[PCell](interiorAllocatedPtr(gch.region, cell)) var objStart = cast[PCell](interiorAllocatedPtr(gch.region, cell))
@ -997,6 +997,7 @@ proc gcMark(gch: var TGcHeap, p: pointer) {.inline.} =
if objStart.color != rcReallyDead: if objStart.color != rcReallyDead:
if gcDebugging: if gcDebugging:
# writeCell("marking ", objStart) # writeCell("marking ", objStart)
discard
else: else:
inc objStart.refcount, rcIncrement inc objStart.refcount, rcIncrement
gch.decStack.add objStart gch.decStack.add objStart
@ -1009,6 +1010,7 @@ proc gcMark(gch: var TGcHeap, p: pointer) {.inline.} =
# coincidence due to the conservative stack marking. # coincidence due to the conservative stack marking.
when debugGC: when debugGC:
# writeCell("marking dead object", objStart) # writeCell("marking dead object", objStart)
discard
when false: when false:
if isAllocatedPtr(gch.region, cell): if isAllocatedPtr(gch.region, cell):
sysAssert false, "allocated pointer but not interior?" sysAssert false, "allocated pointer but not interior?"
@ -1024,12 +1026,12 @@ proc markThreadStacks(gch: var TGcHeap) =
while it != nil: while it != nil:
# mark registers: # mark registers:
for i in 0 .. high(it.registers): gcMark(gch, it.registers[i]) for i in 0 .. high(it.registers): gcMark(gch, it.registers[i])
var sp = cast[TAddress](it.stackBottom) var sp = cast[ByteAddress](it.stackBottom)
var max = cast[TAddress](it.stackTop) var max = cast[ByteAddress](it.stackTop)
# XXX stack direction? # XXX stack direction?
# XXX unroll this loop: # XXX unroll this loop:
while sp <=% max: while sp <=% max:
gcMark(gch, cast[ppointer](sp)[]) gcMark(gch, cast[PPointer](sp)[])
sp = sp +% sizeof(pointer) sp = sp +% sizeof(pointer)
it = it.next it = it.next
@ -1051,8 +1053,8 @@ when not defined(useNimRtl):
# the first init must be the one that defines the stack bottom: # the first init must be the one that defines the stack bottom:
if gch.stackBottom == nil: gch.stackBottom = theStackBottom if gch.stackBottom == nil: gch.stackBottom = theStackBottom
else: else:
var a = cast[TAddress](theStackBottom) # and not PageMask - PageSize*2 var a = cast[ByteAddress](theStackBottom) # and not PageMask - PageSize*2
var b = cast[TAddress](gch.stackBottom) var b = cast[ByteAddress](gch.stackBottom)
#c_fprintf(c_stdout, "old: %p new: %p;\n",gch.stackBottom,theStackBottom) #c_fprintf(c_stdout, "old: %p new: %p;\n",gch.stackBottom,theStackBottom)
when stackIncreases: when stackIncreases:
gch.stackBottom = cast[pointer](min(a, b)) gch.stackBottom = cast[pointer](min(a, b))
@ -1067,15 +1069,15 @@ proc stackSize(): int {.noinline.} =
var var
jmpbufSize {.importc: "sizeof(jmp_buf)", nodecl.}: int jmpbufSize {.importc: "sizeof(jmp_buf)", nodecl.}: int
# a little hack to get the size of a TJmpBuf in the generated C code # a little hack to get the size of a TJmpBuf in the generated C code
# in a platform independant way # in a platform independent way
when defined(sparc): # For SPARC architecture. when defined(sparc): # For SPARC architecture.
proc isOnStack(p: pointer): bool = proc isOnStack(p: pointer): bool =
var stackTop {.volatile.}: pointer var stackTop {.volatile.}: pointer
stackTop = addr(stackTop) stackTop = addr(stackTop)
var b = cast[TAddress](gch.stackBottom) var b = cast[ByteAddress](gch.stackBottom)
var a = cast[TAddress](stackTop) var a = cast[ByteAddress](stackTop)
var x = cast[TAddress](p) var x = cast[ByteAddress](p)
result = a <=% x and x <=% b result = a <=% x and x <=% b
proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} = proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} =
@ -1092,7 +1094,7 @@ when defined(sparc): # For SPARC architecture.
# Addresses decrease as the stack grows. # Addresses decrease as the stack grows.
while sp <= max: while sp <= max:
gcMark(gch, sp[]) gcMark(gch, sp[])
sp = cast[ppointer](cast[TAddress](sp) +% sizeof(pointer)) sp = cast[PPointer](cast[ByteAddress](sp) +% sizeof(pointer))
elif defined(ELATE): elif defined(ELATE):
{.error: "stack marking code is to be written for this architecture".} {.error: "stack marking code is to be written for this architecture".}
@ -1104,20 +1106,20 @@ elif stackIncreases:
proc isOnStack(p: pointer): bool = proc isOnStack(p: pointer): bool =
var stackTop {.volatile.}: pointer var stackTop {.volatile.}: pointer
stackTop = addr(stackTop) stackTop = addr(stackTop)
var a = cast[TAddress](gch.stackBottom) var a = cast[ByteAddress](gch.stackBottom)
var b = cast[TAddress](stackTop) var b = cast[ByteAddress](stackTop)
var x = cast[TAddress](p) var x = cast[ByteAddress](p)
result = a <=% x and x <=% b result = a <=% x and x <=% b
proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} = proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} =
var registers: C_JmpBuf var registers: C_JmpBuf
if c_setjmp(registers) == 0'i32: # To fill the C stack with registers. if c_setjmp(registers) == 0'i32: # To fill the C stack with registers.
var max = cast[TAddress](gch.stackBottom) var max = cast[ByteAddress](gch.stackBottom)
var sp = cast[TAddress](addr(registers)) +% jmpbufSize -% sizeof(pointer) var sp = cast[ByteAddress](addr(registers)) +% jmpbufSize -% sizeof(pointer)
# sp will traverse the JMP_BUF as well (jmp_buf size is added, # sp will traverse the JMP_BUF as well (jmp_buf size is added,
# otherwise sp would be below the registers structure). # otherwise sp would be below the registers structure).
while sp >=% max: while sp >=% max:
gcMark(gch, cast[ppointer](sp)[]) gcMark(gch, cast[PPointer](sp)[])
sp = sp -% sizeof(pointer) sp = sp -% sizeof(pointer)
else: else:
@ -1127,9 +1129,9 @@ else:
proc isOnStack(p: pointer): bool = proc isOnStack(p: pointer): bool =
var stackTop {.volatile.}: pointer var stackTop {.volatile.}: pointer
stackTop = addr(stackTop) stackTop = addr(stackTop)
var b = cast[TAddress](gch.stackBottom) var b = cast[ByteAddress](gch.stackBottom)
var a = cast[TAddress](stackTop) var a = cast[ByteAddress](stackTop)
var x = cast[TAddress](p) var x = cast[ByteAddress](p)
result = a <=% x and x <=% b result = a <=% x and x <=% b
proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} = proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} =
@ -1141,18 +1143,18 @@ else:
if c_setjmp(registers) == 0'i32: # To fill the C stack with registers. if c_setjmp(registers) == 0'i32: # To fill the C stack with registers.
when MinimumStackMarking: when MinimumStackMarking:
# mark the registers # mark the registers
var jmpbufPtr = cast[TAddress](addr(registers)) var jmpbufPtr = cast[ByteAddress](addr(registers))
var jmpbufEnd = jmpbufPtr +% jmpbufSize var jmpbufEnd = jmpbufPtr +% jmpbufSize
while jmpbufPtr <=% jmpbufEnd: while jmpbufPtr <=% jmpbufEnd:
gcMark(gch, cast[ppointer](jmpbufPtr)[]) gcMark(gch, cast[PPointer](jmpbufPtr)[])
jmpbufPtr = jmpbufPtr +% sizeof(pointer) jmpbufPtr = jmpbufPtr +% sizeof(pointer)
var sp = cast[TAddress](gch.stackTop) var sp = cast[ByteAddress](gch.stackTop)
else: else:
var sp = cast[TAddress](addr(registers)) var sp = cast[ByteAddress](addr(registers))
# mark the user stack # mark the user stack
var max = cast[TAddress](gch.stackBottom) var max = cast[ByteAddress](gch.stackBottom)
# loop unrolled: # loop unrolled:
while sp <% max - 8*sizeof(pointer): while sp <% max - 8*sizeof(pointer):
gcMark(gch, cast[PStackSlice](sp)[0]) gcMark(gch, cast[PStackSlice](sp)[0])
@ -1166,7 +1168,7 @@ else:
sp = sp +% sizeof(pointer)*8 sp = sp +% sizeof(pointer)*8
# last few entries: # last few entries:
while sp <=% max: while sp <=% max:
gcMark(gch, cast[ppointer](sp)[]) gcMark(gch, cast[PPointer](sp)[])
sp = sp +% sizeof(pointer) sp = sp +% sizeof(pointer)
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
@ -1202,7 +1204,7 @@ proc releaseCell(gch: var TGcHeap, cell: PCell) =
# recursion). # recursion).
# We can ignore it now as the ZCT cleaner will reach it soon. # We can ignore it now as the ZCT cleaner will reach it soon.
proc CollectZCT(gch: var TGcHeap): bool = proc collectZCT(gch: var TGcHeap): bool =
const workPackage = 100 const workPackage = 100
var L = addr(gch.zct.len) var L = addr(gch.zct.len)
@ -1213,8 +1215,8 @@ proc CollectZCT(gch: var TGcHeap): bool =
while L[] > 0: while L[] > 0:
var c = gch.zct.d[0] var c = gch.zct.d[0]
sysAssert c.isBitUp(rcZct), "CollectZCT: rcZct missing!" sysAssert c.isBitUp(rcZct), "collectZCT: rcZct missing!"
sysAssert(isAllocatedPtr(gch.region, c), "CollectZCT: isAllocatedPtr") sysAssert(isAllocatedPtr(gch.region, c), "collectZCT: isAllocatedPtr")
# remove from ZCT: # remove from ZCT:
c.clearBit(rcZct) c.clearBit(rcZct)
@ -1263,7 +1265,7 @@ proc unmarkStackAndRegisters(gch: var TGcHeap) =
# XXX no need for an atomic dec here: # XXX no need for an atomic dec here:
if c.refcount--(LocalHeap): if c.refcount--(LocalHeap):
# the object survived only because of a stack reference # the object survived only because of a stack reference
# it still doesn't have heap refernces # it still doesn't have heap references
addZCT(gch.zct, c) addZCT(gch.zct, c)
if canbeCycleRoot(c): if canbeCycleRoot(c):
@ -1295,7 +1297,7 @@ proc collectCTBody(gch: var TGcHeap) =
sysAssert gch.zct.len == 0, "zct is not null after collect cycles" sysAssert gch.zct.len == 0, "zct is not null after collect cycles"
inc(gch.stat.cycleCollections) inc(gch.stat.cycleCollections)
gch.cycleThreshold = max(InitialCycleThreshold, getOccupiedMem() * gch.cycleThreshold = max(InitialCycleThreshold, getOccupiedMem() *
cycleIncrease) CycleIncrease)
gch.stat.maxThreshold = max(gch.stat.maxThreshold, gch.cycleThreshold) gch.stat.maxThreshold = max(gch.stat.maxThreshold, gch.cycleThreshold)
unmarkStackAndRegisters(gch) unmarkStackAndRegisters(gch)
sysAssert(allocInv(gch.region), "collectCT: end") sysAssert(allocInv(gch.region), "collectCT: end")
@ -1346,10 +1348,10 @@ when not defined(useNimRtl):
proc GC_setStrategy(strategy: GC_Strategy) = proc GC_setStrategy(strategy: GC_Strategy) =
case strategy case strategy
of gcThroughput: nil of gcThroughput: discard
of gcResponsiveness: nil of gcResponsiveness: discard
of gcOptimizeSpace: nil of gcOptimizeSpace: discard
of gcOptimizeTime: nil of gcOptimizeTime: discard
proc GC_enableMarkAndSweep() = proc GC_enableMarkAndSweep() =
gch.cycleThreshold = InitialCycleThreshold gch.cycleThreshold = InitialCycleThreshold

View file

@ -476,7 +476,7 @@ elif stackIncreases:
var var
jmpbufSize {.importc: "sizeof(jmp_buf)", nodecl.}: int jmpbufSize {.importc: "sizeof(jmp_buf)", nodecl.}: int
# a little hack to get the size of a TJmpBuf in the generated C code # a little hack to get the size of a TJmpBuf in the generated C code
# in a platform independant way # in a platform independent way
proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} = proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} =
var registers: C_JmpBuf var registers: C_JmpBuf

Some files were not shown because too many files have changed in this diff Show more