Merge pull request #4 from nim-lang/devel

#4
This commit is contained in:
Michael Voronin 2018-05-10 13:15:33 +03:00 • committed by GitHub
commit 1051e8d69d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
130 changed files with 1427 additions and 3117 deletions

View file

@ -17,6 +17,9 @@
- The ``not nil`` type annotation now has to be enabled explicitly - The ``not nil`` type annotation now has to be enabled explicitly
via ``{.experimental: "notnil"}`` as we are still not pleased with how this via ``{.experimental: "notnil"}`` as we are still not pleased with how this
feature works with Nim's containers. feature works with Nim's containers.
- The parser now warns about inconsistent spacing around binary operators as
these can easily be confused with unary operators. This warning will likely
become an error in the future.
#### Breaking changes in the standard library #### Breaking changes in the standard library
@ -38,6 +41,9 @@
#### Breaking changes in the compiler #### Breaking changes in the compiler
- The undocumented ``#? braces`` parsing mode was removed.
- The undocumented PHP backend was removed.
### Library additions ### Library additions
- ``re.split`` now also supports the ``maxsplit`` parameter for consistency - ``re.split`` now also supports the ``maxsplit`` parameter for consistency
@ -63,6 +69,11 @@
fields. fields.
- ``system.SomeReal`` is now called ``SomeFloat`` for consistency and - ``system.SomeReal`` is now called ``SomeFloat`` for consistency and
correctness. correctness.
- ``algorithm.smartBinarySearch`` and ``algorithm.binarySearch`` is
now joined in ``binarySearch``. ``smartbinarySearch`` is now
deprecated.
- The `terminal` module now exports additional procs for generating ANSI color
codes as strings.
### Language additions ### Language additions
@ -86,11 +97,18 @@
- ``nil`` for strings/seqs is finally gone. Instead the default value for - ``nil`` for strings/seqs is finally gone. Instead the default value for
these is ``"" / @[]``. these is ``"" / @[]``.
- Accessing the binary zero terminator in Nim's native strings - Accessing the binary zero terminator in Nim's native strings
is now invalid. Internally a Nim string still has the trailing zero for is now invalid. Internally a Nim string still has the trailing zero for
zero-copy interoperability with ``cstring``. Compile your code with the zero-copy interoperability with ``cstring``. Compile your code with the
next switch ``--laxStrings:on`` if you need a transition period. new switch ``--laxStrings:on`` if you need a transition period.
- The command syntax now supports keyword arguments after the first comma.
- Thread-local variables can now be declared inside procs. This implies all
the effects of the `global` pragma.
- Nim now supports `except` clause in the export statement.
### Tool changes ### Tool changes

View file

@ -1615,6 +1615,19 @@ proc originatingModule*(s: PSym): PSym =
proc isRoutine*(s: PSym): bool {.inline.} = proc isRoutine*(s: PSym): bool {.inline.} =
result = s.kind in skProcKinds result = s.kind in skProcKinds
proc isCompileTimeProc*(s: PSym): bool {.inline.} =
result = s.kind == skMacro or
s.kind == skProc and sfCompileTime in s.flags
proc requiredParams*(s: PSym): int =
# Returns the number of required params (without default values)
# XXX: Perhaps we can store this in the `offset` field of the
# symbol instead?
for i in 1 ..< s.typ.len:
if s.typ.n[i].sym.ast != nil:
return i - 1
return s.typ.len - 1
proc hasPattern*(s: PSym): bool {.inline.} = proc hasPattern*(s: PSym): bool {.inline.} =
result = isRoutine(s) and s.ast.sons[patternPos].kind != nkEmpty result = isRoutine(s) and s.ast.sons[patternPos].kind != nkEmpty
@ -1671,7 +1684,7 @@ proc isException*(t: PType): bool =
var base = t var base = t
while base != nil: while base != nil:
if base.sym.magic == mException: if base.sym != nil and base.sym.magic == mException:
return true return true
base = base.lastSon base = base.lastSon
return false return false

View file

@ -69,22 +69,22 @@ proc debug*(n: PNode) {.deprecated.}
template mdbg*: bool {.dirty.} = template mdbg*: bool {.dirty.} =
when compiles(c.module): when compiles(c.module):
c.module.fileIdx == gProjectMainIdx c.module.fileIdx.int32 == gProjectMainIdx
elif compiles(c.c.module): elif compiles(c.c.module):
c.c.module.fileIdx == gProjectMainIdx c.c.module.fileIdx.int32 == gProjectMainIdx
elif compiles(m.c.module): elif compiles(m.c.module):
m.c.module.fileIdx == gProjectMainIdx m.c.module.fileIdx.int32 == gProjectMainIdx
elif compiles(cl.c.module): elif compiles(cl.c.module):
cl.c.module.fileIdx == gProjectMainIdx cl.c.module.fileIdx.int32 == gProjectMainIdx
elif compiles(p): elif compiles(p):
when compiles(p.lex): when compiles(p.lex):
p.lex.fileIdx == gProjectMainIdx p.lex.fileIdx.int32 == gProjectMainIdx
else: else:
p.module.module.fileIdx == gProjectMainIdx p.module.module.fileIdx.int32 == gProjectMainIdx
elif compiles(m.module.fileIdx): elif compiles(m.module.fileIdx):
m.module.fileIdx == gProjectMainIdx m.module.fileIdx.int32 == gProjectMainIdx
elif compiles(L.fileIdx): elif compiles(L.fileIdx):
L.fileIdx == gProjectMainIdx L.fileIdx.int32 == gProjectMainIdx
else: else:
error() error()

View file

@ -265,7 +265,7 @@ proc rdCharLoc(a: TLoc): Rope =
proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc, proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc,
takeAddr: bool) = takeAddr: bool) =
if p.module.compileToCpp and t.isException: if p.module.compileToCpp and t.isException and not isDefined("noCppExceptions"):
# init vtable in Exception object for polymorphic exceptions # init vtable in Exception object for polymorphic exceptions
includeHeader(p.module, "<new>") includeHeader(p.module, "<new>")
linefmt(p, section, "new ($1) $2;$n", rdLoc(a), getTypeDesc(p.module, t)) linefmt(p, section, "new ($1) $2;$n", rdLoc(a), getTypeDesc(p.module, t))
@ -746,7 +746,7 @@ proc genProcAux(m: BModule, prc: PSym) =
else: else:
fillResult(resNode) fillResult(resNode)
assignParam(p, res) assignParam(p, res)
resetLoc(p, res.loc) if sfNoInit notin prc.flags: resetLoc(p, res.loc)
if skipTypes(res.typ, abstractInst).kind == tyArray: if skipTypes(res.typ, abstractInst).kind == tyArray:
#incl(res.loc.flags, lfIndirect) #incl(res.loc.flags, lfIndirect)
res.loc.storage = OnUnknown res.loc.storage = OnUnknown

View file

@ -430,6 +430,7 @@ proc injectDestructorCalls*(owner: PSym; n: PNode): PNode =
c.tmp.typ = c.tmpObj c.tmp.typ = c.tmpObj
c.destroys = newNodeI(nkStmtList, n.info) c.destroys = newNodeI(nkStmtList, n.info)
c.topLevelVars = newNodeI(nkVarSection, n.info) c.topLevelVars = newNodeI(nkVarSection, n.info)
c.toDropBit = initTable[int, PSym]()
let cfg = constructCfg(owner, n) let cfg = constructCfg(owner, n)
shallowCopy(c.g, cfg) shallowCopy(c.g, cfg)
c.jumpTargets = initIntSet() c.jumpTargets = initIntSet()

View file

@ -790,7 +790,7 @@ proc writeOutputJson*(d: PDoc, filename, outExt: string,
discard "fixme: error report" discard "fixme: error report"
proc commandDoc*() = proc commandDoc*() =
var ast = parseFile(gProjectMainIdx.FileIndex, newIdentCache()) var ast = parseFile(gProjectMainIdx.FileIndex, newIdentCache(), newConfigRef())
if ast == nil: return if ast == nil: return
var d = newDocumentor(gProjectFull, options.gConfigVars) var d = newDocumentor(gProjectFull, options.gConfigVars)
d.hasToc = true d.hasToc = true
@ -840,7 +840,7 @@ proc commandRst2TeX*() =
commandRstAux(gProjectFull, TexExt) commandRstAux(gProjectFull, TexExt)
proc commandJson*() = proc commandJson*() =
var ast = parseFile(gProjectMainIdx.FileIndex, newIdentCache()) var ast = parseFile(gProjectMainIdx.FileIndex, newIdentCache(), newConfigRef())
if ast == nil: return if ast == nil: return
var d = newDocumentor(gProjectFull, options.gConfigVars) var d = newDocumentor(gProjectFull, options.gConfigVars)
d.hasToc = true d.hasToc = true
@ -855,7 +855,7 @@ proc commandJson*() =
writeRope(content, getOutFile(gProjectFull, JsonExt), useWarning = false) writeRope(content, getOutFile(gProjectFull, JsonExt), useWarning = false)
proc commandTags*() = proc commandTags*() =
var ast = parseFile(gProjectMainIdx.FileIndex, newIdentCache()) var ast = parseFile(gProjectMainIdx.FileIndex, newIdentCache(), newConfigRef())
if ast == nil: return if ast == nil: return
var d = newDocumentor(gProjectFull, options.gConfigVars) var d = newDocumentor(gProjectFull, options.gConfigVars)
d.hasToc = true d.hasToc = true

View file

@ -63,7 +63,7 @@ proc evalTemplateArgs(n: PNode, s: PSym; fromHlo: bool): PNode =
# if the template has zero arguments, it can be called without ``()`` # if the template has zero arguments, it can be called without ``()``
# `n` is then a nkSym or something similar # `n` is then a nkSym or something similar
var totalParams = case n.kind var totalParams = case n.kind
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit: n.len-1 of nkCallKinds: n.len-1
else: 0 else: 0
var var

View file

@ -45,7 +45,6 @@ proc scanPar(p: var TTmplParser, d: int) =
let hi = p.x.len - 1 let hi = p.x.len - 1
while i <= hi: while i <= hi:
case p.x[i] case p.x[i]
of '\0': break
of '(': inc(p.par) of '(': inc(p.par)
of ')': dec(p.par) of ')': dec(p.par)
of '[': inc(p.bracket) of '[': inc(p.bracket)
@ -64,16 +63,22 @@ const
proc parseLine(p: var TTmplParser) = proc parseLine(p: var TTmplParser) =
var j = 0 var j = 0
while p.x[j] == ' ': inc(j) let hi = p.x.len - 1
if hi == 0:
return
while j <= hi and p.x[j] == ' ': inc(j)
if p.x[0] == p.nimDirective and p.x[1] == '?': if p.x[0] == p.nimDirective and p.x[1] == '?':
newLine(p) newLine(p)
elif p.x[j] == p.nimDirective: elif p.x[j] == p.nimDirective:
newLine(p) newLine(p)
inc(j) inc(j)
while p.x[j] == ' ': inc(j) while j <= hi and p.x[j] == ' ': inc(j)
let d = j let d = j
var keyw = "" var keyw = ""
while p.x[j] in PatternChars: while j <= hi and p.x[j] in PatternChars:
add(keyw, p.x[j]) add(keyw, p.x[j])
inc(j) inc(j)
@ -127,10 +132,8 @@ proc parseLine(p: var TTmplParser) =
llStreamWrite(p.outp, "(\"") llStreamWrite(p.outp, "(\"")
inc(p.emitPar) inc(p.emitPar)
p.state = psTempl p.state = psTempl
while true: while j <= hi:
case p.x[j] case p.x[j]
of '\0':
break
of '\x01'..'\x1F', '\x80'..'\xFF': of '\x01'..'\x1F', '\x80'..'\xFF':
llStreamWrite(p.outp, "\\x") llStreamWrite(p.outp, "\\x")
llStreamWrite(p.outp, toHex(ord(p.x[j]), 2)) llStreamWrite(p.outp, toHex(ord(p.x[j]), 2))
@ -157,11 +160,8 @@ proc parseLine(p: var TTmplParser) =
llStreamWrite(p.outp, '(') llStreamWrite(p.outp, '(')
inc(j) inc(j)
var curly = 0 var curly = 0
while true: while j <= hi:
case p.x[j] case p.x[j]
of '\0':
localError(p.info, errXExpected, "}")
break
of '{': of '{':
inc(j) inc(j)
inc(curly) inc(curly)
@ -174,6 +174,9 @@ proc parseLine(p: var TTmplParser) =
else: else:
llStreamWrite(p.outp, p.x[j]) llStreamWrite(p.outp, p.x[j])
inc(j) inc(j)
if curly > 0:
localError(p.info, errXExpected, "}")
break
llStreamWrite(p.outp, ')') llStreamWrite(p.outp, ')')
llStreamWrite(p.outp, p.conc) llStreamWrite(p.outp, p.conc)
llStreamWrite(p.outp, '\"') llStreamWrite(p.outp, '\"')
@ -182,7 +185,7 @@ proc parseLine(p: var TTmplParser) =
llStreamWrite(p.outp, p.conc) llStreamWrite(p.outp, p.conc)
llStreamWrite(p.outp, p.toStr) llStreamWrite(p.outp, p.toStr)
llStreamWrite(p.outp, '(') llStreamWrite(p.outp, '(')
while p.x[j] in PatternChars: while j <= hi and p.x[j] in PatternChars:
llStreamWrite(p.outp, p.x[j]) llStreamWrite(p.outp, p.x[j])
inc(j) inc(j)
llStreamWrite(p.outp, ')') llStreamWrite(p.outp, ')')

View file

@ -16,6 +16,13 @@ import
proc evalImport*(c: PContext, n: PNode): PNode proc evalImport*(c: PContext, n: PNode): PNode
proc evalFrom*(c: PContext, n: PNode): PNode proc evalFrom*(c: PContext, n: PNode): PNode
proc readExceptSet*(n: PNode): IntSet =
assert n.kind in {nkImportExceptStmt, nkExportExceptStmt}
result = initIntSet()
for i in 1 ..< n.len:
let ident = lookups.considerQuotedIdent(n[i])
result.incl(ident.id)
proc importPureEnumField*(c: PContext; s: PSym) = proc importPureEnumField*(c: PContext; s: PSym) =
var check = strTableGet(c.importTable.symbols, s.name) var check = strTableGet(c.importTable.symbols, s.name)
if check == nil: if check == nil:
@ -198,9 +205,5 @@ proc evalImportExcept*(c: PContext, n: PNode): PNode =
if m != nil: if m != nil:
n.sons[0] = newSymNode(m) n.sons[0] = newSymNode(m)
addDecl(c, m, n.info) # add symbol to symbol table of module addDecl(c, m, n.info) # add symbol to symbol table of module
var exceptSet = initIntSet() importAllSymbolsExcept(c, m, readExceptSet(n))
for i in countup(1, sonsLen(n) - 1):
let ident = lookups.considerQuotedIdent(n.sons[i])
exceptSet.incl(ident.id)
importAllSymbolsExcept(c, m, exceptSet)
#importForwarded(c, m.ast, exceptSet) #importForwarded(c, m.ast, exceptSet)

View file

@ -144,13 +144,12 @@ type
cache*: IdentCache cache*: IdentCache
when defined(nimsuggest): when defined(nimsuggest):
previousToken: TLineInfo previousToken: TLineInfo
config*: ConfigRef
when defined(nimpretty): when defined(nimpretty):
var var
gIndentationWidth*: int gIndentationWidth*: int
var gLinesCompiled*: int # all lines that have been compiled
proc getLineInfo*(L: TLexer, tok: TToken): TLineInfo {.inline.} = proc getLineInfo*(L: TLexer, tok: TToken): TLineInfo {.inline.} =
result = newLineInfo(L.fileIdx, tok.line, tok.col) result = newLineInfo(L.fileIdx, tok.line, tok.col)
when defined(nimpretty): when defined(nimpretty):
@ -222,7 +221,7 @@ proc fillToken(L: var TToken) =
L.commentOffsetB = 0 L.commentOffsetB = 0
proc openLexer*(lex: var TLexer, fileIdx: FileIndex, inputstream: PLLStream; proc openLexer*(lex: var TLexer, fileIdx: FileIndex, inputstream: PLLStream;
cache: IdentCache) = cache: IdentCache; config: ConfigRef) =
openBaseLexer(lex, inputstream) openBaseLexer(lex, inputstream)
lex.fileIdx = fileidx lex.fileIdx = fileidx
lex.indentAhead = - 1 lex.indentAhead = - 1
@ -231,13 +230,15 @@ proc openLexer*(lex: var TLexer, fileIdx: FileIndex, inputstream: PLLStream;
lex.cache = cache lex.cache = cache
when defined(nimsuggest): when defined(nimsuggest):
lex.previousToken.fileIndex = fileIdx lex.previousToken.fileIndex = fileIdx
lex.config = config
proc openLexer*(lex: var TLexer, filename: string, inputstream: PLLStream; proc openLexer*(lex: var TLexer, filename: string, inputstream: PLLStream;
cache: IdentCache) = cache: IdentCache; config: ConfigRef) =
openLexer(lex, filename.fileInfoIdx, inputstream, cache) openLexer(lex, filename.fileInfoIdx, inputstream, cache, config)
proc closeLexer*(lex: var TLexer) = proc closeLexer*(lex: var TLexer) =
inc(gLinesCompiled, lex.lineNumber) if lex.config != nil:
inc(lex.config.linesCompiled, lex.lineNumber)
closeBaseLexer(lex) closeBaseLexer(lex)
proc getLineInfo(L: TLexer): TLineInfo = proc getLineInfo(L: TLexer): TLineInfo =
@ -576,7 +577,8 @@ proc getNumber(L: var TLexer, result: var TToken) =
result.iNumber = parseBiggestInt(result.literal) result.iNumber = parseBiggestInt(result.literal)
# Explicit bounds checks # Explicit bounds checks
let outOfRange = case result.tokType: let outOfRange =
case result.tokType
of tkInt8Lit: (result.iNumber < int8.low or result.iNumber > int8.high) of tkInt8Lit: (result.iNumber < int8.low or result.iNumber > int8.high)
of tkUInt8Lit: (result.iNumber < BiggestInt(uint8.low) or of tkUInt8Lit: (result.iNumber < BiggestInt(uint8.low) or
result.iNumber > BiggestInt(uint8.high)) result.iNumber > BiggestInt(uint8.high))

View file

@ -129,9 +129,10 @@ proc commandEval(graph: ModuleGraph; cache: IdentCache; exp: string) =
interactivePasses(graph, cache) interactivePasses(graph, cache)
compileSystemModule(graph, cache) compileSystemModule(graph, cache)
let echoExp = "echo \"eval\\t\", " & "repr(" & exp & ")" let echoExp = "echo \"eval\\t\", " & "repr(" & exp & ")"
evalNim(graph, echoExp.parseString(cache), makeStdinModule(graph), cache) evalNim(graph, echoExp.parseString(cache, graph.config),
makeStdinModule(graph), cache)
proc commandScan(cache: IdentCache) = proc commandScan(cache: IdentCache, config: ConfigRef) =
var f = addFileExt(mainCommandArg(), NimExt) var f = addFileExt(mainCommandArg(), NimExt)
var stream = llStreamOpen(f, fmRead) var stream = llStreamOpen(f, fmRead)
if stream != nil: if stream != nil:
@ -139,7 +140,7 @@ proc commandScan(cache: IdentCache) =
L: TLexer L: TLexer
tok: TToken tok: TToken
initToken(tok) initToken(tok)
openLexer(L, f, stream, cache) openLexer(L, f, stream, cache, config)
while true: while true:
rawGetTok(L, tok) rawGetTok(L, tok)
printTok(tok) printTok(tok)
@ -265,11 +266,11 @@ proc mainCommand*(graph: ModuleGraph; cache: IdentCache) =
of "parse": of "parse":
gCmd = cmdParse gCmd = cmdParse
wantMainModule() wantMainModule()
discard parseFile(FileIndex gProjectMainIdx, cache) discard parseFile(FileIndex gProjectMainIdx, cache, graph.config)
of "scan": of "scan":
gCmd = cmdScan gCmd = cmdScan
wantMainModule() wantMainModule()
commandScan(cache) commandScan(cache, graph.config)
msgWriteln("Beware: Indentation tokens depend on the parser's state!") msgWriteln("Beware: Indentation tokens depend on the parser's state!")
of "secret": of "secret":
gCmd = cmdInteractive gCmd = cmdInteractive
@ -291,7 +292,7 @@ proc mainCommand*(graph: ModuleGraph; cache: IdentCache) =
let usedMem = formatSize(getMaxMem()) & " peakmem" let usedMem = formatSize(getMaxMem()) & " peakmem"
else: else:
let usedMem = formatSize(getTotalMem()) let usedMem = formatSize(getTotalMem())
rawMessage(hintSuccessX, [$gLinesCompiled, rawMessage(hintSuccessX, [$graph.config.linesCompiled,
formatFloat(epochTime() - gLastCmdTime, ffDecimal, 3), formatFloat(epochTime() - gLastCmdTime, ffDecimal, 3),
usedMem, usedMem,
if condSyms.isDefined("release"): "Release Build" if condSyms.isDefined("release"): "Release Build"

View file

@ -107,7 +107,7 @@ proc importModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex;
proc includeModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex; proc includeModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex;
cache: IdentCache): PNode {.procvar.} = cache: IdentCache): PNode {.procvar.} =
result = syntaxes.parseFile(fileIdx, cache) result = syntaxes.parseFile(fileIdx, cache, graph.config)
graph.addDep(s, fileIdx) graph.addDep(s, fileIdx)
graph.addIncludeDep(s.position.FileIndex, fileIdx) graph.addIncludeDep(s.position.FileIndex, fileIdx)

View file

@ -131,7 +131,7 @@ type
warnEachIdentIsTuple, warnShadowIdent, warnEachIdentIsTuple, warnShadowIdent,
warnProveInit, warnProveField, warnProveIndex, warnGcUnsafe, warnGcUnsafe2, warnProveInit, warnProveField, warnProveIndex, warnGcUnsafe, warnGcUnsafe2,
warnUninit, warnGcMem, warnDestructor, warnLockLevel, warnResultShadowed, warnUninit, warnGcMem, warnDestructor, warnLockLevel, warnResultShadowed,
warnUser, warnInconsistentSpacing, warnUser,
hintSuccess, hintSuccessX, hintSuccess, hintSuccessX,
hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded, hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded,
hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled, hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled,
@ -146,7 +146,7 @@ const
errUnknown: "unknown error", errUnknown: "unknown error",
errInternal: "internal error: $1", errInternal: "internal error: $1",
errIllFormedAstX: "illformed AST: $1", errIllFormedAstX: "illformed AST: $1",
errCannotOpenFile: "cannot open \'$1\'", errCannotOpenFile: "cannot open '$1'",
errGenerated: "$1", errGenerated: "$1",
errStringLiteralExpected: "string literal expected", errStringLiteralExpected: "string literal expected",
errIntLiteralExpected: "integer literal expected", errIntLiteralExpected: "integer literal expected",
@ -160,39 +160,39 @@ const
errNumberOutOfRange: "number $1 out of valid range", errNumberOutOfRange: "number $1 out of valid range",
errNnotAllowedInCharacter: "\\n not allowed in character literal", errNnotAllowedInCharacter: "\\n not allowed in character literal",
errClosingBracketExpected: "closing ']' expected, but end of file reached", errClosingBracketExpected: "closing ']' expected, but end of file reached",
errMissingFinalQuote: "missing final \' for character literal", errMissingFinalQuote: "missing final ' for character literal",
errIdentifierExpected: "identifier expected, but found \'$1\'", errIdentifierExpected: "identifier expected, but found '$1'",
errNewlineExpected: "newline expected, but found \'$1\'", errNewlineExpected: "newline expected, but found '$1'",
errInvalidModuleName: "invalid module name: '$1'", errInvalidModuleName: "invalid module name: '$1'",
errOperatorExpected: "operator expected, but found \'$1\'", errOperatorExpected: "operator expected, but found '$1'",
errTokenExpected: "\'$1\' expected", errTokenExpected: "'$1' expected",
errRecursiveDependencyX: "recursive dependency: \'$1\'", errRecursiveDependencyX: "recursive dependency: '$1'",
errOnOrOffExpected: "\'on\' or \'off\' expected", errOnOrOffExpected: "'on' or 'off' expected",
errNoneSpeedOrSizeExpected: "\'none\', \'speed\' or \'size\' expected", errNoneSpeedOrSizeExpected: "'none', 'speed' or 'size' expected",
errInvalidPragma: "invalid pragma", errInvalidPragma: "invalid pragma",
errUnknownPragma: "unknown pragma: \'$1\'", errUnknownPragma: "unknown pragma: '$1'",
errInvalidDirectiveX: "invalid directive: \'$1\'", errInvalidDirectiveX: "invalid directive: '$1'",
errAtPopWithoutPush: "\'pop\' without a \'push\' pragma", errAtPopWithoutPush: "'pop' without a 'push' pragma",
errEmptyAsm: "empty asm statement", errEmptyAsm: "empty asm statement",
errInvalidIndentation: "invalid indentation", errInvalidIndentation: "invalid indentation",
errExceptionAlreadyHandled: "exception already handled", errExceptionAlreadyHandled: "exception already handled",
errYieldNotAllowedHere: "'yield' only allowed in an iterator", errYieldNotAllowedHere: "'yield' only allowed in an iterator",
errYieldNotAllowedInTryStmt: "'yield' cannot be used within 'try' in a non-inlined iterator", errYieldNotAllowedInTryStmt: "'yield' cannot be used within 'try' in a non-inlined iterator",
errInvalidNumberOfYieldExpr: "invalid number of \'yield\' expressions", errInvalidNumberOfYieldExpr: "invalid number of 'yield' expressions",
errCannotReturnExpr: "current routine cannot return an expression", errCannotReturnExpr: "current routine cannot return an expression",
errNoReturnWithReturnTypeNotAllowed: "routines with NoReturn pragma are not allowed to have return type", errNoReturnWithReturnTypeNotAllowed: "routines with NoReturn pragma are not allowed to have return type",
errAttemptToRedefine: "redefinition of \'$1\'", errAttemptToRedefine: "redefinition of '$1'",
errStmtInvalidAfterReturn: "statement not allowed after \'return\', \'break\', \'raise\', \'continue\' or proc call with noreturn pragma", errStmtInvalidAfterReturn: "statement not allowed after 'return', 'break', 'raise', 'continue' or proc call with noreturn pragma",
errStmtExpected: "statement expected", errStmtExpected: "statement expected",
errInvalidLabel: "\'$1\' is no label", errInvalidLabel: "'$1' is no label",
errInvalidCmdLineOption: "invalid command line option: \'$1\'", errInvalidCmdLineOption: "invalid command line option: '$1'",
errCmdLineArgExpected: "argument for command line option expected: \'$1\'", errCmdLineArgExpected: "argument for command line option expected: '$1'",
errCmdLineNoArgExpected: "invalid argument for command line option: \'$1\'", errCmdLineNoArgExpected: "invalid argument for command line option: '$1'",
errInvalidVarSubstitution: "invalid variable substitution in \'$1\'", errInvalidVarSubstitution: "invalid variable substitution in '$1'",
errUnknownVar: "unknown variable: \'$1\'", errUnknownVar: "unknown variable: '$1'",
errUnknownCcompiler: "unknown C compiler: \'$1\'", errUnknownCcompiler: "unknown C compiler: '$1'",
errOnOrOffExpectedButXFound: "\'on\' or \'off\' expected, but \'$1\' found", errOnOrOffExpectedButXFound: "'on' or 'off' expected, but '$1' found",
errOnOffOrListExpectedButXFound: "\'on\', \'off\' or \'list\' expected, but \'$1\' found", errOnOffOrListExpectedButXFound: "'on', 'off' or 'list' expected, but '$1' found",
errNoneBoehmRefcExpectedButXFound: "'none', 'boehm' or 'refc' expected, but '$1' found", errNoneBoehmRefcExpectedButXFound: "'none', 'boehm' or 'refc' expected, but '$1' found",
errNoneSpeedOrSizeExpectedButXFound: "'none', 'speed' or 'size' expected, but '$1' found", errNoneSpeedOrSizeExpectedButXFound: "'none', 'speed' or 'size' expected, but '$1' found",
errGuiConsoleOrLibExpectedButXFound: "'gui', 'console' or 'lib' expected, but '$1' found", errGuiConsoleOrLibExpectedButXFound: "'gui', 'console' or 'lib' expected, but '$1' found",
@ -201,19 +201,19 @@ const
errGenOutExpectedButXFound: "'c', 'c++' or 'yaml' expected, but '$1' found", errGenOutExpectedButXFound: "'c', 'c++' or 'yaml' expected, but '$1' found",
errArgsNeedRunOption: "arguments can only be given if the '--run' option is selected", errArgsNeedRunOption: "arguments can only be given if the '--run' option is selected",
errInvalidMultipleAsgn: "multiple assignment is not allowed", errInvalidMultipleAsgn: "multiple assignment is not allowed",
errColonOrEqualsExpected: "\':\' or \'=\' expected, but found \'$1\'", errColonOrEqualsExpected: "':' or '=' expected, but found '$1'",
errExprExpected: "expression expected, but found \'$1\'", errExprExpected: "expression expected, but found '$1'",
errUndeclaredField: "undeclared field: \'$1\'", errUndeclaredField: "undeclared field: '$1'",
errUndeclaredRoutine: "attempting to call undeclared routine: \'$1\'", errUndeclaredRoutine: "attempting to call undeclared routine: '$1'",
errUseQualifier: "ambiguous identifier: \'$1\' -- use a qualifier", errUseQualifier: "ambiguous identifier: '$1' -- use a qualifier",
errTypeExpected: "type expected", errTypeExpected: "type expected",
errSystemNeeds: "system module needs \'$1\'", errSystemNeeds: "system module needs '$1'",
errExecutionOfProgramFailed: "execution of an external program failed: '$1'", errExecutionOfProgramFailed: "execution of an external program failed: '$1'",
errNotOverloadable: "overloaded \'$1\' leads to ambiguous calls", errNotOverloadable: "overloaded '$1' leads to ambiguous calls",
errInvalidArgForX: "invalid argument for \'$1\'", errInvalidArgForX: "invalid argument for '$1'",
errStmtHasNoEffect: "statement has no effect", errStmtHasNoEffect: "statement has no effect",
errXExpectsTypeOrValue: "\'$1\' expects a type or value", errXExpectsTypeOrValue: "'$1' expects a type or value",
errXExpectsArrayType: "\'$1\' expects an array type", errXExpectsArrayType: "'$1' expects an array type",
errIteratorCannotBeInstantiated: "'$1' cannot be instantiated because its body has not been compiled yet", errIteratorCannotBeInstantiated: "'$1' cannot be instantiated because its body has not been compiled yet",
errExprXAmbiguous: "expression '$1' ambiguous in this context", errExprXAmbiguous: "expression '$1' ambiguous in this context",
errConstantDivisionByZero: "division by zero", errConstantDivisionByZero: "division by zero",
@ -221,26 +221,26 @@ const
errOrdinalOrFloatTypeExpected: "ordinal or float type expected", errOrdinalOrFloatTypeExpected: "ordinal or float type expected",
errOverOrUnderflow: "over- or underflow", errOverOrUnderflow: "over- or underflow",
errCannotEvalXBecauseIncompletelyDefined: "cannot evaluate '$1' because type is not defined completely", errCannotEvalXBecauseIncompletelyDefined: "cannot evaluate '$1' because type is not defined completely",
errChrExpectsRange0_255: "\'chr\' expects an int in the range 0..255", errChrExpectsRange0_255: "'chr' expects an int in the range 0..255",
errDynlibRequiresExportc: "\'dynlib\' requires \'exportc\'", errDynlibRequiresExportc: "'dynlib' requires 'exportc'",
errUndeclaredFieldX: "undeclared field: \'$1\'", errUndeclaredFieldX: "undeclared field: '$1'",
errNilAccess: "attempt to access a nil address", errNilAccess: "attempt to access a nil address",
errIndexOutOfBounds: "index out of bounds", errIndexOutOfBounds: "index out of bounds",
errIndexTypesDoNotMatch: "index types do not match", errIndexTypesDoNotMatch: "index types do not match",
errBracketsInvalidForType: "\'[]\' operator invalid for this type", errBracketsInvalidForType: "'[]' operator invalid for this type",
errValueOutOfSetBounds: "value out of set bounds", errValueOutOfSetBounds: "value out of set bounds",
errFieldInitTwice: "field initialized twice: \'$1\'", errFieldInitTwice: "field initialized twice: '$1'",
errFieldNotInit: "field \'$1\' not initialized", errFieldNotInit: "field '$1' not initialized",
errExprXCannotBeCalled: "expression \'$1\' cannot be called", errExprXCannotBeCalled: "expression '$1' cannot be called",
errExprHasNoType: "expression has no type", errExprHasNoType: "expression has no type",
errExprXHasNoType: "expression \'$1\' has no type (or is ambiguous)", errExprXHasNoType: "expression '$1' has no type (or is ambiguous)",
errCastNotInSafeMode: "\'cast\' not allowed in safe mode", errCastNotInSafeMode: "'cast' not allowed in safe mode",
errExprCannotBeCastToX: "expression cannot be cast to $1", errExprCannotBeCastToX: "expression cannot be cast to $1",
errCommaOrParRiExpected: "',' or ')' expected", errCommaOrParRiExpected: "',' or ')' expected",
errCurlyLeOrParLeExpected: "\'{\' or \'(\' expected", errCurlyLeOrParLeExpected: "'{' or '(' expected",
errSectionExpected: "section (\'type\', \'proc\', etc.) expected", errSectionExpected: "section ('type', 'proc', etc.) expected",
errRangeExpected: "range expected", errRangeExpected: "range expected",
errMagicOnlyInSystem: "\'magic\' only allowed in system module", errMagicOnlyInSystem: "'magic' only allowed in system module",
errPowerOfTwoExpected: "power of two expected", errPowerOfTwoExpected: "power of two expected",
errStringMayNotBeEmpty: "string literal may not be empty", errStringMayNotBeEmpty: "string literal may not be empty",
errCallConvExpected: "calling convention expected", errCallConvExpected: "calling convention expected",
@ -257,51 +257,51 @@ const
errWrongNumberOfVariables: "wrong number of variables", errWrongNumberOfVariables: "wrong number of variables",
errExprCannotBeRaised: "only a 'ref object' can be raised", errExprCannotBeRaised: "only a 'ref object' can be raised",
errBreakOnlyInLoop: "'break' only allowed in loop construct", errBreakOnlyInLoop: "'break' only allowed in loop construct",
errTypeXhasUnknownSize: "type \'$1\' has unknown size", errTypeXhasUnknownSize: "type '$1' has unknown size",
errConstNeedsConstExpr: "a constant can only be initialized with a constant expression", errConstNeedsConstExpr: "a constant can only be initialized with a constant expression",
errConstNeedsValue: "a constant needs a value", errConstNeedsValue: "a constant needs a value",
errResultCannotBeOpenArray: "the result type cannot be on open array", errResultCannotBeOpenArray: "the result type cannot be on open array",
errSizeTooBig: "computing the type\'s size produced an overflow", errSizeTooBig: "computing the type's size produced an overflow",
errSetTooBig: "set is too large", errSetTooBig: "set is too large",
errBaseTypeMustBeOrdinal: "base type of a set must be an ordinal", errBaseTypeMustBeOrdinal: "base type of a set must be an ordinal",
errInheritanceOnlyWithNonFinalObjects: "inheritance only works with non-final objects", errInheritanceOnlyWithNonFinalObjects: "inheritance only works with non-final objects",
errInheritanceOnlyWithEnums: "inheritance only works with an enum", errInheritanceOnlyWithEnums: "inheritance only works with an enum",
errIllegalRecursionInTypeX: "illegal recursion in type \'$1\'", errIllegalRecursionInTypeX: "illegal recursion in type '$1'",
errCannotInstantiateX: "cannot instantiate: \'$1\'", errCannotInstantiateX: "cannot instantiate: '$1'",
errExprHasNoAddress: "expression has no address", errExprHasNoAddress: "expression has no address",
errXStackEscape: "address of '$1' may not escape its stack frame", errXStackEscape: "address of '$1' may not escape its stack frame",
errVarForOutParamNeededX: "for a \'var\' type a variable needs to be passed; but '$1' is immutable", errVarForOutParamNeededX: "for a 'var' type a variable needs to be passed; but '$1' is immutable",
errPureTypeMismatch: "type mismatch", errPureTypeMismatch: "type mismatch",
errTypeMismatch: "type mismatch: got <", errTypeMismatch: "type mismatch: got <",
errButExpected: "but expected one of: ", errButExpected: "but expected one of: ",
errButExpectedX: "but expected \'$1\'", errButExpectedX: "but expected '$1'",
errAmbiguousCallXYZ: "ambiguous call; both $1 and $2 match for: $3", errAmbiguousCallXYZ: "ambiguous call; both $1 and $2 match for: $3",
errWrongNumberOfArguments: "wrong number of arguments", errWrongNumberOfArguments: "wrong number of arguments",
errWrongNumberOfArgumentsInCall: "wrong number of arguments in call to '$1'", errWrongNumberOfArgumentsInCall: "wrong number of arguments in call to '$1'",
errMissingGenericParamsForTemplate: "'$1' has unspecified generic parameters", errMissingGenericParamsForTemplate: "'$1' has unspecified generic parameters",
errXCannotBePassedToProcVar: "\'$1\' cannot be passed to a procvar", errXCannotBePassedToProcVar: "'$1' cannot be passed to a procvar",
errPragmaOnlyInHeaderOfProcX: "pragmas are only allowed in the header of a proc; redefinition of $1", errPragmaOnlyInHeaderOfProcX: "pragmas are only allowed in the header of a proc; redefinition of $1",
errImplOfXNotAllowed: "implementation of \'$1\' is not allowed", errImplOfXNotAllowed: "implementation of '$1' is not allowed",
errImplOfXexpected: "implementation of \'$1\' expected", errImplOfXexpected: "implementation of '$1' expected",
errNoSymbolToBorrowFromFound: "no symbol to borrow from found", errNoSymbolToBorrowFromFound: "no symbol to borrow from found",
errDiscardValueX: "value of type '$1' has to be discarded", errDiscardValueX: "value of type '$1' has to be discarded",
errInvalidDiscard: "statement returns no value that can be discarded", errInvalidDiscard: "statement returns no value that can be discarded",
errIllegalConvFromXtoY: "conversion from $1 to $2 is invalid", errIllegalConvFromXtoY: "conversion from $1 to $2 is invalid",
errCannotBindXTwice: "cannot bind parameter \'$1\' twice", errCannotBindXTwice: "cannot bind parameter '$1' twice",
errInvalidOrderInArrayConstructor: "invalid order in array constructor", errInvalidOrderInArrayConstructor: "invalid order in array constructor",
errInvalidOrderInEnumX: "invalid order in enum \'$1\'", errInvalidOrderInEnumX: "invalid order in enum '$1'",
errEnumXHasHoles: "enum \'$1\' has holes", errEnumXHasHoles: "enum '$1' has holes",
errExceptExpected: "\'except\' or \'finally\' expected", errExceptExpected: "'except' or 'finally' expected",
errInvalidTry: "after catch all \'except\' or \'finally\' no section may follow", errInvalidTry: "after catch all 'except' or 'finally' no section may follow",
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",
errUnknownSubstitionVar: "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",
errNoGenericParamsAllowedForX: "no generic parameters allowed for $1", errNoGenericParamsAllowedForX: "no generic parameters allowed for $1",
errInvalidParamKindX: "invalid param kind: \'$1\'", errInvalidParamKindX: "invalid param kind: '$1'",
errDefaultArgumentInvalid: "default argument invalid", errDefaultArgumentInvalid: "default argument invalid",
errNamedParamHasToBeIdent: "named parameter has to be an identifier", errNamedParamHasToBeIdent: "named parameter has to be an identifier",
errNoReturnTypeForX: "no return type allowed for $1", errNoReturnTypeForX: "no return type allowed for $1",
@ -309,24 +309,24 @@ const
errInvalidPragmaX: "invalid pragma: $1", errInvalidPragmaX: "invalid pragma: $1",
errXNotAllowedHere: "$1 not allowed here", errXNotAllowedHere: "$1 not allowed here",
errInvalidControlFlowX: "invalid control flow: $1", errInvalidControlFlowX: "invalid control flow: $1",
errXisNoType: "invalid type: \'$1\'", errXisNoType: "invalid type: '$1'",
errCircumNeedsPointer: "'[]' needs a pointer or reference type", errCircumNeedsPointer: "'[]' needs a pointer or reference type",
errInvalidExpression: "invalid expression", errInvalidExpression: "invalid expression",
errInvalidExpressionX: "invalid expression: \'$1\'", errInvalidExpressionX: "invalid expression: '$1'",
errEnumHasNoValueX: "enum has no value \'$1\'", errEnumHasNoValueX: "enum has no value '$1'",
errNamedExprExpected: "named expression expected", errNamedExprExpected: "named expression expected",
errNamedExprNotAllowed: "named expression not allowed here", errNamedExprNotAllowed: "named expression not allowed here",
errXExpectsOneTypeParam: "\'$1\' expects one type parameter", errXExpectsOneTypeParam: "'$1' expects one type parameter",
errArrayExpectsTwoTypeParams: "array expects two type parameters", errArrayExpectsTwoTypeParams: "array expects two type parameters",
errInvalidVisibilityX: "invalid visibility: \'$1\'", errInvalidVisibilityX: "invalid visibility: '$1'",
errInitHereNotAllowed: "initialization not allowed here", errInitHereNotAllowed: "initialization not allowed here",
errXCannotBeAssignedTo: "\'$1\' cannot be assigned to", errXCannotBeAssignedTo: "'$1' cannot be assigned to",
errIteratorNotAllowed: "iterators can only be defined at the module\'s top level", errIteratorNotAllowed: "iterators can only be defined at the module's top level",
errXNeedsReturnType: "$1 needs a return type", errXNeedsReturnType: "$1 needs a return type",
errNoReturnTypeDeclared: "no return type declared", errNoReturnTypeDeclared: "no return type declared",
errNoCommand: "no command given", errNoCommand: "no command given",
errInvalidCommandX: "invalid command: \'$1\'", errInvalidCommandX: "invalid command: '$1'",
errXOnlyAtModuleScope: "\'$1\' is only allowed at top level", errXOnlyAtModuleScope: "'$1' is only allowed at top level",
errXNeedsParamObjectType: "'$1' needs a parameter that has an object type", errXNeedsParamObjectType: "'$1' needs a parameter that has an object type",
errTemplateInstantiationTooNested: "template instantiation too nested, try --evalTemplateLimit:N", errTemplateInstantiationTooNested: "template instantiation too nested, try --evalTemplateLimit:N",
errMacroInstantiationTooNested: "macro instantiation too nested, try --evalMacroLimit:N", errMacroInstantiationTooNested: "macro instantiation too nested, try --evalMacroLimit:N",
@ -334,17 +334,17 @@ const
errInvalidIndexValueForTuple: "invalid index value for tuple subscript", errInvalidIndexValueForTuple: "invalid index value for tuple subscript",
errCommandExpectsFilename: "command expects a filename argument", errCommandExpectsFilename: "command expects a filename argument",
errMainModuleMustBeSpecified: "please, specify a main module in the project configuration file", errMainModuleMustBeSpecified: "please, specify a main module in the project configuration file",
errXExpected: "\'$1\' expected", errXExpected: "'$1' expected",
errTIsNotAConcreteType: "\'$1\' is not a concrete type.", errTIsNotAConcreteType: "'$1' is not a concrete type.",
errCastToANonConcreteType: "cannot cast to a non concrete type: \'$1\'", errCastToANonConcreteType: "cannot cast to a non concrete type: '$1'",
errInvalidSectionStart: "invalid section start", errInvalidSectionStart: "invalid section start",
errGridTableNotImplemented: "grid table is not implemented", errGridTableNotImplemented: "grid table is not implemented",
errGeneralParseError: "general parse error", errGeneralParseError: "general parse error",
errNewSectionExpected: "new section expected", errNewSectionExpected: "new section expected",
errWhitespaceExpected: "whitespace expected, got \'$1\'", errWhitespaceExpected: "whitespace expected, got '$1'",
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",
errInstantiateXExplicitly: "instantiate '$1' explicitly", 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",
@ -354,26 +354,26 @@ const
"A destructor must be associated will all instantiations of a generic type", "A destructor must be associated will all instantiations of a generic type",
errInlineIteratorsAsProcParams: "inline iterators can be used as parameters only for " & errInlineIteratorsAsProcParams: "inline iterators can be used as parameters only for " &
"templates, macros and other inline iterators", "templates, macros and other inline iterators",
errXExpectsTwoArguments: "\'$1\' expects two arguments", errXExpectsTwoArguments: "'$1' expects two arguments",
errXExpectsObjectTypes: "\'$1\' expects object types", errXExpectsObjectTypes: "'$1' expects object types",
errXcanNeverBeOfThisSubtype: "\'$1\' can never be of this subtype", errXcanNeverBeOfThisSubtype: "'$1' can never be of this subtype",
errTooManyIterations: "interpretation requires too many iterations; " & errTooManyIterations: "interpretation requires too many iterations; " &
"if you are sure this is not a bug in your code edit " & "if you are sure this is not a bug in your code edit " &
"compiler/vmdef.MaxLoopIterations and rebuild the compiler", "compiler/vmdef.MaxLoopIterations and rebuild the compiler",
errCannotInterpretNodeX: "cannot evaluate \'$1\'", errCannotInterpretNodeX: "cannot evaluate '$1'",
errFieldXNotFound: "field \'$1\' cannot be found", errFieldXNotFound: "field '$1' cannot be found",
errInvalidConversionFromTypeX: "invalid conversion from type \'$1\'", errInvalidConversionFromTypeX: "invalid conversion from type '$1'",
errAssertionFailed: "assertion failed", errAssertionFailed: "assertion failed",
errCannotGenerateCodeForX: "cannot generate code for \'$1\'", errCannotGenerateCodeForX: "cannot generate code for '$1'",
errXRequiresOneArgument: "$1 requires one parameter", errXRequiresOneArgument: "$1 requires one parameter",
errUnhandledExceptionX: "unhandled exception: $1", errUnhandledExceptionX: "unhandled exception: $1",
errCyclicTree: "macro returned a cyclic abstract syntax tree", errCyclicTree: "macro returned a cyclic abstract syntax tree",
errXisNoMacroOrTemplate: "\'$1\' is no macro or template", errXisNoMacroOrTemplate: "'$1' is no macro or template",
errXhasSideEffects: "\'$1\' can have side effects", errXhasSideEffects: "'$1' can have side effects",
errIteratorExpected: "iterator within for loop context expected", errIteratorExpected: "iterator within for loop context expected",
errLetNeedsInit: "'let' symbol requires an initialization", errLetNeedsInit: "'let' symbol requires an initialization",
errThreadvarCannotInit: "a thread var cannot be initialized explicitly; this would only run for the main thread", errThreadvarCannotInit: "a thread var cannot be initialized explicitly; this would only run for the main thread",
errWrongSymbolX: "usage of \'$1\' is a user-defined error", errWrongSymbolX: "usage of '$1' is a user-defined error",
errIllegalCaptureX: "illegal capture '$1'", errIllegalCaptureX: "illegal capture '$1'",
errXCannotBeClosure: "'$1' cannot have 'closure' calling convention", errXCannotBeClosure: "'$1' cannot have 'closure' calling convention",
errXMustBeCompileTime: "'$1' can only be used in compile-time context", errXMustBeCompileTime: "'$1' can only be used in compile-time context",
@ -384,22 +384,22 @@ const
"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 inferred from the expected signature.", "of the generic paramers can be inferred from the expected signature.",
errProcHasNoConcreteType: "'$1' doesn't have a concrete type, due to unspecified generic parameters.", errProcHasNoConcreteType: "'$1' doesn't have a concrete type, due to unspecified generic parameters.",
errCompilerDoesntSupportTarget: "The current compiler \'$1\' doesn't support the requested compilation target", errCompilerDoesntSupportTarget: "The current compiler '$1' doesn't support the requested compilation target",
errInOutFlagNotExtern: "The `$1` modifier can be used only with imported types", errInOutFlagNotExtern: "The `$1` modifier can be used only with imported types",
errUser: "$1", errUser: "$1",
warnCannotOpenFile: "cannot open \'$1\'", warnCannotOpenFile: "cannot open '$1'",
warnOctalEscape: "octal escape sequences do not exist; leading zero is ignored", warnOctalEscape: "octal escape sequences do not exist; leading zero is ignored",
warnXIsNeverRead: "\'$1\' is never read", warnXIsNeverRead: "'$1' is never read",
warnXmightNotBeenInit: "\'$1\' might not have been initialized", warnXmightNotBeenInit: "'$1' might not have been initialized",
warnDeprecated: "$1 is deprecated", warnDeprecated: "$1 is deprecated",
warnConfigDeprecated: "config file '$1' is deprecated", warnConfigDeprecated: "config file '$1' is deprecated",
warnSmallLshouldNotBeUsed: "\'l\' should not be used as an identifier; may look like \'1\' (one)", warnSmallLshouldNotBeUsed: "'l' should not be used as an identifier; may look like '1' (one)",
warnUnknownMagic: "unknown magic \'$1\' might crash the compiler", warnUnknownMagic: "unknown magic '$1' might crash the compiler",
warnRedefinitionOfLabel: "redefinition of label \'$1\'", warnRedefinitionOfLabel: "redefinition of label '$1'",
warnUnknownSubstitutionX: "unknown substitution \'$1\'", warnUnknownSubstitutionX: "unknown substitution '$1'",
warnLanguageXNotSupported: "language \'$1\' not supported", warnLanguageXNotSupported: "language '$1' not supported",
warnFieldXNotSupported: "field \'$1\' not supported", warnFieldXNotSupported: "field '$1' not supported",
warnCommentXIgnored: "comment \'$1\' ignored", warnCommentXIgnored: "comment '$1' ignored",
warnTypelessParam: "'$1' has no type. Typeless parameters are deprecated; only allowed for 'template'", warnTypelessParam: "'$1' has no type. Typeless parameters are deprecated; only allowed for 'template'",
warnUseBase: "use {.base.} for base methods; baseless methods are deprecated", warnUseBase: "use {.base.} for base methods; baseless methods are deprecated",
warnWriteToForeignHeap: "write to foreign heap", warnWriteToForeignHeap: "write to foreign heap",
@ -416,19 +416,20 @@ const
warnDestructor: "usage of a type with a destructor in a non destructible context. This will become a compile time error in the future.", warnDestructor: "usage of a type with a destructor in a non destructible context. This will become a compile time error in the future.",
warnLockLevel: "$1", warnLockLevel: "$1",
warnResultShadowed: "Special variable 'result' is shadowed.", warnResultShadowed: "Special variable 'result' is shadowed.",
warnInconsistentSpacing: "Number of spaces around '$#' is not consistent",
warnUser: "$1", warnUser: "$1",
hintSuccess: "operation successful", hintSuccess: "operation successful",
hintSuccessX: "operation successful ($# lines compiled; $# sec total; $#; $#)", hintSuccessX: "operation successful ($# lines compiled; $# sec total; $#; $#)",
hintLineTooLong: "line too long", hintLineTooLong: "line too long",
hintXDeclaredButNotUsed: "\'$1\' is declared but not used", hintXDeclaredButNotUsed: "'$1' is declared but not used",
hintConvToBaseNotNeeded: "conversion to base object is not needed", hintConvToBaseNotNeeded: "conversion to base object is not needed",
hintConvFromXtoItselfNotNeeded: "conversion from $1 to itself is pointless", hintConvFromXtoItselfNotNeeded: "conversion from $1 to itself is pointless",
hintExprAlwaysX: "expression evaluates always to \'$1\'", hintExprAlwaysX: "expression evaluates always to '$1'",
hintQuitCalled: "quit() called", hintQuitCalled: "quit() called",
hintProcessing: "$1", hintProcessing: "$1",
hintCodeBegin: "generated code listing:", hintCodeBegin: "generated code listing:",
hintCodeEnd: "end of listing", hintCodeEnd: "end of listing",
hintConf: "used config file \'$1\'", hintConf: "used config file '$1'",
hintPath: "added path: '$1'", hintPath: "added path: '$1'",
hintConditionAlwaysTrue: "condition is always true: '$1'", hintConditionAlwaysTrue: "condition is always true: '$1'",
hintName: "name should be: '$1'", hintName: "name should be: '$1'",
@ -454,7 +455,8 @@ const
"TypelessParam", "UseBase", "WriteToForeignHeap", "TypelessParam", "UseBase", "WriteToForeignHeap",
"UnsafeCode", "EachIdentIsTuple", "ShadowIdent", "UnsafeCode", "EachIdentIsTuple", "ShadowIdent",
"ProveInit", "ProveField", "ProveIndex", "GcUnsafe", "GcUnsafe2", "Uninit", "ProveInit", "ProveField", "ProveIndex", "GcUnsafe", "GcUnsafe2", "Uninit",
"GcMem", "Destructor", "LockLevel", "ResultShadowed", "User"] "GcMem", "Destructor", "LockLevel", "ResultShadowed",
"Spacing", "User"]
HintsToStr* = ["Success", "SuccessX", "LineTooLong", HintsToStr* = ["Success", "SuccessX", "LineTooLong",
"XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded", "XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded",

View file

@ -205,7 +205,7 @@ proc readConfigFile(filename: string; cache: IdentCache; config: ConfigRef) =
stream = llStreamOpen(filename, fmRead) stream = llStreamOpen(filename, fmRead)
if stream != nil: if stream != nil:
initToken(tok) initToken(tok)
openLexer(L, filename, stream, cache) openLexer(L, filename, stream, cache, config)
tok.tokType = tkEof # to avoid a pointless warning tok.tokType = tkEof # to avoid a pointless warning
confTok(L, tok, config) # read in the first token confTok(L, tok, config) # read in the first token
while tok.tokType != tkEof: parseAssignment(L, tok, config) while tok.tokType != tkEof: parseAssignment(L, tok, config)

View file

@ -13,7 +13,7 @@
import import
strutils, os, intsets, strtabs strutils, os, intsets, strtabs
import "../compiler" / [options, ast, astalgo, msgs, semdata, ropes, idents] import ".." / [options, ast, astalgo, msgs, semdata, ropes, idents]
import prettybase import prettybase
type type

View file

@ -8,7 +8,7 @@
# #
import strutils, lexbase, streams import strutils, lexbase, streams
import "../compiler" / [ast, msgs, idents] import ".." / [ast, msgs, idents]
from os import splitFile from os import splitFile
type type

View file

@ -113,6 +113,7 @@ type
notnil notnil
ConfigRef* = ref object ## eventually all global configuration should be moved here ConfigRef* = ref object ## eventually all global configuration should be moved here
linesCompiled*: int # all lines that have been compiled
cppDefines*: HashSet[string] cppDefines*: HashSet[string]
headerFile*: string headerFile*: string
features*: set[Feature] features*: set[Feature]

View file

@ -27,7 +27,7 @@ when isMainModule:
outp.close outp.close
import import
llstream, lexer, idents, strutils, ast, astalgo, msgs llstream, lexer, idents, strutils, ast, astalgo, msgs, options
type type
TParser* = object # A TParser object represents a file that TParser* = object # A TParser object represents a file that
@ -84,20 +84,20 @@ proc getTok(p: var TParser) =
p.hasProgress = true p.hasProgress = true
proc openParser*(p: var TParser, fileIdx: FileIndex, inputStream: PLLStream, proc openParser*(p: var TParser, fileIdx: FileIndex, inputStream: PLLStream,
cache: IdentCache; cache: IdentCache; config: ConfigRef;
strongSpaces=false) = strongSpaces=false) =
## Open a parser, using the given arguments to set up its internal state. ## Open a parser, using the given arguments to set up its internal state.
## ##
initToken(p.tok) initToken(p.tok)
openLexer(p.lex, fileIdx, inputStream, cache) openLexer(p.lex, fileIdx, inputStream, cache, config)
getTok(p) # read the first token getTok(p) # read the first token
p.firstTok = true p.firstTok = true
p.strongSpaces = strongSpaces p.strongSpaces = strongSpaces
proc openParser*(p: var TParser, filename: string, inputStream: PLLStream, proc openParser*(p: var TParser, filename: string, inputStream: PLLStream,
cache: IdentCache; cache: IdentCache; config: ConfigRef;
strongSpaces=false) = strongSpaces=false) =
openParser(p, filename.fileInfoIdx, inputStream, cache, strongSpaces) openParser(p, filename.fileInfoIdx, inputStream, cache, config, strongSpaces)
proc closeParser(p: var TParser) = proc closeParser(p: var TParser) =
## Close a parser, freeing up its resources. ## Close a parser, freeing up its resources.
@ -268,13 +268,9 @@ proc isUnary(p: TParser): bool =
proc checkBinary(p: TParser) {.inline.} = proc checkBinary(p: TParser) {.inline.} =
## Check if the current parser token is a binary operator. ## Check if the current parser token is a binary operator.
# we don't check '..' here as that's too annoying # we don't check '..' here as that's too annoying
if p.strongSpaces and p.tok.tokType == tkOpr: if p.tok.tokType == tkOpr:
if p.tok.strongSpaceB > 0 and p.tok.strongSpaceA != p.tok.strongSpaceB: if p.tok.strongSpaceB > 0 and p.tok.strongSpaceA != p.tok.strongSpaceB:
parMessage(p, errGenerated, parMessage(p, warnInconsistentSpacing, prettyTok(p.tok))
"Number of spaces around '$#' not consistent" %
prettyTok(p.tok))
elif p.tok.strongSpaceA notin {0,1,2,4,8}:
parMessage(p, errGenerated, "Number of spaces must be 0,1,2,4 or 8")
#| module = stmt ^* (';' / IND{=}) #| module = stmt ^* (';' / IND{=})
#| #|
@ -706,10 +702,17 @@ proc namedParams(p: var TParser, callee: PNode,
# progress guaranteed # progress guaranteed
exprColonEqExprListAux(p, endTok, result) exprColonEqExprListAux(p, endTok, result)
proc commandParam(p: var TParser): PNode = proc commandParam(p: var TParser, isFirstParam: var bool): PNode =
result = parseExpr(p) result = parseExpr(p)
if p.tok.tokType == tkDo: if p.tok.tokType == tkDo:
result = postExprBlocks(p, result) result = postExprBlocks(p, result)
elif p.tok.tokType == tkEquals and not isFirstParam:
let lhs = result
result = newNodeP(nkExprEqExpr, p)
getTok(p)
addSon(result, lhs)
addSon(result, parseExpr(p))
isFirstParam = false
proc primarySuffix(p: var TParser, r: PNode, baseIndent: int): PNode = proc primarySuffix(p: var TParser, r: PNode, baseIndent: int): PNode =
#| primarySuffix = '(' (exprColonEqExpr comma?)* ')' doBlocks? #| primarySuffix = '(' (exprColonEqExpr comma?)* ')' doBlocks?
@ -744,17 +747,19 @@ proc primarySuffix(p: var TParser, r: PNode, baseIndent: int): PNode =
# progress guaranteed # progress guaranteed
somePar() somePar()
result = namedParams(p, result, nkCurlyExpr, tkCurlyRi) result = namedParams(p, result, nkCurlyExpr, tkCurlyRi)
of tkSymbol, tkAccent, tkIntLit..tkCharLit, tkNil, tkCast, tkAddr, tkType: of tkSymbol, tkAccent, tkIntLit..tkCharLit, tkNil, tkCast, tkAddr, tkType,
if p.inPragma == 0: tkOpr, tkDotDot:
if p.inPragma == 0 and (isUnary(p) or p.tok.tokType notin {tkOpr, tkDotDot}):
# actually parsing {.push hints:off.} as {.push(hints:off).} is a sweet # actually parsing {.push hints:off.} as {.push(hints:off).} is a sweet
# solution, but pragmas.nim can't handle that # solution, but pragmas.nim can't handle that
let a = result let a = result
result = newNodeP(nkCommand, p) result = newNodeP(nkCommand, p)
addSon(result, a) addSon(result, a)
var isFirstParam = true
when true: when true:
# progress NOT guaranteed # progress NOT guaranteed
p.hasProgress = false p.hasProgress = false
addSon result, commandParam(p) addSon result, commandParam(p, isFirstParam)
if not p.hasProgress: break if not p.hasProgress: break
else: else:
while p.tok.tokType != tkEof: while p.tok.tokType != tkEof:
@ -1306,17 +1311,18 @@ proc parseExprStmt(p: var TParser): PNode =
addSon(result, b) addSon(result, b)
else: else:
# simpleExpr parsed 'p a' from 'p a, b'? # simpleExpr parsed 'p a' from 'p a, b'?
var isFirstParam = false
if p.tok.indent < 0 and p.tok.tokType == tkComma and a.kind == nkCommand: if p.tok.indent < 0 and p.tok.tokType == tkComma and a.kind == nkCommand:
result = a result = a
while true: while true:
getTok(p) getTok(p)
optInd(p, result) optInd(p, result)
addSon(result, commandParam(p)) addSon(result, commandParam(p, isFirstParam))
if p.tok.tokType != tkComma: break if p.tok.tokType != tkComma: break
elif p.tok.indent < 0 and isExprStart(p): elif p.tok.indent < 0 and isExprStart(p):
result = newNode(nkCommand, a.info, @[a]) result = newNode(nkCommand, a.info, @[a])
while true: while true:
addSon(result, commandParam(p)) addSon(result, commandParam(p, isFirstParam))
if p.tok.tokType != tkComma: break if p.tok.tokType != tkComma: break
getTok(p) getTok(p)
optInd(p, result) optInd(p, result)
@ -2181,8 +2187,8 @@ proc parseTopLevelStmt(p: var TParser): PNode =
if result.kind == nkEmpty: parMessage(p, errExprExpected, p.tok) if result.kind == nkEmpty: parMessage(p, errExprExpected, p.tok)
break break
proc parseString*(s: string; cache: IdentCache; filename: string = ""; proc parseString*(s: string; cache: IdentCache; config: ConfigRef;
line: int = 0; filename: string = ""; line: int = 0;
errorHandler: TErrorHandler = nil): PNode = errorHandler: TErrorHandler = nil): PNode =
## Parses a string into an AST, returning the top node. ## Parses a string into an AST, returning the top node.
## `filename` and `line`, although optional, provide info so that the ## `filename` and `line`, although optional, provide info so that the
@ -2195,7 +2201,7 @@ proc parseString*(s: string; cache: IdentCache; filename: string = "";
# XXX for now the builtin 'parseStmt/Expr' functions do not know about strong # XXX for now the builtin 'parseStmt/Expr' functions do not know about strong
# spaces... # spaces...
parser.lex.errorHandler = errorHandler parser.lex.errorHandler = errorHandler
openParser(parser, filename, stream, cache, false) openParser(parser, filename, stream, cache, config, false)
result = parser.parseAll result = parser.parseAll
closeParser(parser) closeParser(parser)

View file

@ -207,7 +207,7 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream,
else: else:
s = stream s = stream
while true: while true:
openParsers(p, fileIdx, s, cache) openParsers(p, fileIdx, s, cache, graph.config)
if sfSystemModule notin module.flags: if sfSystemModule notin module.flags:
# XXX what about caching? no processing then? what if I change the # XXX what about caching? no processing then? what if I change the

File diff suppressed because it is too large Load diff

View file

@ -777,7 +777,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
incl(sym.flags, sfRegister) incl(sym.flags, sfRegister)
of wThreadVar: of wThreadVar:
noVal(it) noVal(it)
incl(sym.flags, sfThread) incl(sym.flags, {sfThread, sfGlobal})
of wDeadCodeElimUnused: discard # deprecated, dead code elim always on of wDeadCodeElimUnused: discard # deprecated, dead code elim always on
of wNoForward: pragmaNoForward(c, it) of wNoForward: pragmaNoForward(c, it)
of wReorder: pragmaNoForward(c, it, sfReorder) of wReorder: pragmaNoForward(c, it, sfReorder)

View file

@ -137,7 +137,7 @@ proc hasIncludes(n:PNode): bool =
proc includeModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex; proc includeModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex;
cache: IdentCache): PNode {.procvar.} = cache: IdentCache): PNode {.procvar.} =
result = syntaxes.parseFile(fileIdx, cache) result = syntaxes.parseFile(fileIdx, cache, graph.config)
graph.addDep(s, fileIdx) graph.addDep(s, fileIdx)
graph.addIncludeDep(FileIndex s.position, fileIdx) graph.addIncludeDep(FileIndex s.position, fileIdx)

View file

@ -28,7 +28,7 @@ proc listDirs(a: VmArgs, filter: set[PathComponent]) =
proc setupVM*(module: PSym; cache: IdentCache; scriptName: string; proc setupVM*(module: PSym; cache: IdentCache; scriptName: string;
config: ConfigRef): PEvalContext = config: ConfigRef): PEvalContext =
# For Nimble we need to export 'setupVM'. # For Nimble we need to export 'setupVM'.
result = newCtx(module, cache) result = newCtx(module, cache, config)
result.mode = emRepl result.mode = emRepl
registerAdditionalOps(result) registerAdditionalOps(result)

View file

@ -313,7 +313,7 @@ proc tryConstExpr(c: PContext, n: PNode): PNode =
msgs.gErrorMax = high(int) msgs.gErrorMax = high(int)
try: try:
result = evalConstExpr(c.module, c.cache, e) result = evalConstExpr(c.module, c.cache, c.graph.config, e)
if result == nil or result.kind == nkEmpty: if result == nil or result.kind == nkEmpty:
result = nil result = nil
else: else:
@ -334,7 +334,7 @@ proc semConstExpr(c: PContext, n: PNode): PNode =
result = getConstExpr(c.module, e) result = getConstExpr(c.module, e)
if result == nil: if result == nil:
#if e.kind == nkEmpty: globalError(n.info, errConstExprExpected) #if e.kind == nkEmpty: globalError(n.info, errConstExprExpected)
result = evalConstExpr(c.module, c.cache, e) result = evalConstExpr(c.module, c.cache, c.graph.config, e)
if result == nil or result.kind == nkEmpty: if result == nil or result.kind == nkEmpty:
if e.info != n.info: if e.info != n.info:
pushInfoContext(n.info) pushInfoContext(n.info)
@ -439,7 +439,7 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
#if c.evalContext == nil: #if c.evalContext == nil:
# c.evalContext = c.createEvalContext(emStatic) # c.evalContext = c.createEvalContext(emStatic)
result = evalMacroCall(c.module, c.cache, n, nOrig, sym) result = evalMacroCall(c.module, c.cache, c.graph.config, n, nOrig, sym)
if efNoSemCheck notin flags: if efNoSemCheck notin flags:
result = semAfterMacroCall(c, n, result, sym, flags) result = semAfterMacroCall(c, n, result, sym, flags)
result = wrapInComesFrom(nOrig.info, sym, result) result = wrapInComesFrom(nOrig.info, sym, result)

View file

@ -89,6 +89,7 @@ type
ambiguousSymbols*: IntSet # ids of all ambiguous symbols (cannot ambiguousSymbols*: IntSet # ids of all ambiguous symbols (cannot
# store this info in the syms themselves!) # store this info in the syms themselves!)
inGenericContext*: int # > 0 if we are in a generic type inGenericContext*: int # > 0 if we are in a generic type
inStaticContext*: int # > 0 if we are inside a static: block
inUnrolledContext*: int # > 0 if we are unrolling a loop inUnrolledContext*: int # > 0 if we are unrolling a loop
compilesContextId*: int # > 0 if we are in a ``compiles`` magic compilesContextId*: int # > 0 if we are in a ``compiles`` magic
compilesContextIdGenerator*: int compilesContextIdGenerator*: int

View file

@ -605,12 +605,12 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
call.add(a) call.add(a)
#echo "NOW evaluating at compile time: ", call.renderTree #echo "NOW evaluating at compile time: ", call.renderTree
if sfCompileTime in callee.flags: if sfCompileTime in callee.flags:
result = evalStaticExpr(c.module, c.cache, call, c.p.owner) result = evalStaticExpr(c.module, c.cache, c.graph.config, call, c.p.owner)
if result.isNil: if result.isNil:
localError(n.info, errCannotInterpretNodeX, renderTree(call)) localError(n.info, errCannotInterpretNodeX, renderTree(call))
else: result = fixupTypeAfterEval(c, result, n) else: result = fixupTypeAfterEval(c, result, n)
else: else:
result = evalConstExpr(c.module, c.cache, call) result = evalConstExpr(c.module, c.cache, c.graph.config, call)
if result.isNil: result = n if result.isNil: result = n
else: result = fixupTypeAfterEval(c, result, n) else: result = fixupTypeAfterEval(c, result, n)
#if result != n: #if result != n:
@ -619,7 +619,7 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
proc semStaticExpr(c: PContext, n: PNode): PNode = proc semStaticExpr(c: PContext, n: PNode): PNode =
let a = semExpr(c, n.sons[0]) let a = semExpr(c, n.sons[0])
if a.findUnresolvedStatic != nil: return a if a.findUnresolvedStatic != nil: return a
result = evalStaticExpr(c.module, c.cache, a, c.p.owner) result = evalStaticExpr(c.module, c.cache, c.graph.config, a, c.p.owner)
if result.isNil: if result.isNil:
localError(n.info, errCannotInterpretNodeX, renderTree(n)) localError(n.info, errCannotInterpretNodeX, renderTree(n))
result = emptyNode result = emptyNode
@ -960,18 +960,20 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
else: else:
result = newSymNode(s, n.info) result = newSymNode(s, n.info)
of skMacro: of skMacro:
if efNoEvaluateGeneric in flags and s.ast[genericParamsPos].len > 0: if efNoEvaluateGeneric in flags and s.ast[genericParamsPos].len > 0 or
(n.kind notin nkCallKinds and s.requiredParams > 0):
markUsed(n.info, s, c.graph.usageSym) markUsed(n.info, s, c.graph.usageSym)
styleCheckUse(n.info, s) styleCheckUse(n.info, s)
result = newSymNode(s, n.info) result = symChoice(c, n, s, scClosed)
else: else:
result = semMacroExpr(c, n, n, s, flags) result = semMacroExpr(c, n, n, s, flags)
of skTemplate: of skTemplate:
if efNoEvaluateGeneric in flags and s.ast[genericParamsPos].len > 0 or if efNoEvaluateGeneric in flags and s.ast[genericParamsPos].len > 0 or
(n.kind notin nkCallKinds and s.requiredParams > 0) or
sfCustomPragma in sym.flags: sfCustomPragma in sym.flags:
markUsed(n.info, s, c.graph.usageSym) markUsed(n.info, s, c.graph.usageSym)
styleCheckUse(n.info, s) styleCheckUse(n.info, s)
result = newSymNode(s, n.info) result = symChoice(c, n, s, scClosed)
else: else:
result = semTemplateExpr(c, n, s, flags) result = semTemplateExpr(c, n, s, flags)
of skParam: of skParam:
@ -1778,6 +1780,7 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
let oldInGenericContext = c.inGenericContext let oldInGenericContext = c.inGenericContext
let oldInUnrolledContext = c.inUnrolledContext let oldInUnrolledContext = c.inUnrolledContext
let oldInGenericInst = c.inGenericInst let oldInGenericInst = c.inGenericInst
let oldInStaticContext = c.inStaticContext
let oldProcCon = c.p let oldProcCon = c.p
c.generics = @[] c.generics = @[]
var err: string var err: string
@ -1792,6 +1795,7 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
c.inGenericContext = oldInGenericContext c.inGenericContext = oldInGenericContext
c.inUnrolledContext = oldInUnrolledContext c.inUnrolledContext = oldInUnrolledContext
c.inGenericInst = oldInGenericInst c.inGenericInst = oldInGenericInst
c.inStaticContext = oldInStaticContext
c.p = oldProcCon c.p = oldProcCon
msgs.setInfoContextLen(oldContextLen) msgs.setInfoContextLen(oldContextLen)
setLen(c.graph.owners, oldOwnerLen) setLen(c.graph.owners, oldOwnerLen)
@ -2156,9 +2160,25 @@ proc semBlock(c: PContext, n: PNode): PNode =
closeScope(c) closeScope(c)
dec(c.p.nestedBlockCounter) dec(c.p.nestedBlockCounter)
proc semExportExcept(c: PContext, n: PNode): PNode =
let moduleName = semExpr(c, n[0])
if moduleName.kind != nkSym or moduleName.sym.kind != skModule:
localError(n.info, "The export/except syntax expects a module name")
return
let exceptSet = readExceptSet(n)
let exported = moduleName.sym
strTableAdd(c.module.tab, exported)
var i: TTabIter
var s = initTabIter(i, exported.tab)
while s != nil:
if s.kind in ExportableSymKinds+{skModule} and
s.name.id notin exceptSet:
strTableAdd(c.module.tab, s)
s = nextIter(i, exported.tab)
result = n
proc semExport(c: PContext, n: PNode): PNode = proc semExport(c: PContext, n: PNode): PNode =
var x = newNodeI(n.kind, n.info) var x = newNodeI(n.kind, n.info)
#let L = if n.kind == nkExportExceptStmt: L = 1 else: n.len
for i in 0..<n.len: for i in 0..<n.len:
let a = n.sons[i] let a = n.sons[i]
var o: TOverloadIter var o: TOverloadIter
@ -2444,9 +2464,12 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
of nkIncludeStmt: of nkIncludeStmt:
#if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "include") #if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "include")
result = evalInclude(c, n) result = evalInclude(c, n)
of nkExportStmt, nkExportExceptStmt: of nkExportStmt:
if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "export") if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "export")
result = semExport(c, n) result = semExport(c, n)
of nkExportExceptStmt:
if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "export")
result = semExportExcept(c, n)
of nkPragmaBlock: of nkPragmaBlock:
result = semPragmaBlock(c, n) result = semPragmaBlock(c, n)
of nkStaticStmt: of nkStaticStmt:

View file

@ -199,6 +199,10 @@ proc semBindSym(c: PContext, n: PNode): PNode =
if s != nil: if s != nil:
# we need to mark all symbols: # we need to mark all symbols:
var sc = symChoice(c, id, s, TSymChoiceRule(isMixin.intVal)) var sc = symChoice(c, id, s, TSymChoiceRule(isMixin.intVal))
if not (c.inStaticContext > 0 or getCurrOwner(c).isCompileTimeProc):
# inside regular code, bindSym resolves to the sym-choice
# nodes (see tinspectsymbol)
return sc
result.add(sc) result.add(sc)
else: else:
errorUndeclaredIdentifier(c, n.sons[1].info, sl.strVal) errorUndeclaredIdentifier(c, n.sons[1].info, sl.strVal)

View file

@ -545,7 +545,8 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
b.sons[j] = newSymNode(v) b.sons[j] = newSymNode(v)
checkNilable(v) checkNilable(v)
if sfCompileTime in v.flags: hasCompileTime = true if sfCompileTime in v.flags: hasCompileTime = true
if hasCompileTime: vm.setupCompileTimeVar(c.module, c.cache, result) if hasCompileTime:
vm.setupCompileTimeVar(c.module, c.cache, c.graph.config, result)
proc semConst(c: PContext, n: PNode): PNode = proc semConst(c: PContext, n: PNode): PNode =
result = copyNode(n) result = copyNode(n)
@ -1753,9 +1754,11 @@ proc semPragmaBlock(c: PContext, n: PNode): PNode =
proc semStaticStmt(c: PContext, n: PNode): PNode = proc semStaticStmt(c: PContext, n: PNode): PNode =
#echo "semStaticStmt" #echo "semStaticStmt"
#writeStackTrace() #writeStackTrace()
inc c.inStaticContext
let a = semStmt(c, n.sons[0]) let a = semStmt(c, n.sons[0])
dec c.inStaticContext
n.sons[0] = a n.sons[0] = a
evalStaticStmt(c.module, c.cache, a, c.p.owner) evalStaticStmt(c.module, c.cache, c.graph.config, a, c.p.owner)
result = newNodeI(nkDiscardStmt, n.info, 1) result = newNodeI(nkDiscardStmt, n.info, 1)
result.sons[0] = emptyNode result.sons[0] = emptyNode

View file

@ -1962,7 +1962,8 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
inc(m.genericMatches) inc(m.genericMatches)
if arg.typ == nil: if arg.typ == nil:
result = arg result = arg
elif skipTypes(arg.typ, abstractVar-{tyTypeDesc}).kind == tyTuple: elif skipTypes(arg.typ, abstractVar-{tyTypeDesc}).kind == tyTuple or
m.inheritancePenalty > 0:
result = implicitConv(nkHiddenSubConv, f, arg, m, c) result = implicitConv(nkHiddenSubConv, f, arg, m, c)
elif arg.typ.isEmptyContainer: elif arg.typ.isEmptyContainer:
result = arg.copyTree result = arg.copyTree
@ -2032,8 +2033,9 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
y.calleeSym = m.calleeSym y.calleeSym = m.calleeSym
z.calleeSym = m.calleeSym z.calleeSym = m.calleeSym
var best = -1 var best = -1
for i in countup(0, sonsLen(arg) - 1): for i in 0 ..< arg.len:
if arg.sons[i].sym.kind in {skProc, skFunc, skMethod, skConverter, skIterator}: if arg.sons[i].sym.kind in {skProc, skFunc, skMethod, skConverter,
skIterator, skMacro, skTemplate}:
copyCandidate(z, m) copyCandidate(z, m)
z.callee = arg.sons[i].typ z.callee = arg.sons[i].typ
if tfUnresolved in z.callee.flags: continue if tfUnresolved in z.callee.flags: continue
@ -2062,6 +2064,7 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
x = z x = z
elif cmp == 0: elif cmp == 0:
y = z # z is as good as x y = z # z is as good as x
if x.state == csEmpty: if x.state == csEmpty:
result = nil result = nil
elif y.state == csMatch and cmpCandidates(x, y) == 0: elif y.state == csMatch and cmpCandidates(x, y) == 0:
@ -2070,7 +2073,7 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
# ambiguous: more than one symbol fits! # ambiguous: more than one symbol fits!
# See tsymchoice_for_expr as an example. 'f.kind == tyExpr' should match # See tsymchoice_for_expr as an example. 'f.kind == tyExpr' should match
# anyway: # anyway:
if f.kind == tyExpr: result = arg if f.kind in {tyExpr, tyStmt}: result = arg
else: result = nil else: result = nil
else: else:
# only one valid interpretation found: # only one valid interpretation found:
@ -2171,7 +2174,8 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
var formal: PSym = if formalLen > 1: m.callee.n.sons[1].sym else: nil var formal: PSym = if formalLen > 1: m.callee.n.sons[1].sym else: nil
while a < n.len: while a < n.len:
if a >= formalLen-1 and formal != nil and formal.typ.isVarargsUntyped: if a >= formalLen-1 and f < formalLen and m.callee.n[f].typ.isVarargsUntyped:
formal = m.callee.n.sons[f].sym
incl(marker, formal.position) incl(marker, formal.position)
if container.isNil: if container.isNil:
container = newNodeIT(nkArgList, n.sons[a].info, arrayConstr(c, n.info)) container = newNodeIT(nkArgList, n.sons[a].info, arrayConstr(c, n.info))

View file

@ -11,17 +11,17 @@
import import
strutils, llstream, ast, astalgo, idents, lexer, options, msgs, parser, strutils, llstream, ast, astalgo, idents, lexer, options, msgs, parser,
pbraces, filters, filter_tmpl, renderer filters, filter_tmpl, renderer
type type
TFilterKind* = enum TFilterKind* = enum
filtNone, filtTemplate, filtReplace, filtStrip filtNone, filtTemplate, filtReplace, filtStrip
TParserKind* = enum TParserKind* = enum
skinStandard, skinStrongSpaces, skinBraces, skinEndX skinStandard, skinStrongSpaces, skinEndX
const const
parserNames*: array[TParserKind, string] = ["standard", "strongspaces", parserNames*: array[TParserKind, string] = ["standard", "strongspaces",
"braces", "endx"] "endx"]
filterNames*: array[TFilterKind, string] = ["none", "stdtmpl", "replace", filterNames*: array[TFilterKind, string] = ["none", "stdtmpl", "replace",
"strip"] "strip"]
@ -34,8 +34,6 @@ proc parseAll*(p: var TParsers): PNode =
case p.skin case p.skin
of skinStandard, skinStrongSpaces: of skinStandard, skinStrongSpaces:
result = parser.parseAll(p.parser) result = parser.parseAll(p.parser)
of skinBraces:
result = pbraces.parseAll(p.parser)
of skinEndX: of skinEndX:
internalError("parser to implement") internalError("parser to implement")
result = ast.emptyNode result = ast.emptyNode
@ -44,8 +42,6 @@ proc parseTopLevelStmt*(p: var TParsers): PNode =
case p.skin case p.skin
of skinStandard, skinStrongSpaces: of skinStandard, skinStrongSpaces:
result = parser.parseTopLevelStmt(p.parser) result = parser.parseTopLevelStmt(p.parser)
of skinBraces:
result = pbraces.parseTopLevelStmt(p.parser)
of skinEndX: of skinEndX:
internalError("parser to implement") internalError("parser to implement")
result = ast.emptyNode result = ast.emptyNode
@ -62,7 +58,8 @@ proc containsShebang(s: string, i: int): bool =
while j < s.len and s[j] in Whitespace: inc(j) while j < s.len and s[j] in Whitespace: inc(j)
result = s[j] == '/' result = s[j] == '/'
proc parsePipe(filename: string, inputStream: PLLStream; cache: IdentCache): PNode = proc parsePipe(filename: string, inputStream: PLLStream; cache: IdentCache;
config: ConfigRef): PNode =
result = ast.emptyNode result = ast.emptyNode
var s = llStreamOpen(filename, fmRead) var s = llStreamOpen(filename, fmRead)
if s != nil: if s != nil:
@ -78,7 +75,7 @@ proc parsePipe(filename: string, inputStream: PLLStream; cache: IdentCache): PNo
inc(i, 2) inc(i, 2)
while i < line.len and line[i] in Whitespace: inc(i) while i < line.len and line[i] in Whitespace: inc(i)
var q: TParser var q: TParser
parser.openParser(q, filename, llStreamOpen(substr(line, i)), cache) parser.openParser(q, filename, llStreamOpen(substr(line, i)), cache, config)
result = parser.parseAll(q) result = parser.parseAll(q)
parser.closeParser(q) parser.closeParser(q)
llStreamClose(s) llStreamClose(s)
@ -139,23 +136,23 @@ proc evalPipe(p: var TParsers, n: PNode, filename: string,
result = applyFilter(p, n, filename, result) result = applyFilter(p, n, filename, result)
proc openParsers*(p: var TParsers, fileIdx: FileIndex, inputstream: PLLStream; proc openParsers*(p: var TParsers, fileIdx: FileIndex, inputstream: PLLStream;
cache: IdentCache) = cache: IdentCache; config: ConfigRef) =
var s: PLLStream var s: PLLStream
p.skin = skinStandard p.skin = skinStandard
let filename = fileIdx.toFullPathConsiderDirty let filename = fileIdx.toFullPathConsiderDirty
var pipe = parsePipe(filename, inputstream, cache) var pipe = parsePipe(filename, inputstream, cache, config)
if pipe != nil: s = evalPipe(p, pipe, filename, inputstream) if pipe != nil: s = evalPipe(p, pipe, filename, inputstream)
else: s = inputstream else: s = inputstream
case p.skin case p.skin
of skinStandard, skinBraces, skinEndX: of skinStandard, skinEndX:
parser.openParser(p.parser, fileIdx, s, cache, false) parser.openParser(p.parser, fileIdx, s, cache, config, false)
of skinStrongSpaces: of skinStrongSpaces:
parser.openParser(p.parser, fileIdx, s, cache, true) parser.openParser(p.parser, fileIdx, s, cache, config, true)
proc closeParsers*(p: var TParsers) = proc closeParsers*(p: var TParsers) =
parser.closeParser(p.parser) parser.closeParser(p.parser)
proc parseFile*(fileIdx: FileIndex; cache: IdentCache): PNode {.procvar.} = proc parseFile*(fileIdx: FileIndex; cache: IdentCache; config: ConfigRef): PNode {.procvar.} =
var var
p: TParsers p: TParsers
f: File f: File
@ -163,6 +160,6 @@ proc parseFile*(fileIdx: FileIndex; cache: IdentCache): PNode {.procvar.} =
if not open(f, filename): if not open(f, filename):
rawMessage(errCannotOpenFile, filename) rawMessage(errCannotOpenFile, filename)
return return
openParsers(p, fileIdx, llStreamOpen(f), cache) openParsers(p, fileIdx, llStreamOpen(f), cache, config)
result = parseAll(p) result = parseAll(p)
closeParsers(p) closeParsers(p)

View file

@ -612,7 +612,7 @@ proc firstOrd*(t: PType): BiggestInt =
else: else:
assert(t.n.sons[0].kind == nkSym) assert(t.n.sons[0].kind == nkSym)
result = t.n.sons[0].sym.position result = t.n.sons[0].sym.position
of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias, tyStatic: of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias, tyStatic, tyInferred:
result = firstOrd(lastSon(t)) result = firstOrd(lastSon(t))
of tyOrdinal: of tyOrdinal:
if t.len > 0: result = firstOrd(lastSon(t)) if t.len > 0: result = firstOrd(lastSon(t))
@ -651,7 +651,7 @@ proc lastOrd*(t: PType; fixedUnsigned = false): BiggestInt =
of tyEnum: of tyEnum:
assert(t.n.sons[sonsLen(t.n) - 1].kind == nkSym) assert(t.n.sons[sonsLen(t.n) - 1].kind == nkSym)
result = t.n.sons[sonsLen(t.n) - 1].sym.position result = t.n.sons[sonsLen(t.n) - 1].sym.position
of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias, tyStatic: of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias, tyStatic, tyInferred:
result = lastOrd(lastSon(t)) result = lastOrd(lastSon(t))
of tyProxy: result = 0 of tyProxy: result = 0
of tyOrdinal: of tyOrdinal:

View file

@ -210,8 +210,14 @@ proc putIntoNode(n: var PNode; x: TFullReg) =
of rkInt: n.intVal = x.intVal of rkInt: n.intVal = x.intVal
of rkFloat: n.floatVal = x.floatVal of rkFloat: n.floatVal = x.floatVal
of rkNode: of rkNode:
if nfIsRef in x.node.flags: n = x.node if nfIsRef in x.node.flags:
else: n[] = x.node[] n = x.node
else:
let destIsRef = nfIsRef in n.flags
n[] = x.node[]
# Ref-ness must be kept for the destination
if destIsRef:
n.flags.incl nfIsRef
of rkRegisterAddr: putIntoNode(n, x.regAddr[]) of rkRegisterAddr: putIntoNode(n, x.regAddr[])
of rkNodeAddr: n[] = x.nodeAddr[][] of rkNodeAddr: n[] = x.nodeAddr[][]
@ -1341,8 +1347,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
decodeB(rkNode) decodeB(rkNode)
# c.debug[pc].line.int - countLines(regs[rb].strVal) ? # c.debug[pc].line.int - countLines(regs[rb].strVal) ?
var error: string var error: string
let ast = parseString(regs[rb].node.strVal, c.cache, c.debug[pc].toFullPath, let ast = parseString(regs[rb].node.strVal, c.cache, c.config,
c.debug[pc].line.int, c.debug[pc].toFullPath, c.debug[pc].line.int,
proc (info: TLineInfo; msg: TMsgKind; arg: string) = proc (info: TLineInfo; msg: TMsgKind; arg: string) =
if error.isNil and msg <= msgs.errMax: if error.isNil and msg <= msgs.errMax:
error = formatMsg(info, msg, arg)) error = formatMsg(info, msg, arg))
@ -1355,8 +1361,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
of opcParseStmtToAst: of opcParseStmtToAst:
decodeB(rkNode) decodeB(rkNode)
var error: string var error: string
let ast = parseString(regs[rb].node.strVal, c.cache, c.debug[pc].toFullPath, let ast = parseString(regs[rb].node.strVal, c.cache, c.config,
c.debug[pc].line.int, c.debug[pc].toFullPath, c.debug[pc].line.int,
proc (info: TLineInfo; msg: TMsgKind; arg: string) = proc (info: TLineInfo; msg: TMsgKind; arg: string) =
if error.isNil and msg <= msgs.errMax: if error.isNil and msg <= msgs.errMax:
error = formatMsg(info, msg, arg)) error = formatMsg(info, msg, arg))
@ -1643,9 +1649,9 @@ include vmops
var var
globalCtx*: PCtx globalCtx*: PCtx
proc setupGlobalCtx(module: PSym; cache: IdentCache) = proc setupGlobalCtx(module: PSym; cache: IdentCache; config: ConfigRef) =
if globalCtx.isNil: if globalCtx.isNil:
globalCtx = newCtx(module, cache) globalCtx = newCtx(module, cache, config)
registerAdditionalOps(globalCtx) registerAdditionalOps(globalCtx)
else: else:
refresh(globalCtx, module) refresh(globalCtx, module)
@ -1656,7 +1662,7 @@ proc myOpen(graph: ModuleGraph; module: PSym; cache: IdentCache): PPassContext =
#pushStackFrame(c, newStackFrame()) #pushStackFrame(c, newStackFrame())
# XXX produce a new 'globals' environment here: # XXX produce a new 'globals' environment here:
setupGlobalCtx(module, cache) setupGlobalCtx(module, cache, graph.config)
result = globalCtx result = globalCtx
when hasFFI: when hasFFI:
globalCtx.features = {allowFFI, allowCast} globalCtx.features = {allowFFI, allowCast}
@ -1677,10 +1683,11 @@ proc myClose(graph: ModuleGraph; c: PPassContext, n: PNode): PNode =
const evalPass* = makePass(myOpen, nil, myProcess, myClose) const evalPass* = makePass(myOpen, nil, myProcess, myClose)
proc evalConstExprAux(module: PSym; cache: IdentCache; prc: PSym, n: PNode, proc evalConstExprAux(module: PSym; cache: IdentCache;
config: ConfigRef; prc: PSym, n: PNode,
mode: TEvalMode): PNode = mode: TEvalMode): PNode =
let n = transformExpr(module, n) let n = transformExpr(module, n)
setupGlobalCtx(module, cache) setupGlobalCtx(module, cache, config)
var c = globalCtx var c = globalCtx
let oldMode = c.mode let oldMode = c.mode
defer: c.mode = oldMode defer: c.mode = oldMode
@ -1695,17 +1702,17 @@ proc evalConstExprAux(module: PSym; cache: IdentCache; prc: PSym, n: PNode,
result = rawExecute(c, start, tos).regToNode result = rawExecute(c, start, tos).regToNode
if result.info.col < 0: result.info = n.info if result.info.col < 0: result.info = n.info
proc evalConstExpr*(module: PSym; cache: IdentCache, e: PNode): PNode = proc evalConstExpr*(module: PSym; cache: IdentCache, config: ConfigRef; e: PNode): PNode =
result = evalConstExprAux(module, cache, nil, e, emConst) result = evalConstExprAux(module, cache, config, nil, e, emConst)
proc evalStaticExpr*(module: PSym; cache: IdentCache, e: PNode, prc: PSym): PNode = proc evalStaticExpr*(module: PSym; cache: IdentCache, config: ConfigRef; e: PNode, prc: PSym): PNode =
result = evalConstExprAux(module, cache, prc, e, emStaticExpr) result = evalConstExprAux(module, cache, config, prc, e, emStaticExpr)
proc evalStaticStmt*(module: PSym; cache: IdentCache, e: PNode, prc: PSym) = proc evalStaticStmt*(module: PSym; cache: IdentCache, config: ConfigRef; e: PNode, prc: PSym) =
discard evalConstExprAux(module, cache, prc, e, emStaticStmt) discard evalConstExprAux(module, cache, config, prc, e, emStaticStmt)
proc setupCompileTimeVar*(module: PSym; cache: IdentCache, n: PNode) = proc setupCompileTimeVar*(module: PSym; cache: IdentCache, config: ConfigRef; n: PNode) =
discard evalConstExprAux(module, cache, nil, n, emStaticStmt) discard evalConstExprAux(module, cache, config, nil, n, emStaticStmt)
proc setupMacroParam(x: PNode, typ: PType): TFullReg = proc setupMacroParam(x: PNode, typ: PType): TFullReg =
case typ.kind case typ.kind
@ -1733,8 +1740,8 @@ iterator genericParamsInMacroCall*(macroSym: PSym, call: PNode): (PSym, PNode) =
const evalMacroLimit = 1000 const evalMacroLimit = 1000
var evalMacroCounter: int var evalMacroCounter: int
proc evalMacroCall*(module: PSym; cache: IdentCache, n, nOrig: PNode, proc evalMacroCall*(module: PSym; cache: IdentCache; config: ConfigRef;
sym: PSym): PNode = n, nOrig: PNode, sym: PSym): PNode =
# XXX globalError() is ugly here, but I don't know a better solution for now # XXX globalError() is ugly here, but I don't know a better solution for now
inc(evalMacroCounter) inc(evalMacroCounter)
if evalMacroCounter > evalMacroLimit: if evalMacroCounter > evalMacroLimit:
@ -1746,7 +1753,7 @@ proc evalMacroCall*(module: PSym; cache: IdentCache, n, nOrig: PNode,
globalError(n.info, "in call '$#' got $#, but expected $# argument(s)" % [ globalError(n.info, "in call '$#' got $#, but expected $# argument(s)" % [
n.renderTree, $(n.safeLen-1), $(sym.typ.len-1)]) n.renderTree, $(n.safeLen-1), $(sym.typ.len-1)])
setupGlobalCtx(module, cache) setupGlobalCtx(module, cache, config)
var c = globalCtx var c = globalCtx
c.comesFromHeuristic.line = 0'u16 c.comesFromHeuristic.line = 0'u16

View file

@ -10,7 +10,7 @@
## This module contains the type definitions for the new evaluation engine. ## This module contains the type definitions for the new evaluation engine.
## An instruction is 1-3 int32s in memory, it is a register based VM. ## An instruction is 1-3 int32s in memory, it is a register based VM.
import ast, passes, msgs, idents, intsets import ast, passes, msgs, idents, intsets, options
const const
byteExcess* = 128 # we use excess-K for immediates byteExcess* = 128 # we use excess-K for immediates
@ -206,17 +206,19 @@ type
callbacks*: seq[tuple[key: string, value: VmCallback]] callbacks*: seq[tuple[key: string, value: VmCallback]]
errorFlag*: string errorFlag*: string
cache*: IdentCache cache*: IdentCache
config*: ConfigRef
TPosition* = distinct int TPosition* = distinct int
PEvalContext* = PCtx PEvalContext* = PCtx
proc newCtx*(module: PSym; cache: IdentCache): PCtx = proc newCtx*(module: PSym; cache: IdentCache; config: ConfigRef = nil): PCtx =
let conf = if config != nil: config else: newConfigRef()
PCtx(code: @[], debug: @[], PCtx(code: @[], debug: @[],
globals: newNode(nkStmtListExpr), constants: newNode(nkStmtList), types: @[], globals: newNode(nkStmtListExpr), constants: newNode(nkStmtList), types: @[],
prc: PProc(blocks: @[]), module: module, loopIterations: MaxLoopIterations, prc: PProc(blocks: @[]), module: module, loopIterations: MaxLoopIterations,
comesFromHeuristic: unknownLineInfo(), callbacks: @[], errorFlag: "", comesFromHeuristic: unknownLineInfo(), callbacks: @[], errorFlag: "",
cache: cache) cache: cache, config: conf)
proc refresh*(c: PCtx, module: PSym) = proc refresh*(c: PCtx, module: PSym) =
c.module = module c.module = module

View file

@ -1554,7 +1554,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
of tyCString, tyString: of tyCString, tyString:
result = newNodeIT(nkStrLit, info, t) result = newNodeIT(nkStrLit, info, t)
result.strVal = "" result.strVal = ""
of tyVar, tyLent, tyPointer, tyPtr, tySequence, tyExpr, of tyVar, tyLent, tyPointer, tyPtr, tyExpr,
tyStmt, tyTypeDesc, tyStatic, tyRef, tyNil: tyStmt, tyTypeDesc, tyStatic, tyRef, tyNil:
result = newNodeIT(nkNilLit, info, t) result = newNodeIT(nkNilLit, info, t)
of tyProc: of tyProc:
@ -1585,6 +1585,8 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
result = newNodeIT(nkCurly, info, t) result = newNodeIT(nkCurly, info, t)
of tyOpt: of tyOpt:
result = newNodeIT(nkNilLit, info, t) result = newNodeIT(nkNilLit, info, t)
of tySequence:
result = newNodeIT(nkBracket, info, t)
else: else:
globalError(info, "cannot create null element for: " & $t.kind) globalError(info, "cannot create null element for: " & $t.kind)

View file

@ -6298,6 +6298,9 @@ modules don't need to import a module's dependencies:
var x: MyObject var x: MyObject
echo $x echo $x
When the exported symbol is another module, all of its definitions will
be forwarded. You can use an ``except`` list to exclude some of the symbols.
Note on paths Note on paths
----------- -----------
In module related statements, if any part of the module name / In module related statements, if any part of the module name /
@ -7798,8 +7801,9 @@ Future directions:
Threadvar pragma Threadvar pragma
---------------- ----------------
A global variable can be marked with the ``threadvar`` pragma; it is A variable can be marked with the ``threadvar`` pragma, which makes it a
a `thread-local`:idx: variable then: `thread-local`:idx: variable; Additionally, this implies all the effects
of the ``global`` pragma.
.. code-block:: nim .. code-block:: nim
var checkpoints* {.threadvar.}: seq[string] var checkpoints* {.threadvar.}: seq[string]

View file

@ -252,7 +252,7 @@ proc xz(args: string) =
proc buildTool(toolname, args: string) = proc buildTool(toolname, args: string) =
nimexec("cc $# $#" % [args, toolname]) nimexec("cc $# $#" % [args, toolname])
copyFile(dest="bin"/ splitFile(toolname).name.exe, source=toolname.exe) copyFile(dest="bin" / splitFile(toolname).name.exe, source=toolname.exe)
proc buildTools(latest: bool) = proc buildTools(latest: bool) =
let nimsugExe = "bin/nimsuggest".exe let nimsugExe = "bin/nimsuggest".exe

View file

@ -385,7 +385,7 @@ type
{.deprecated: [TBindSymRule: BindSymRule].} {.deprecated: [TBindSymRule: BindSymRule].}
proc bindSym*(ident: string, rule: BindSymRule = brClosed): NimNode {. proc bindSym*(ident: static[string], rule: BindSymRule = brClosed): NimNode {.
magic: "NBindSym", noSideEffect.} magic: "NBindSym", noSideEffect.}
## creates a node that binds `ident` to a symbol node. The bound symbol ## creates a node that binds `ident` to a symbol node. The bound symbol
## may be an overloaded symbol. ## may be an overloaded symbol.

View file

@ -12,7 +12,7 @@ import sockets, strutils, parseutils, times, os, asyncio
from asyncnet import nil from asyncnet import nil
from nativesockets import nil from nativesockets import nil
from asyncdispatch import PFuture from asyncdispatch import Future
## **Note**: This module is deprecated since version 0.11.3. ## **Note**: This module is deprecated since version 0.11.3.
## You should use the async version of this module ## You should use the async version of this module
## `asyncftpclient <asyncftpclient.html>`_. ## `asyncftpclient <asyncftpclient.html>`_.

View file

@ -853,7 +853,6 @@ type
DirKind = enum # must be ordered alphabetically! DirKind = enum # must be ordered alphabetically!
dkNone, dkAuthor, dkAuthors, dkCode, dkCodeBlock, dkContainer, dkContents, dkNone, dkAuthor, dkAuthors, dkCode, dkCodeBlock, dkContainer, dkContents,
dkFigure, dkImage, dkInclude, dkIndex, dkRaw, dkTitle dkFigure, dkImage, dkInclude, dkIndex, dkRaw, dkTitle
{.deprecated: [TDirKind: DirKind].}
const const
DirIds: array[0..12, string] = ["", "author", "authors", "code", DirIds: array[0..12, string] = ["", "author", "authors", "code",
@ -1114,7 +1113,6 @@ proc parseHeadline(p: var RstParser): PRstNode =
type type
IntSeq = seq[int] IntSeq = seq[int]
{.deprecated: [TIntSeq: IntSeq].}
proc tokEnd(p: RstParser): int = proc tokEnd(p: RstParser): int =
result = p.tok[p.idx].col + len(p.tok[p.idx].symbol) - 1 result = p.tok[p.idx].col + len(p.tok[p.idx].symbol) - 1
@ -1408,8 +1406,6 @@ type
hasArg, hasOptions, argIsFile, argIsWord hasArg, hasOptions, argIsFile, argIsWord
DirFlags = set[DirFlag] DirFlags = set[DirFlag]
SectionParser = proc (p: var RstParser): PRstNode {.nimcall.} SectionParser = proc (p: var RstParser): PRstNode {.nimcall.}
{.deprecated: [TDirFlag: DirFlag, TDirFlags: DirFlags,
TSectionParser: SectionParser].}
proc parseDirective(p: var RstParser, flags: DirFlags): PRstNode = proc parseDirective(p: var RstParser, flags: DirFlags): PRstNode =
## Parses arguments and options for a directive block. ## Parses arguments and options for a directive block.

View file

@ -70,8 +70,6 @@ type
## the document or the section ## the document or the section
level*: int ## valid for some node kinds level*: int ## valid for some node kinds
sons*: RstNodeSeq ## the node's sons sons*: RstNodeSeq ## the node's sons
{.deprecated: [TRstNodeKind: RstNodeKind, TRstNodeSeq: RstNodeSeq,
TRstNode: RstNode].}
proc len*(n: PRstNode): int = proc len*(n: PRstNode): int =
result = len(n.sons) result = len(n.sons)
@ -99,7 +97,6 @@ type
RenderContext {.pure.} = object RenderContext {.pure.} = object
indent: int indent: int
verbatim: int verbatim: int
{.deprecated: [TRenderContext: RenderContext].}
proc renderRstToRst(d: var RenderContext, n: PRstNode, proc renderRstToRst(d: var RenderContext, n: PRstNode,
result: var string) {.gcsafe.} result: var string) {.gcsafe.}

View file

@ -13,9 +13,6 @@ type
SortOrder* = enum ## sort order SortOrder* = enum ## sort order
Descending, Ascending Descending, Ascending
{.deprecated: [TSortOrder: SortOrder].}
proc `*`*(x: int, order: SortOrder): int {.inline.} = proc `*`*(x: int, order: SortOrder): int {.inline.} =
## flips `x` if ``order == Descending``; ## flips `x` if ``order == Descending``;
## if ``order == Ascending`` then `x` is returned. ## if ``order == Ascending`` then `x` is returned.
@ -69,6 +66,15 @@ proc reversed*[T](a: openArray[T]): seq[T] =
proc binarySearch*[T](a: openArray[T], key: T): int = proc binarySearch*[T](a: openArray[T], key: T): int =
## binary search for `key` in `a`. Returns -1 if not found. ## binary search for `key` in `a`. Returns -1 if not found.
if ((a.len - 1) and a.len) == 0 and a.len > 0:
# when `a.len` is a power of 2, a faster div can be used.
var step = a.len div 2
while step > 0:
if a[result or step] <= key:
result = result or step
step = step shr 1
if a[result] != key: result = -1
else:
var b = len(a) var b = len(a)
while result < b: while result < b:
var mid = (result + b) div 2 var mid = (result + b) div 2
@ -76,14 +82,9 @@ proc binarySearch*[T](a: openArray[T], key: T): int =
else: b = mid else: b = mid
if result >= len(a) or a[result] != key: result = -1 if result >= len(a) or a[result] != key: result = -1
proc smartBinarySearch*[T](a: openArray[T], key: T): int = proc smartBinarySearch*[T](a: openArray[T], key: T): int {.deprecated.} =
## ``a.len`` must be a power of 2 for this to work. ## **Deprecated since version 0.18.1**; Use ``binarySearch`` instead.
var step = a.len div 2 binarySearch(a,key)
while step > 0:
if a[result or step] <= key:
result = result or step
step = step shr 1
if a[result] != key: result = -1
const const
onlySafeCode = true onlySafeCode = true
@ -363,10 +364,11 @@ when isMainModule:
var srt1 = [1,2,3,4,4,4,4,5] var srt1 = [1,2,3,4,4,4,4,5]
var srt2 = ["iello","hello"] var srt2 = ["iello","hello"]
var srt3 = [1.0,1.0,1.0] var srt3 = [1.0,1.0,1.0]
var srt4: seq[int] = @[] var srt4: seq[int]
assert srt1.isSorted(cmp) == true assert srt1.isSorted(cmp) == true
assert srt2.isSorted(cmp) == false assert srt2.isSorted(cmp) == false
assert srt3.isSorted(cmp) == true assert srt3.isSorted(cmp) == true
assert srt4.isSorted(cmp) == true
var srtseq = newSeq[int]() var srtseq = newSeq[int]()
assert srtseq.isSorted(cmp) == true assert srtseq.isSorted(cmp) == true
# Tests for reversed # Tests for reversed
@ -515,3 +517,23 @@ when isMainModule:
block fillEmptySeq: block fillEmptySeq:
var s = newSeq[int]() var s = newSeq[int]()
s.fill(0) s.fill(0)
block testBinarySearch:
var noData: seq[int]
doAssert binarySearch(noData, 7) == -1
let oneData = @[1]
doAssert binarySearch(oneData, 1) == 0
doAssert binarySearch(onedata, 7) == -1
let someData = @[1,3,4,7]
doAssert binarySearch(someData, 1) == 0
doAssert binarySearch(somedata, 7) == 3
doAssert binarySearch(someData, -1) == -1
doAssert binarySearch(someData, 5) == -1
doAssert binarySearch(someData, 13) == -1
let moreData = @[1,3,5,7,4711]
doAssert binarySearch(moreData, -1) == -1
doAssert binarySearch(moreData, 1) == 0
doAssert binarySearch(moreData, 5) == 2
doAssert binarySearch(moreData, 6) == -1
doAssert binarySearch(moreData, 4711) == 4
doAssert binarySearch(moreData, 4712) == -1

View file

@ -27,8 +27,6 @@ type
FutureError* = object of Exception FutureError* = object of Exception
cause*: FutureBase cause*: FutureBase
{.deprecated: [PFutureBase: FutureBase, PFuture: Future].}
when not defined(release): when not defined(release):
var currentID = 0 var currentID = 0

View file

@ -60,9 +60,6 @@ type
reusePort: bool reusePort: bool
maxBody: int ## The maximum content-length that will be read for the body. maxBody: int ## The maximum content-length that will be read for the body.
{.deprecated: [TRequest: Request, PAsyncHttpServer: AsyncHttpServer,
THttpCode: HttpCode, THttpVersion: HttpVersion].}
proc newAsyncHttpServer*(reuseAddr = true, reusePort = false, proc newAsyncHttpServer*(reuseAddr = true, reusePort = false,
maxBody = 8388608): AsyncHttpServer = maxBody = 8388608): AsyncHttpServer =
## Creates a new ``AsyncHttpServer`` instance. ## Creates a new ``AsyncHttpServer`` instance.

View file

@ -134,8 +134,6 @@ type
protocol: Protocol protocol: Protocol
AsyncSocket* = ref AsyncSocketDesc AsyncSocket* = ref AsyncSocketDesc
{.deprecated: [PAsyncSocket: AsyncSocket].}
proc newAsyncSocket*(fd: AsyncFD, domain: Domain = AF_INET, proc newAsyncSocket*(fd: AsyncFD, domain: Domain = AF_INET,
sockType: SockType = SOCK_STREAM, sockType: SockType = SOCK_STREAM,
protocol: Protocol = IPPROTO_TCP, buffered = true): AsyncSocket = protocol: Protocol = IPPROTO_TCP, buffered = true): AsyncSocket =

View file

@ -64,8 +64,6 @@ type
methodPost, ## query uses the POST method methodPost, ## query uses the POST method
methodGet ## query uses the GET method methodGet ## query uses the GET method
{.deprecated: [TRequestMethod: RequestMethod, ECgi: CgiError].}
proc cgiError*(msg: string) {.noreturn.} = proc cgiError*(msg: string) {.noreturn.} =
## raises an ECgi exception with message `msg`. ## raises an ECgi exception with message `msg`.
var e: ref CgiError var e: ref CgiError

View file

@ -120,6 +120,13 @@ iterator items*[A](s: HashSet[A]): A =
for h in 0..high(s.data): for h in 0..high(s.data):
if isFilled(s.data[h].hcode): yield s.data[h].key if isFilled(s.data[h].hcode): yield s.data[h].key
proc hash*[A](s: HashSet[A]): Hash =
## hashing of HashSet
assert s.isValid, "The set needs to be initialized."
for h in 0..high(s.data):
result = result xor s.data[h].hcode
result = !$result
const const
growthFactor = 2 growthFactor = 2
@ -690,6 +697,13 @@ iterator items*[A](s: OrderedSet[A]): A =
forAllOrderedPairs: forAllOrderedPairs:
yield s.data[h].key yield s.data[h].key
proc hash*[A](s: OrderedSet[A]): Hash =
## hashing of OrderedSet
assert s.isValid, "The set needs to be initialized."
forAllOrderedPairs:
result = result !& s.data[h].hcode
result = !$result
iterator pairs*[A](s: OrderedSet[A]): tuple[a: int, b: A] = iterator pairs*[A](s: OrderedSet[A]): tuple[a: int, b: A] =
assert s.isValid, "The set needs to be initialized" assert s.isValid, "The set needs to be initialized"
forAllOrderedPairs: forAllOrderedPairs:

View file

@ -14,8 +14,6 @@ import strutils
type type
Color* = distinct int ## a color stored as RGB Color* = distinct int ## a color stored as RGB
{.deprecated: [TColor: Color].}
proc `==` *(a, b: Color): bool {.borrow.} proc `==` *(a, b: Color): bool {.borrow.}
## compares two colors. ## compares two colors.

View file

@ -25,8 +25,6 @@ type
Complex* = tuple[re, im: float] Complex* = tuple[re, im: float]
## a complex number, consisting of a real and an imaginary part ## a complex number, consisting of a real and an imaginary part
{.deprecated: [TComplex: Complex].}
proc toComplex*(x: SomeInteger): Complex = proc toComplex*(x: SomeInteger): Complex =
## Convert some integer ``x`` to a complex number. ## Convert some integer ``x`` to a complex number.
result.re = x result.re = x

View file

@ -83,9 +83,6 @@ type
foreignKey*: bool ## is this a foreign key? foreignKey*: bool ## is this a foreign key?
DbColumns* = seq[DbColumn] DbColumns* = seq[DbColumn]
{.deprecated: [EDb: DbError, TSqlQuery: SqlQuery, FDb: DbEffect,
FReadDb: ReadDbEffect, FWriteDb: WriteDbEffect].}
template sql*(query: string): SqlQuery = template sql*(query: string): SqlQuery =
## constructs a SqlQuery from the string `query`. This is supposed to be ## constructs a SqlQuery from the string `query`. This is supposed to be
## used as a raw-string-literal modifier: ## used as a raw-string-literal modifier:

View file

@ -59,8 +59,6 @@ import strutils
type type
LibHandle* = pointer ## a handle to a dynamically loaded library LibHandle* = pointer ## a handle to a dynamically loaded library
{.deprecated: [TLibHandle: LibHandle].}
proc loadLib*(path: string, global_symbols=false): LibHandle {.gcsafe.} proc loadLib*(path: string, global_symbols=false): LibHandle {.gcsafe.}
## loads a library from `path`. Returns nil if the library could not ## loads a library from `path`. Returns nil if the library could not
## be loaded. ## be loaded.

View file

@ -27,8 +27,6 @@ type
EncodingError* = object of ValueError ## exception that is raised EncodingError* = object of ValueError ## exception that is raised
## for encoding errors ## for encoding errors
{.deprecated: [EInvalidEncoding: EncodingError, PConverter: EncodingConverter].}
when defined(windows): when defined(windows):
proc eqEncodingNames(a, b: string): bool = proc eqEncodingNames(a, b: string): bool =
var i = 0 var i = 0

View file

@ -43,9 +43,6 @@ type
s: seq[EventHandler] s: seq[EventHandler]
EventError* = object of ValueError EventError* = object of ValueError
{.deprecated: [TEventArgs: EventArgs, TEventHandler: EventHandler,
TEventEmitter: EventEmitter, EInvalidEvent: EventError].}
proc initEventHandler*(name: string): EventHandler = proc initEventHandler*(name: string): EventHandler =
## Initializes an EventHandler with the specified name and returns it. ## Initializes an EventHandler with the specified name and returns it.
result.handlers = @[] result.handlers = @[]

View file

@ -45,7 +45,6 @@ type
Hash* = int ## a hash value; hash tables using these values should Hash* = int ## a hash value; hash tables using these values should
## always have a size of a power of two and can use the ``and`` ## always have a size of a power of two and can use the ``and``
## operator instead of ``mod`` for truncation of the hash value. ## operator instead of ``mod`` for truncation of the hash value.
{.deprecated: [THash: Hash].}
proc `!&`*(h: Hash, val: int): Hash {.inline.} = proc `!&`*(h: Hash, val: int): Hash {.inline.} =
## mixes a hash value `h` with `val` to produce a new hash value. This is ## mixes a hash value `h` with `val` to produce a new hash value. This is

View file

@ -178,7 +178,6 @@ type
tagVar, ## the HTML ``var`` element tagVar, ## the HTML ``var`` element
tagVideo, ## the HTML ``video`` element tagVideo, ## the HTML ``video`` element
tagWbr ## the HTML ``wbr`` element tagWbr ## the HTML ``wbr`` element
{.deprecated: [THtmlTag: HtmlTag].}
const const
tagToStr* = [ tagToStr* = [

View file

@ -219,10 +219,6 @@ type
## and ``postContent`` proc, ## and ``postContent`` proc,
## when the server returns an error ## when the server returns an error
{.deprecated: [TResponse: Response, PProxy: Proxy,
EInvalidProtocol: ProtocolError, EHttpRequestErr: HttpRequestError
].}
const defUserAgent* = "Nim httpclient/" & NimVersion const defUserAgent* = "Nim httpclient/" & NimVersion
proc httpError(msg: string) = proc httpError(msg: string) =
@ -362,8 +358,6 @@ proc parseResponse(s: Socket, getBody: bool, timeout: int): Response =
else: else:
result.body = "" result.body = ""
{.deprecated: [THttpMethod: HttpMethod].}
when not defined(ssl): when not defined(ssl):
type SSLContext = ref object type SSLContext = ref object
var defaultSSLContext {.threadvar.}: SSLContext var defaultSSLContext {.threadvar.}: SSLContext
@ -585,7 +579,7 @@ proc request*(url: string, httpMethod: string, extraHeaders = "",
result = parseResponse(s, httpMethod != "HEAD", timeout) result = parseResponse(s, httpMethod != "HEAD", timeout)
proc request*(url: string, httpMethod = httpGET, extraHeaders = "", 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
{.deprecated.} = {.deprecated.} =
@ -627,13 +621,13 @@ proc get*(url: string, extraHeaders = "", maxRedirects = 5,
## server takes longer than specified an ETimeout exception will be raised. ## server takes longer than specified an ETimeout exception will be raised.
## ##
## **Deprecated since version 0.15.0**: use ``HttpClient.get`` instead. ## **Deprecated since version 0.15.0**: use ``HttpClient.get`` instead.
result = request(url, httpGET, extraHeaders, "", sslContext, timeout, result = request(url, HttpGET, extraHeaders, "", sslContext, timeout,
userAgent, proxy) userAgent, proxy)
var lastURL = url var lastURL = url
for i in 1..maxRedirects: for i in 1..maxRedirects:
if result.status.redirection(): if result.status.redirection():
let redirectTo = getNewLocation(lastURL, result.headers) let redirectTo = getNewLocation(lastURL, result.headers)
result = request(redirectTo, httpGET, extraHeaders, "", sslContext, result = request(redirectTo, HttpGET, extraHeaders, "", sslContext,
timeout, userAgent, proxy) timeout, userAgent, proxy)
lastURL = redirectTo lastURL = redirectTo
@ -687,13 +681,13 @@ proc post*(url: string, extraHeaders = "", body = "",
if not multipart.isNil: if not multipart.isNil:
xh.add(withNewLine("Content-Type: " & mpContentType)) xh.add(withNewLine("Content-Type: " & mpContentType))
result = request(url, httpPOST, xh, xb, sslContext, timeout, userAgent, result = request(url, HttpPOST, xh, xb, sslContext, timeout, userAgent,
proxy) proxy)
var lastURL = url var lastURL = url
for i in 1..maxRedirects: for i in 1..maxRedirects:
if result.status.redirection(): if result.status.redirection():
let redirectTo = getNewLocation(lastURL, result.headers) let redirectTo = getNewLocation(lastURL, result.headers)
var meth = if result.status != "307": httpGet else: httpPost var meth = if result.status != "307": HttpGet else: HttpPost
result = request(redirectTo, meth, xh, xb, sslContext, timeout, result = request(redirectTo, meth, xh, xb, sslContext, timeout,
userAgent, proxy) userAgent, proxy)
lastURL = redirectTo lastURL = redirectTo
@ -749,7 +743,7 @@ proc generateHeaders(requestUrl: Uri, httpMethod: string,
if proxy.isNil or requestUrl.scheme == "https": if proxy.isNil or requestUrl.scheme == "https":
# /path?query # /path?query
if requestUrl.path[0] != '/': result.add '/' if not requestUrl.path.startsWith("/"): result.add '/'
result.add(requestUrl.path) result.add(requestUrl.path)
if requestUrl.query.len > 0: if requestUrl.query.len > 0:
result.add("?" & requestUrl.query) result.add("?" & requestUrl.query)

View file

@ -45,10 +45,6 @@ type
## TCP/IP tunnel, usually used for proxies. ## TCP/IP tunnel, usually used for proxies.
HttpPatch ## Applies partial modifications to a resource. HttpPatch ## Applies partial modifications to a resource.
{.deprecated: [httpGet: HttpGet, httpHead: HttpHead, httpPost: HttpPost,
httpPut: HttpPut, httpDelete: HttpDelete, httpTrace: HttpTrace,
httpOptions: HttpOptions, httpConnect: HttpConnect].}
const const
Http100* = HttpCode(100) Http100* = HttpCode(100)

View file

@ -110,7 +110,6 @@ when false:
# TODO: Fix this, or get rid of it. # TODO: Fix this, or get rid of it.
type type
RequestMethod = enum reqGet, reqPost RequestMethod = enum reqGet, reqPost
{.deprecated: [TRequestMethod: RequestMethod].}
proc executeCgi(client: Socket, path, query: string, meth: RequestMethod) = proc executeCgi(client: Socket, path, query: string, meth: RequestMethod) =
var env = newStringTable(modeCaseInsensitive) var env = newStringTable(modeCaseInsensitive)
@ -225,7 +224,6 @@ type
PAsyncHTTPServer* = ref AsyncHTTPServer PAsyncHTTPServer* = ref AsyncHTTPServer
AsyncHTTPServer = object of Server AsyncHTTPServer = object of Server
asyncSocket: AsyncSocket asyncSocket: AsyncSocket
{.deprecated: [TAsyncHTTPServer: AsyncHTTPServer, TServer: Server].}
proc open*(s: var Server, port = Port(80), reuseAddr = false) = proc open*(s: var Server, port = Port(80), reuseAddr = false) =
## creates a new server at port `port`. If ``port == 0`` a free port is ## creates a new server at port `port`. If ``port == 0`` a free port is

View file

@ -18,13 +18,13 @@ proc createAsyncNativeSocket*(domain: Domain = Domain.AF_INET,
createAsyncNativeSocketImpl(domain, sockType, protocol) createAsyncNativeSocketImpl(domain, sockType, protocol)
proc newAsyncNativeSocket*(domain: cint, sockType: cint, proc newAsyncNativeSocket*(domain: cint, sockType: cint,
protocol: cint): AsyncFD {.deprecated.} = protocol: cint): AsyncFD {.deprecated: "use createAsyncNativeSocket instead".} =
createAsyncNativeSocketImpl(domain, sockType, protocol) createAsyncNativeSocketImpl(domain, sockType, protocol)
proc newAsyncNativeSocket*(domain: Domain = Domain.AF_INET, proc newAsyncNativeSocket*(domain: Domain = Domain.AF_INET,
sockType: SockType = SOCK_STREAM, sockType: SockType = SOCK_STREAM,
protocol: Protocol = IPPROTO_TCP): AsyncFD protocol: Protocol = IPPROTO_TCP): AsyncFD
{.deprecated.} = {.deprecated: "use createAsyncNativeSocket instead".} =
createAsyncNativeSocketImpl(domain, sockType, protocol) createAsyncNativeSocketImpl(domain, sockType, protocol)
when defined(windows) or defined(nimdoc): when defined(windows) or defined(nimdoc):

View file

@ -12,50 +12,6 @@ when not defined(nimscript):
when defined(windows): when defined(windows):
import winlean import winlean
proc osErrorMsg*(): string {.rtl, extern: "nos$1", deprecated.} =
## Retrieves the operating system's error flag, ``errno``.
## On Windows ``GetLastError`` is checked before ``errno``.
## Returns "" if no error occurred.
##
## **Deprecated since version 0.9.4**: use the other ``osErrorMsg`` proc.
result = ""
when defined(Windows) and not defined(nimscript):
var err = getLastError()
if err != 0'i32:
when useWinUnicode:
var msgbuf: WideCString
if formatMessageW(0x00000100 or 0x00001000 or 0x00000200 or 0x000000FF,
nil, err, 0, addr(msgbuf), 0, nil) != 0'i32:
result = $msgbuf
if msgbuf != nil: localFree(cast[pointer](msgbuf))
else:
var msgbuf: cstring
if formatMessageA(0x00000100 or 0x00001000 or 0x00000200 or 0x000000FF,
nil, err, 0, addr(msgbuf), 0, nil) != 0'i32:
result = $msgbuf
if msgbuf != nil: localFree(msgbuf)
when not defined(nimscript):
if errno != 0'i32:
result = $c_strerror(errno)
{.push warning[deprecated]: off.}
proc raiseOSError*(msg: string = "") {.noinline, rtl, extern: "nos$1",
deprecated.} =
## raises an OSError exception with the given message ``msg``.
## If ``msg == ""``, the operating system's error flag
## (``errno``) is converted to a readable error message. On Windows
## ``GetLastError`` is checked before ``errno``.
## If no error flag is set, the message ``unknown OS error`` is used.
##
## **Deprecated since version 0.9.4**: use the other ``raiseOSError`` proc.
if len(msg) == 0:
var m = osErrorMsg()
raise newException(OSError, if m.len > 0: m else: "unknown OS error")
else:
raise newException(OSError, msg)
{.pop.}
proc `==`*(err1, err2: OSErrorCode): bool {.borrow.} proc `==`*(err1, err2: OSErrorCode): bool {.borrow.}
proc `$`*(err: OSErrorCode): string {.borrow.} proc `$`*(err: OSErrorCode): string {.borrow.}

View file

@ -158,9 +158,6 @@ type
JsonKindError* = object of ValueError ## raised by the ``to`` macro if the JsonKindError* = object of ValueError ## raised by the ``to`` macro if the
## JSON kind is incorrect. ## JSON kind is incorrect.
{.deprecated: [TJsonEventKind: JsonEventKind, TJsonError: JsonError,
TJsonParser: JsonParser, TTokKind: TokKind].}
const const
errorMessages: array[JsonError, string] = [ errorMessages: array[JsonError, string] = [
"no error", "no error",
@ -622,9 +619,6 @@ type
JsonParsingError* = object of ValueError ## is raised for a JSON error JsonParsingError* = object of ValueError ## is raised for a JSON error
{.deprecated: [EJsonParsingError: JsonParsingError, TJsonNode: JsonNodeObj,
PJsonNode: JsonNode, TJsonNodeKind: JsonNodeKind].}
proc raiseParseErr*(p: JsonParser, msg: string) {.noinline, noreturn.} = proc raiseParseErr*(p: JsonParser, msg: string) {.noinline, noreturn.} =
## raises an `EJsonParsingError` exception. ## raises an `EJsonParsingError` exception.
raise newException(JsonParsingError, errorMsgExpected(p, msg)) raise newException(JsonParsingError, errorMsgExpected(p, msg))
@ -695,7 +689,7 @@ proc getBiggestInt*(n: JsonNode, default: BiggestInt = 0): BiggestInt =
if n.isNil or n.kind != JInt: return default if n.isNil or n.kind != JInt: return default
else: return n.num else: return n.num
proc getNum*(n: JsonNode, default: BiggestInt = 0): BiggestInt {.deprecated.} = proc getNum*(n: JsonNode, default: BiggestInt = 0): BiggestInt {.deprecated: "use getInt or getBiggestInt instead".} =
## **Deprecated since v0.18.2:** use ``getInt`` or ``getBiggestInt`` instead. ## **Deprecated since v0.18.2:** use ``getInt`` or ``getBiggestInt`` instead.
getBiggestInt(n, default) getBiggestInt(n, default)
@ -709,7 +703,7 @@ proc getFloat*(n: JsonNode, default: float = 0.0): float =
of JInt: return float(n.num) of JInt: return float(n.num)
else: return default else: return default
proc getFNum*(n: JsonNode, default: float = 0.0): float {.deprecated.} = proc getFNum*(n: JsonNode, default: float = 0.0): float {.deprecated: "use getFloat instead".} =
## **Deprecated since v0.18.2:** use ``getFloat`` instead. ## **Deprecated since v0.18.2:** use ``getFloat`` instead.
getFloat(n, default) getFloat(n, default)
@ -720,7 +714,7 @@ proc getBool*(n: JsonNode, default: bool = false): bool =
if n.isNil or n.kind != JBool: return default if n.isNil or n.kind != JBool: return default
else: return n.bval else: return n.bval
proc getBVal*(n: JsonNode, default: bool = false): bool {.deprecated.} = proc getBVal*(n: JsonNode, default: bool = false): bool {.deprecated: "use getBool instead".} =
## **Deprecated since v0.18.2:** use ``getBool`` instead. ## **Deprecated since v0.18.2:** use ``getBool`` instead.
getBool(n, default) getBool(n, default)
@ -946,7 +940,7 @@ proc contains*(node: JsonNode, val: JsonNode): bool =
assert(node.kind == JArray) assert(node.kind == JArray)
find(node.elems, val) >= 0 find(node.elems, val) >= 0
proc existsKey*(node: JsonNode, key: string): bool {.deprecated.} = node.hasKey(key) proc existsKey*(node: JsonNode, key: string): bool {.deprecated: "use hasKey instead".} = node.hasKey(key)
## **Deprecated:** use `hasKey` instead. ## **Deprecated:** use `hasKey` instead.
proc `[]=`*(obj: JsonNode, key: string, val: JsonNode) {.inline.} = proc `[]=`*(obj: JsonNode, key: string, val: JsonNode) {.inline.} =
@ -1277,7 +1271,6 @@ else:
from math import `mod` from math import `mod`
type type
JSObject = object JSObject = object
{.deprecated: [TJSObject: JSObject].}
proc parseNativeJson(x: cstring): JSObject {.importc: "JSON.parse".} proc parseNativeJson(x: cstring): JSObject {.importc: "JSON.parse".}

View file

@ -40,8 +40,6 @@ type
offsetBase*: int # use ``offsetBase + bufpos`` to get the offset offsetBase*: int # use ``offsetBase + bufpos`` to get the offset
refillChars: set[char] refillChars: set[char]
{.deprecated: [TBaseLexer: BaseLexer].}
const const
chrSize = sizeof(char) chrSize = sizeof(char)

View file

@ -96,10 +96,6 @@ when not defined(js):
logFiles: int # how many log files already created, e.g. basename.1, basename.2... logFiles: int # how many log files already created, e.g. basename.1, basename.2...
bufSize: int # size of output buffer (-1: use system defaults, 0: unbuffered, >0: fixed buffer size) bufSize: int # size of output buffer (-1: use system defaults, 0: unbuffered, >0: fixed buffer size)
{.deprecated: [PFileLogger: FileLogger, PRollingFileLogger: RollingFileLogger].}
{.deprecated: [TLevel: Level, PLogger: Logger, PConsoleLogger: ConsoleLogger].}
var var
level {.threadvar.}: Level ## global log filter level {.threadvar.}: Level ## global log filter
handlers {.threadvar.}: seq[Logger] ## handlers with their own log levels handlers {.threadvar.}: seq[Logger] ## handlers with their own log levels

View file

@ -309,7 +309,6 @@ when not defined(testing) and isMainModule:
Node = object Node = object
next, prev: PNode next, prev: PNode
data: string data: string
{.deprecated: [TNode: Node].}
proc buildList(): PNode = proc buildList(): PNode =
new(result) new(result)

View file

@ -29,11 +29,21 @@ proc binom*(n, k: int): int {.noSideEffect.} =
for i in countup(2, k): for i in countup(2, k):
result = (result * (n + 1 - i)) div i result = (result * (n + 1 - i)) div i
proc fac*(n: int): int {.noSideEffect.} = proc createFactTable[N: static[int]]: array[N, int] =
result[0] = 1
for i in 1 ..< N:
result[i] = result[i - 1] * i
proc fac*(n: int): int =
## Computes the faculty/factorial function. ## Computes the faculty/factorial function.
result = 1 const factTable =
for i in countup(2, n): when sizeof(int) == 4:
result = result * i createFactTable[13]()
else:
createFactTable[21]()
assert(n > 0, $n & " must not be negative.")
assert(n < factTable.len, $n & " is too large to look up in the table")
factTable[n]
{.push checks:off, line_dir:off, stack_trace:off.} {.push checks:off, line_dir:off, stack_trace:off.}

View file

@ -38,8 +38,6 @@ type
else: else:
handle: cint handle: cint
{.deprecated: [TMemFile: MemFile].}
proc mapMem*(m: var MemFile, mode: FileMode = fmRead, proc mapMem*(m: var MemFile, mode: FileMode = fmRead,
mappedSize = -1, offset = 0): pointer = mappedSize = -1, offset = 0): pointer =
## returns a pointer to a mapped portion of MemFile `m` ## returns a pointer to a mapped portion of MemFile `m`

View file

@ -12,8 +12,6 @@ type
mt: array[0..623, uint32] mt: array[0..623, uint32]
index: int index: int
{.deprecated: [TMersenneTwister: MersenneTwister].}
proc newMersenneTwister*(seed: uint32): MersenneTwister = proc newMersenneTwister*(seed: uint32): MersenneTwister =
result.index = 0 result.index = 0
result.mt[0] = seed result.mt[0] = seed

View file

@ -13,8 +13,6 @@ type
MimeDB* = object MimeDB* = object
mimes: StringTableRef mimes: StringTableRef
{.deprecated: [TMimeDB: MimeDB].}
const mimes* = { const mimes* = {
"ez": "application/andrew-inset", "ez": "application/andrew-inset",
"anx": "application/annodex", "anx": "application/annodex",

View file

@ -85,9 +85,6 @@ type
length*: int length*: int
addrList*: seq[string] addrList*: seq[string]
{.deprecated: [TPort: Port, TDomain: Domain, TType: SockType,
TProtocol: Protocol, TServent: Servent, THostent: Hostent].}
when useWinVersion: when useWinVersion:
let let
osInvalidSocket* = winlean.INVALID_SOCKET osInvalidSocket* = winlean.INVALID_SOCKET
@ -640,7 +637,7 @@ proc pruneSocketSet(s: var seq[SocketHandle], fd: var TFdSet) =
inc(i) inc(i)
setLen(s, L) setLen(s, L)
proc select*(readfds: var seq[SocketHandle], timeout = 500): int {.deprecated.} = proc select*(readfds: var seq[SocketHandle], timeout = 500): int {.deprecated: "use selectRead instead".} =
## When a socket in ``readfds`` is ready to be read from then a non-zero ## When a socket in ``readfds`` is ready to be read from then a non-zero
## value will be returned specifying the count of the sockets which can be ## value will be returned specifying the count of the sockets which can be
## read from. The sockets which can be read from will also be removed ## read from. The sockets which can be read from will also be removed

View file

@ -110,9 +110,6 @@ when defineSsl:
serverGetPskFunc: SslServerGetPskFunc serverGetPskFunc: SslServerGetPskFunc
clientGetPskFunc: SslClientGetPskFunc clientGetPskFunc: SslClientGetPskFunc
{.deprecated: [ESSL: SSLError, TSSLCVerifyMode: SSLCVerifyMode,
TSSLProtVersion: SSLProtVersion, PSSLContext: SSLContext,
TSSLAcceptResult: SSLAcceptResult].}
else: else:
type type
SslContext* = void # TODO: Workaround #4797. SslContext* = void # TODO: Workaround #4797.
@ -159,10 +156,6 @@ type
Peek, Peek,
SafeDisconn ## Ensures disconnection exceptions (ECONNRESET, EPIPE etc) are not thrown. SafeDisconn ## Ensures disconnection exceptions (ECONNRESET, EPIPE etc) are not thrown.
{.deprecated: [TSocketFlags: SocketFlag, ETimeout: TimeoutError,
TReadLineResult: ReadLineResult, TSOBool: SOBool, PSocket: Socket,
TSocketImpl: SocketImpl].}
type type
IpAddressFamily* {.pure.} = enum ## Describes the type of an IP address IpAddressFamily* {.pure.} = enum ## Describes the type of an IP address
IPv6, ## IPv6 address IPv6, ## IPv6 address
@ -176,8 +169,6 @@ type
of IpAddressFamily.IPv4: of IpAddressFamily.IPv4:
address_v4*: array[0..3, uint8] ## Contains the IP address in bytes in address_v4*: array[0..3, uint8] ## Contains the IP address in bytes in
## case of IPv4 ## case of IPv4
{.deprecated: [TIpAddress: IpAddress].}
proc socketError*(socket: Socket, err: int = -1, async = false, proc socketError*(socket: Socket, err: int = -1, async = false,
lastError = (-1).OSErrorCode): void {.gcsafe.} lastError = (-1).OSErrorCode): void {.gcsafe.}
@ -969,7 +960,7 @@ when defined(posix) and not defined(nimdoc):
raise newException(ValueError, "socket path too long") raise newException(ValueError, "socket path too long")
copyMem(addr result.sun_path, path.cstring, path.len + 1) copyMem(addr result.sun_path, path.cstring, path.len + 1)
when defined(posix): when defined(posix) or defined(nimdoc):
proc connectUnix*(socket: Socket, path: string) = proc connectUnix*(socket: Socket, path: string) =
## Connects to Unix socket on `path`. ## Connects to Unix socket on `path`.
## This only works on Unix-style systems: Mac OS X, BSD and Linux ## This only works on Unix-style systems: Mac OS X, BSD and Linux

View file

@ -30,7 +30,6 @@ when not declared(system.StackTrace):
type StackTrace = object type StackTrace = object
lines: array[0..20, cstring] lines: array[0..20, cstring]
files: array[0..20, cstring] files: array[0..20, cstring]
{.deprecated: [TStackTrace: StackTrace].}
proc `[]`*(st: StackTrace, i: int): cstring = st.lines[i] proc `[]`*(st: StackTrace, i: int): cstring = st.lines[i]
# We use a simple hash table of bounded size to keep track of the stack traces: # We use a simple hash table of bounded size to keep track of the stack traces:
@ -39,7 +38,6 @@ type
total: int total: int
st: StackTrace st: StackTrace
ProfileData = array[0..64*1024-1, ptr ProfileEntry] ProfileData = array[0..64*1024-1, ptr ProfileEntry]
{.deprecated: [TProfileEntry: ProfileEntry, TProfileData: ProfileData].}
proc `==`(a, b: StackTrace): bool = proc `==`(a, b: StackTrace): bool =
for i in 0 .. high(a.lines): for i in 0 .. high(a.lines):

View file

@ -23,8 +23,6 @@ type
fuzz: int32 ## fuzz: int32 ##
count: int32 ## count: int32 ##
{.deprecated: [Toid: Oid].}
proc `==`*(oid1: Oid, oid2: Oid): bool = proc `==`*(oid1: Oid, oid2: Oid): bool =
## Compare two Mongo Object IDs for equality ## Compare two Mongo Object IDs for equality
return (oid1.time == oid2.time) and (oid1.fuzz == oid2.fuzz) and (oid1.count == oid2.count) return (oid1.time == oid2.time) and (oid1.fuzz == oid2.fuzz) and (oid1.count == oid2.count)

View file

@ -134,7 +134,7 @@ proc get*[T](self: Option[T]): T =
proc get*[T](self: Option[T], otherwise: T): T = proc get*[T](self: Option[T], otherwise: T): T =
## Returns the contents of this option or `otherwise` if the option is none. ## Returns the contents of this option or `otherwise` if the option is none.
if self.has: if self.isSome:
self.val self.val
else: else:
otherwise otherwise
@ -154,7 +154,7 @@ proc map*[T, R](self: Option[T], callback: proc (input: T): R): Option[R] =
proc flatten*[A](self: Option[Option[A]]): Option[A] = proc flatten*[A](self: Option[Option[A]]): Option[A] =
## Remove one level of structure in a nested Option. ## Remove one level of structure in a nested Option.
if self.has: if self.isSome:
self.val self.val
else: else:
none(A) none(A)
@ -179,14 +179,14 @@ proc filter*[T](self: Option[T], callback: proc (input: T): bool): Option[T] =
proc `==`*(a, b: Option): bool = proc `==`*(a, b: Option): bool =
## Returns ``true`` if both ``Option``s are ``none``, ## Returns ``true`` if both ``Option``s are ``none``,
## or if they have equal values ## or if they have equal values
(a.has and b.has and a.val == b.val) or (not a.has and not b.has) (a.isSome and b.isSome and a.val == b.val) or (not a.isSome and not b.isSome)
proc `$`*[T](self: Option[T]): string = proc `$`*[T](self: Option[T]): string =
## Get the string representation of this option. If the option has a value, ## Get the string representation of this option. If the option has a value,
## the result will be `Some(x)` where `x` is the string representation of the contained value. ## the result will be `Some(x)` where `x` is the string representation of the contained value.
## If the option does not have a value, the result will be `None[T]` where `T` is the name of ## If the option does not have a value, the result will be `None[T]` where `T` is the name of
## the type contained in the option. ## the type contained in the option.
if self.has: if self.isSome:
"Some(" & $self.val & ")" "Some(" & $self.val & ")"
else: else:
"None[" & T.name & "]" "None[" & T.name & "]"

View file

@ -431,8 +431,6 @@ type
fpOthersWrite, ## write access for others fpOthersWrite, ## write access for others
fpOthersRead ## read access for others fpOthersRead ## read access for others
{.deprecated: [TFilePermission: FilePermission].}
proc getFilePermissions*(filename: string): set[FilePermission] {. proc getFilePermissions*(filename: string): set[FilePermission] {.
rtl, extern: "nos$1", tags: [ReadDirEffect].} = rtl, extern: "nos$1", tags: [ReadDirEffect].} =
## retrieves file permissions for `filename`. `OSError` is raised in case of ## retrieves file permissions for `filename`. `OSError` is raised in case of
@ -730,8 +728,6 @@ type
pcDir, ## path refers to a directory pcDir, ## path refers to a directory
pcLinkToDir ## path refers to a symbolic link to a directory pcLinkToDir ## path refers to a symbolic link to a directory
{.deprecated: [TPathComponent: PathComponent].}
when defined(posix): when defined(posix):
proc getSymlinkFileKind(path: string): PathComponent = proc getSymlinkFileKind(path: string): PathComponent =
@ -1441,18 +1437,6 @@ proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [ReadIOEffect].} =
if result.len == 0: if result.len == 0:
result = getApplHeuristic() result = getApplHeuristic()
proc getApplicationFilename*(): string {.rtl, extern: "nos$1", deprecated.} =
## Returns the filename of the application's executable.
## **Deprecated since version 0.8.12**: use ``getAppFilename``
## instead.
result = getAppFilename()
proc getApplicationDir*(): string {.rtl, extern: "nos$1", deprecated.} =
## Returns the directory of the application's executable.
## **Deprecated since version 0.8.12**: use ``getAppDir``
## instead.
result = splitFile(getAppFilename()).dir
proc getAppDir*(): string {.rtl, extern: "nos$1", tags: [ReadIOEffect].} = proc getAppDir*(): string {.rtl, extern: "nos$1", tags: [ReadIOEffect].} =
## Returns the directory of the application's executable. ## Returns the directory of the application's executable.
result = splitFile(getAppFilename()).dir result = splitFile(getAppFilename()).dir

View file

@ -29,11 +29,6 @@ type
OSErrorCode* = distinct int32 ## Specifies an OS Error Code. OSErrorCode* = distinct int32 ## Specifies an OS Error Code.
{.deprecated: [FReadEnv: ReadEnvEffect, FWriteEnv: WriteEnvEffect,
FReadDir: ReadDirEffect,
FWriteDir: WriteDirEffect,
TOSErrorCode: OSErrorCode
].}
const const
doslikeFileSystem* = defined(windows) or defined(OS2) or defined(DOS) doslikeFileSystem* = defined(windows) or defined(OS2) or defined(DOS)

View file

@ -61,9 +61,6 @@ type
Process* = ref ProcessObj ## represents an operating system process Process* = ref ProcessObj ## represents an operating system process
{.deprecated: [TProcess: ProcessObj, PProcess: Process,
TProcessOption: ProcessOption].}
const poUseShell* {.deprecated.} = poUsePath const poUseShell* {.deprecated.} = poUsePath
## Deprecated alias for poUsePath. ## Deprecated alias for poUsePath.
@ -373,17 +370,15 @@ template streamAccess(p) =
when defined(Windows) and not defined(useNimRtl): when defined(Windows) and not defined(useNimRtl):
# We need to implement a handle stream for Windows: # We need to implement a handle stream for Windows:
type type
PFileHandleStream = ref FileHandleStream FileHandleStream = ref object of StreamObj
FileHandleStream = object of StreamObj
handle: Handle handle: Handle
atTheEnd: bool atTheEnd: bool
{.deprecated: [TFileHandleStream: FileHandleStream].}
proc hsClose(s: Stream) = discard # nothing to do here proc hsClose(s: Stream) = discard # nothing to do here
proc hsAtEnd(s: Stream): bool = return PFileHandleStream(s).atTheEnd proc hsAtEnd(s: Stream): bool = return FileHandleStream(s).atTheEnd
proc hsReadData(s: Stream, buffer: pointer, bufLen: int): int = proc hsReadData(s: Stream, buffer: pointer, bufLen: int): int =
var s = PFileHandleStream(s) var s = FileHandleStream(s)
if s.atTheEnd: return 0 if s.atTheEnd: return 0
var br: int32 var br: int32
var a = winlean.readFile(s.handle, buffer, bufLen.cint, addr br, nil) var a = winlean.readFile(s.handle, buffer, bufLen.cint, addr br, nil)
@ -395,13 +390,13 @@ when defined(Windows) and not defined(useNimRtl):
result = br result = br
proc hsWriteData(s: Stream, buffer: pointer, bufLen: int) = proc hsWriteData(s: Stream, buffer: pointer, bufLen: int) =
var s = PFileHandleStream(s) var s = FileHandleStream(s)
var bytesWritten: int32 var bytesWritten: int32
var a = winlean.writeFile(s.handle, buffer, bufLen.cint, var a = winlean.writeFile(s.handle, buffer, bufLen.cint,
addr bytesWritten, nil) addr bytesWritten, nil)
if a == 0: raiseOSError(osLastError()) if a == 0: raiseOSError(osLastError())
proc newFileHandleStream(handle: Handle): PFileHandleStream = proc newFileHandleStream(handle: Handle): FileHandleStream =
new(result) new(result)
result.handle = handle result.handle = handle
result.closeImpl = hsClose result.closeImpl = hsClose
@ -752,14 +747,14 @@ elif not defined(useNimRtl):
copyMem(result[i], addr(x[0]), x.len+1) copyMem(result[i], addr(x[0]), x.len+1)
inc(i) inc(i)
type StartProcessData = object type
StartProcessData = object
sysCommand: string sysCommand: string
sysArgs: cstringArray sysArgs: cstringArray
sysEnv: cstringArray sysEnv: cstringArray
workingDir: cstring workingDir: cstring
pStdin, pStdout, pStderr, pErrorPipe: array[0..1, cint] pStdin, pStdout, pStderr, pErrorPipe: array[0..1, cint]
options: set[ProcessOption] options: set[ProcessOption]
{.deprecated: [TStartProcessData: StartProcessData].}
const useProcessAuxSpawn = declared(posix_spawn) and not defined(useFork) and const useProcessAuxSpawn = declared(posix_spawn) and not defined(useFork) and
not defined(useClone) and not defined(linux) not defined(useClone) and not defined(linux)

View file

@ -125,9 +125,6 @@ type
tok: Token tok: Token
filename: string filename: string
{.deprecated: [TCfgEventKind: CfgEventKind, TCfgEvent: CfgEvent,
TTokKind: TokKind, TToken: Token, TCfgParser: CfgParser].}
# implementation # implementation
const const

View file

@ -66,8 +66,6 @@ type
CsvError* = object of IOError ## exception that is raised if CsvError* = object of IOError ## exception that is raised if
## a parsing error occurs ## a parsing error occurs
{.deprecated: [TCsvRow: CsvRow, TCsvParser: CsvParser, EInvalidCsv: CsvError].}
proc raiseEInvalidCsv(filename: string, line, col: int, proc raiseEInvalidCsv(filename: string, line, col: int,
msg: string) {.noreturn.} = msg: string) {.noreturn.} =
var e: ref CsvError var e: ref CsvError

View file

@ -54,8 +54,6 @@ type
## or the argument, ``value`` is not "" if ## or the argument, ``value`` is not "" if
## the option was given a value ## the option was given a value
{.deprecated: [TCmdLineKind: CmdLineKind, TOptParser: OptParser].}
proc parseWord(s: string, i: int, w: var string, proc parseWord(s: string, i: int, w: var string,
delim: set[char] = {'\x09', ' '}): int = delim: set[char] = {'\x09', ' '}): int =
result = i result = i

View file

@ -41,8 +41,6 @@ type
## or the argument, ``value`` is not "" if ## or the argument, ``value`` is not "" if
## the option was given a value ## the option was given a value
{.deprecated: [TCmdLineKind: CmdLineKind, TOptParser: OptParser].}
proc initOptParser*(cmdline: seq[string]): OptParser {.rtl.} = proc initOptParser*(cmdline: seq[string]): OptParser {.rtl.} =
## Initalizes option parses with cmdline. cmdline should not contain ## Initalizes option parses with cmdline. cmdline should not contain
## argument 0 - program name. ## argument 0 - program name.
@ -122,8 +120,6 @@ proc cmdLineRest*(p: OptParser): TaintedString {.rtl, extern: "npo2$1", deprecat
type type
GetoptResult* = tuple[kind: CmdLineKind, key, val: TaintedString] GetoptResult* = tuple[kind: CmdLineKind, key, val: TaintedString]
{.deprecated: [TGetoptResult: GetoptResult].}
iterator getopt*(p: var OptParser): GetoptResult = iterator getopt*(p: var OptParser): GetoptResult =
## This is an convenience iterator for iterating over the given OptParser object. ## This is an convenience iterator for iterating over the given OptParser object.
## Example: ## Example:

View file

@ -45,8 +45,6 @@ type
SqlLexer* = object of BaseLexer ## the parser object. SqlLexer* = object of BaseLexer ## the parser object.
filename: string filename: string
{.deprecated: [TToken: Token, TSqlLexer: SqlLexer].}
const const
tokKindToStr: array[TokKind, string] = [ tokKindToStr: array[TokKind, string] = [
"invalid", "[EOF]", "identifier", "quoted identifier", "string constant", "invalid", "[EOF]", "identifier", "quoted identifier", "string constant",

View file

@ -365,8 +365,6 @@ type
ikVar, ## ``var`` part of the interpolated string ikVar, ## ``var`` part of the interpolated string
ikExpr ## ``expr`` part of the interpolated string ikExpr ## ``expr`` part of the interpolated string
{.deprecated: [TInterpolatedKind: InterpolatedKind].}
iterator interpolatedFragments*(s: string): tuple[kind: InterpolatedKind, iterator interpolatedFragments*(s: string): tuple[kind: InterpolatedKind,
value: string] = value: string] =
## Tokenizes the string `s` into substrings for interpolation purposes. ## Tokenizes the string `s` into substrings for interpolation purposes.

View file

@ -98,9 +98,6 @@ type
filename: string filename: string
options: set[XmlParseOption] options: set[XmlParseOption]
{.deprecated: [TXmlParser: XmlParser, TXmlParseOptions: XmlParseOption,
TXmlError: XmlErrorKind, TXmlEventKind: XmlEventKind].}
const const
errorMessages: array[XmlErrorKind, string] = [ errorMessages: array[XmlErrorKind, string] = [
"no error", "no error",

View file

@ -74,8 +74,8 @@ type
line: int ## line the symbol has been declared/used in line: int ## line the symbol has been declared/used in
col: int ## column the symbol has been declared/used in col: int ## column the symbol has been declared/used in
flags: set[NonTerminalFlag] ## the nonterminal's flags flags: set[NonTerminalFlag] ## the nonterminal's flags
rule: Node ## the rule that the symbol refers to rule: Peg ## the rule that the symbol refers to
Node {.shallow.} = object Peg* {.shallow.} = object ## type that represents a PEG
case kind: PegKind case kind: PegKind
of pkEmpty..pkWhitespace: nil of pkEmpty..pkWhitespace: nil
of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle: term: string of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle: term: string
@ -83,13 +83,9 @@ type
of pkCharChoice, pkGreedyRepSet: charChoice: ref set[char] of pkCharChoice, pkGreedyRepSet: charChoice: ref set[char]
of pkNonTerminal: nt: NonTerminal of pkNonTerminal: nt: NonTerminal
of pkBackRef..pkBackRefIgnoreStyle: index: range[0..MaxSubpatterns] of pkBackRef..pkBackRefIgnoreStyle: index: range[0..MaxSubpatterns]
else: sons: seq[Node] else: sons: seq[Peg]
NonTerminal* = ref NonTerminalObj NonTerminal* = ref NonTerminalObj
Peg* = Node ## type that represents a PEG
{.deprecated: [TPeg: Peg, TNode: Node].}
proc term*(t: string): Peg {.nosideEffect, rtl, extern: "npegs$1Str".} = proc term*(t: string): Peg {.nosideEffect, rtl, extern: "npegs$1Str".} =
## constructs a PEG from a terminal string ## constructs a PEG from a terminal string
if t.len != 1: if t.len != 1:
@ -621,7 +617,7 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
a, b: Rune a, b: Rune
result = start result = start
while i < len(p.term): while i < len(p.term):
while true: while i < len(p.term):
fastRuneAt(p.term, i, a) fastRuneAt(p.term, i, a)
if a != Rune('_'): break if a != Rune('_'): break
while result < s.len: while result < s.len:

View file

@ -37,8 +37,6 @@ type
length: int length: int
data: string # != nil if a leaf data: string # != nil if a leaf
{.deprecated: [PRope: Rope].}
proc isConc(r: Rope): bool {.inline.} = return isNil(r.data) 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.

View file

@ -94,9 +94,6 @@ type
disp: Dispatcher disp: Dispatcher
AsyncScgiState* = ref AsyncScgiStateObj AsyncScgiState* = ref AsyncScgiStateObj
{.deprecated: [EScgi: ScgiError, TScgiState: ScgiState,
PAsyncScgiState: AsyncScgiState].}
proc recvBuffer(s: var ScgiState, L: int) = proc recvBuffer(s: var ScgiState, L: int) =
if L > s.bufLen: if L > s.bufLen:
s.bufLen = L s.bufLen = L

View file

@ -316,18 +316,18 @@ else:
include ioselects/ioselectors_poll include ioselects/ioselectors_poll
proc register*[T](s: Selector[T], fd: int | SocketHandle, proc register*[T](s: Selector[T], fd: int | SocketHandle,
events: set[Event], data: T) {.deprecated.} = events: set[Event], data: T) {.deprecated: "use registerHandle instead".} =
## **Deprecated since v0.18.0:** Use ``registerHandle`` instead. ## **Deprecated since v0.18.0:** Use ``registerHandle`` instead.
s.registerHandle(fd, events, data) s.registerHandle(fd, events, data)
proc setEvent*(ev: SelectEvent) {.deprecated.} = proc setEvent*(ev: SelectEvent) {.deprecated: "use trigger instead".} =
## Trigger event ``ev``. ## Trigger event ``ev``.
## ##
## **Deprecated since v0.18.0:** Use ``trigger`` instead. ## **Deprecated since v0.18.0:** Use ``trigger`` instead.
ev.trigger() ev.trigger()
proc update*[T](s: Selector[T], fd: int | SocketHandle, proc update*[T](s: Selector[T], fd: int | SocketHandle,
events: set[Event]) {.deprecated.} = events: set[Event]) {.deprecated: "use updateHandle instead".} =
## Update file/socket descriptor ``fd``, registered in selector ## Update file/socket descriptor ``fd``, registered in selector
## ``s`` with new events set ``event``. ## ``s`` with new events set ``event``.
## ##

View file

@ -51,8 +51,6 @@ type
Smtp* = SmtpBase[Socket] Smtp* = SmtpBase[Socket]
AsyncSmtp* = SmtpBase[AsyncSocket] AsyncSmtp* = SmtpBase[AsyncSocket]
{.deprecated: [EInvalidReply: ReplyError, TMessage: Message, TSMTP: Smtp].}
proc debugSend(smtp: Smtp | AsyncSmtp, cmd: string) {.multisync.} = proc debugSend(smtp: Smtp | AsyncSmtp, cmd: string) {.multisync.} =
if smtp.debug: if smtp.debug:
echo("C:" & cmd) echo("C:" & cmd)

View file

@ -65,8 +65,6 @@ type
y_stats*: RunningStat ## stats for second set of data y_stats*: RunningStat ## stats for second set of data
s_xy: float ## accumulated data for combined xy s_xy: float ## accumulated data for combined xy
{.deprecated: [TFloatClass: FloatClass, TRunningStat: RunningStat].}
# ----------- RunningStat -------------------------- # ----------- RunningStat --------------------------
proc clear*(s: var RunningStat) = proc clear*(s: var RunningStat) =
## reset `s` ## reset `s`

View file

@ -57,8 +57,6 @@ type
tags: [WriteIOEffect], gcsafe.} tags: [WriteIOEffect], gcsafe.}
flushImpl*: proc (s: Stream) {.nimcall, tags: [WriteIOEffect], gcsafe.} flushImpl*: proc (s: Stream) {.nimcall, tags: [WriteIOEffect], gcsafe.}
{.deprecated: [PStream: Stream, TStream: StreamObj].}
proc flush*(s: Stream) = proc flush*(s: Stream) =
## flushes the buffers that the stream `s` might use. ## flushes the buffers that the stream `s` might use.
if not isNil(s.flushImpl): s.flushImpl(s) if not isNil(s.flushImpl): s.flushImpl(s)
@ -76,27 +74,14 @@ proc atEnd*(s: Stream): bool =
## been read. ## been read.
result = s.atEndImpl(s) result = s.atEndImpl(s)
proc atEnd*(s, unused: Stream): bool {.deprecated.} =
## checks if more data can be read from `f`. Returns true if all data has
## been read.
result = s.atEndImpl(s)
proc setPosition*(s: Stream, pos: int) = proc setPosition*(s: Stream, pos: int) =
## sets the position `pos` of the stream `s`. ## sets the position `pos` of the stream `s`.
s.setPositionImpl(s, pos) s.setPositionImpl(s, pos)
proc setPosition*(s, unused: Stream, pos: int) {.deprecated.} =
## sets the position `pos` of the stream `s`.
s.setPositionImpl(s, pos)
proc getPosition*(s: Stream): int = proc getPosition*(s: Stream): int =
## retrieves the current position in the stream `s`. ## retrieves the current position in the stream `s`.
result = s.getPositionImpl(s) result = s.getPositionImpl(s)
proc getPosition*(s, unused: Stream): int {.deprecated.} =
## retrieves the current position in the stream `s`.
result = s.getPositionImpl(s)
proc readData*(s: Stream, buffer: pointer, bufLen: int): int = proc readData*(s: Stream, buffer: pointer, bufLen: int): int =
## low level proc that reads data into an untyped `buffer` of `bufLen` size. ## low level proc that reads data into an untyped `buffer` of `bufLen` size.
result = s.readDataImpl(s, buffer, bufLen) result = s.readDataImpl(s, buffer, bufLen)
@ -114,11 +99,6 @@ proc readAll*(s: Stream): string =
inc r, bufferSize inc r, bufferSize
setLen(result, r+bufferSize) setLen(result, r+bufferSize)
proc readData*(s, unused: Stream, buffer: pointer,
bufLen: int): int {.deprecated.} =
## low level proc that reads data into an untyped `buffer` of `bufLen` size.
result = s.readDataImpl(s, buffer, bufLen)
proc peekData*(s: Stream, buffer: pointer, bufLen: int): int = proc peekData*(s: Stream, buffer: pointer, bufLen: int): int =
## low level proc that reads data into an untyped `buffer` of `bufLen` size ## low level proc that reads data into an untyped `buffer` of `bufLen` size
## without moving stream position ## without moving stream position
@ -153,11 +133,6 @@ proc write*(s: Stream, x: string) =
else: else:
if x.len > 0: writeData(s, unsafeAddr x[0], x.len) if x.len > 0: writeData(s, unsafeAddr x[0], x.len)
proc writeLn*(s: Stream, args: varargs[string, `$`]) {.deprecated.} =
## **Deprecated since version 0.11.4:** Use **writeLine** instead.
for str in args: write(s, str)
write(s, "\n")
proc writeLine*(s: Stream, args: varargs[string, `$`]) = proc writeLine*(s: Stream, args: varargs[string, `$`]) =
## writes one or more strings to the the stream `s` followed ## writes one or more strings to the the stream `s` followed
## by a new line. No length field or terminating zero is written. ## by a new line. No length field or terminating zero is written.
@ -348,8 +323,6 @@ when not defined(js):
data*: string data*: string
pos: int pos: int
{.deprecated: [PStringStream: StringStream, TStringStream: StringStreamObj].}
proc ssAtEnd(s: Stream): bool = proc ssAtEnd(s: Stream): bool =
var s = StringStream(s) var s = StringStream(s)
return s.pos >= s.data.len return s.pos >= s.data.len
@ -409,7 +382,6 @@ when not defined(js):
FileStream* = ref FileStreamObj ## a stream that encapsulates a `File` FileStream* = ref FileStreamObj ## a stream that encapsulates a `File`
FileStreamObj* = object of Stream FileStreamObj* = object of Stream
f: File f: File
{.deprecated: [PFileStream: FileStream, TFileStream: FileStreamObj].}
proc fsClose(s: Stream) = proc fsClose(s: Stream) =
if FileStream(s).f != nil: if FileStream(s).f != nil:
@ -472,9 +444,6 @@ else:
handle*: FileHandle handle*: FileHandle
pos: int pos: int
{.deprecated: [PFileHandleStream: FileHandleStream,
TFileHandleStream: FileHandleStreamObj].}
proc newEOS(msg: string): ref OSError = proc newEOS(msg: string): ref OSError =
new(result) new(result)
result.msg = msg result.msg = msg

View file

@ -17,9 +17,7 @@ import
when defined(js): when defined(js):
{.pragma: rtlFunc.} {.pragma: rtlFunc.}
{.pragma: deprecatedGetFunc.}
else: else:
{.pragma: deprecatedGetFunc, deprecatedGet.}
{.pragma: rtlFunc, rtl.} {.pragma: rtlFunc, rtl.}
import os import os
include "system/inclrtl" include "system/inclrtl"
@ -38,9 +36,6 @@ type
StringTableRef* = ref StringTableObj ## use this type to declare string tables StringTableRef* = ref StringTableObj ## use this type to declare string tables
{.deprecated: [TStringTableMode: StringTableMode,
TStringTable: StringTableObj, PStringTable: StringTableRef].}
proc len*(t: StringTableRef): int {.rtlFunc, extern: "nst$1".} = proc len*(t: StringTableRef): int {.rtlFunc, extern: "nst$1".} =
## returns the number of keys in `t`. ## returns the number of keys in `t`.
result = t.counter result = t.counter
@ -73,10 +68,6 @@ type
useKey ## do not replace ``$key`` if it is not found useKey ## do not replace ``$key`` if it is not found
## in the table (or in the environment) ## in the table (or in the environment)
{.deprecated: [TFormatFlag: FormatFlag].}
# implementation
const const
growthFactor = 2 growthFactor = 2
startSize = 64 startSize = 64
@ -118,17 +109,12 @@ template get(t: StringTableRef, key: string) =
raise newException(KeyError, "key not found") raise newException(KeyError, "key not found")
proc `[]`*(t: StringTableRef, key: string): var string {. proc `[]`*(t: StringTableRef, key: string): var string {.
rtlFunc, extern: "nstTake", deprecatedGetFunc.} = rtlFunc, extern: "nstTake".} =
## retrieves the location at ``t[key]``. If `key` is not in `t`, the ## retrieves the location at ``t[key]``. If `key` is not in `t`, the
## ``KeyError`` exception is raised. One can check with ``hasKey`` whether ## ``KeyError`` exception is raised. One can check with ``hasKey`` whether
## the key exists. ## the key exists.
get(t, key) get(t, key)
proc mget*(t: StringTableRef, key: string): var string {.deprecated.} =
## retrieves the location at ``t[key]``. If `key` is not in `t`, the
## ``KeyError`` exception is raised. Use ```[]``` instead.
get(t, key)
proc getOrDefault*(t: StringTableRef; key: string, default: string = ""): string = proc getOrDefault*(t: StringTableRef; key: string, default: string = ""): string =
var index = rawGet(t, key) var index = rawGet(t, key)
if index >= 0: result = t.data[index].val if index >= 0: result = t.data[index].val
@ -193,7 +179,8 @@ proc newStringTable*(mode: StringTableMode): StringTableRef {.
result.counter = 0 result.counter = 0
newSeq(result.data, startSize) newSeq(result.data, startSize)
proc clear*(s: StringTableRef, mode: StringTableMode) = proc clear*(s: StringTableRef, mode: StringTableMode) {.
rtlFunc, extern: "nst$1".} =
## resets a string table to be empty again. ## resets a string table to be empty again.
s.mode = mode s.mode = mode
s.counter = 0 s.counter = 0

View file

@ -1262,21 +1262,20 @@ proc initSkipTable*(a: var SkipTable, sub: string)
{.noSideEffect, rtl, extern: "nsuInitSkipTable".} = {.noSideEffect, rtl, extern: "nsuInitSkipTable".} =
## Preprocess table `a` for `sub`. ## Preprocess table `a` for `sub`.
let m = len(sub) let m = len(sub)
let m1 = m + 1
var i = 0 var i = 0
while i <= 0xff-7: while i <= 0xff-7:
a[chr(i + 0)] = m1 a[chr(i + 0)] = m
a[chr(i + 1)] = m1 a[chr(i + 1)] = m
a[chr(i + 2)] = m1 a[chr(i + 2)] = m
a[chr(i + 3)] = m1 a[chr(i + 3)] = m
a[chr(i + 4)] = m1 a[chr(i + 4)] = m
a[chr(i + 5)] = m1 a[chr(i + 5)] = m
a[chr(i + 6)] = m1 a[chr(i + 6)] = m
a[chr(i + 7)] = m1 a[chr(i + 7)] = m
i += 8 i += 8
for i in 0..m-1: for i in 0 ..< m - 1:
a[sub[i]] = m-i a[sub[i]] = m - 1 - i
proc find*(a: SkipTable, s, sub: string, start: Natural = 0, last: Natural = 0): int proc find*(a: SkipTable, s, sub: string, start: Natural = 0, last: Natural = 0): int
{.noSideEffect, rtl, extern: "nsuFindStrA".} = {.noSideEffect, rtl, extern: "nsuFindStrA".} =
@ -1284,18 +1283,29 @@ proc find*(a: SkipTable, s, sub: string, start: Natural = 0, last: Natural = 0):
## If `last` is unspecified, it defaults to `s.high`. ## If `last` is unspecified, it defaults to `s.high`.
## ##
## Searching is case-sensitive. If `sub` is not in `s`, -1 is returned. ## Searching is case-sensitive. If `sub` is not in `s`, -1 is returned.
let let
last = if last==0: s.high else: last last = if last==0: s.high else: last
m = len(sub) sLen = last - start + 1
n = last + 1 subLast = sub.len - 1
# search:
var j = start if subLast == -1:
while j <= n - m: # this was an empty needle string,
block match: # we count this as match in the first possible position:
for k in 0..m-1: return start
if sub[k] != s[k+j]: break match
return j # This is an implementation of the Boyer-Moore Horspool algorithms
inc(j, a[s[j+m]]) # https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore%E2%80%93Horspool_algorithm
var skip = start
while last - skip >= subLast:
var i = subLast
while s[skip + i] == sub[i]:
if i == 0:
return skip
dec i
inc skip, a[s[skip + subLast]]
return -1 return -1
when not (defined(js) or defined(nimdoc) or defined(nimscript)): when not (defined(js) or defined(nimdoc) or defined(nimscript)):
@ -1455,8 +1465,30 @@ proc contains*(s: string, chars: set[char]): bool {.noSideEffect.} =
proc replace*(s, sub: string, by = ""): string {.noSideEffect, proc replace*(s, sub: string, by = ""): string {.noSideEffect,
rtl, extern: "nsuReplaceStr".} = rtl, extern: "nsuReplaceStr".} =
## Replaces `sub` in `s` by the string `by`. ## Replaces `sub` in `s` by the string `by`.
var a {.noinit.}: SkipTable
result = "" result = ""
let subLen = sub.len
if subLen == 0:
for c in s:
add result, by
add result, c
add result, by
return
elif subLen == 1:
# when the pattern is a single char, we use a faster
# char-based search that doesn't need a skip table:
var c = sub[0]
let last = s.high
var i = 0
while true:
let j = find(s, c, i, last)
if j < 0: break
add result, substr(s, i, j - 1)
add result, by
i = j + subLen
# copy the rest:
add result, substr(s, i)
else:
var a {.noinit.}: SkipTable
initSkipTable(a, sub) initSkipTable(a, sub)
let last = s.high let last = s.high
var i = 0 var i = 0
@ -1465,11 +1497,7 @@ proc replace*(s, sub: string, by = ""): string {.noSideEffect,
if j < 0: break if j < 0: break
add result, substr(s, i, j - 1) add result, substr(s, i, j - 1)
add result, by add result, by
if sub.len == 0: i = j + subLen
if i < s.len: add result, s[i]
i = j + 1
else:
i = j + sub.len
# copy the rest: # copy the rest:
add result, substr(s, i) add result, substr(s, i)
@ -1492,6 +1520,7 @@ proc replaceWord*(s, sub: string, by = ""): string {.noSideEffect,
## Each occurrence 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.
if sub.len == 0: return s
const wordChars = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\128'..'\255'} const wordChars = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\128'..'\255'}
var a {.noinit.}: SkipTable var a {.noinit.}: SkipTable
result = "" result = ""
@ -2326,6 +2355,57 @@ proc removePrefix*(s: var string, prefix: string) {.
s.delete(0, prefix.len - 1) s.delete(0, prefix.len - 1)
when isMainModule: when isMainModule:
proc nonStaticTests =
doAssert formatBiggestFloat(1234.567, ffDecimal, -1) == "1234.567000"
doAssert formatBiggestFloat(1234.567, ffDecimal, 0) == "1235."
doAssert formatBiggestFloat(1234.567, ffDecimal, 1) == "1234.6"
doAssert formatBiggestFloat(0.00000000001, ffDecimal, 11) == "0.00000000001"
doAssert formatBiggestFloat(0.00000000001, ffScientific, 1, ',') in
["1,0e-11", "1,0e-011"]
# bug #6589
doAssert formatFloat(123.456, ffScientific, precision = -1) == "1.234560e+02"
doAssert "$# $3 $# $#" % ["a", "b", "c"] == "a c b c"
doAssert "${1}12 ${-1}$2" % ["a", "b"] == "a12 bb"
block: # formatSize tests
doAssert formatSize((1'i64 shl 31) + (300'i64 shl 20)) == "2.293GiB"
doAssert formatSize((2.234*1024*1024).int) == "2.234MiB"
doAssert formatSize(4096) == "4KiB"
doAssert formatSize(4096, prefix=bpColloquial, includeSpace=true) == "4 kB"
doAssert formatSize(4096, includeSpace=true) == "4 KiB"
doAssert formatSize(5_378_934, prefix=bpColloquial, decimalSep=',') == "5,13MB"
block: # formatEng tests
doAssert formatEng(0, 2, trim=false) == "0.00"
doAssert formatEng(0, 2) == "0"
doAssert formatEng(53, 2, trim=false) == "53.00"
doAssert formatEng(0.053, 2, trim=false) == "53.00e-3"
doAssert formatEng(0.053, 4, trim=false) == "53.0000e-3"
doAssert formatEng(0.053, 4, trim=true) == "53e-3"
doAssert formatEng(0.053, 0) == "53e-3"
doAssert formatEng(52731234) == "52.731234e6"
doAssert formatEng(-52731234) == "-52.731234e6"
doAssert formatEng(52731234, 1) == "52.7e6"
doAssert formatEng(-52731234, 1) == "-52.7e6"
doAssert formatEng(52731234, 1, decimalSep=',') == "52,7e6"
doAssert formatEng(-52731234, 1, decimalSep=',') == "-52,7e6"
doAssert formatEng(4100, siPrefix=true, unit="V") == "4.1 kV"
doAssert formatEng(4.1, siPrefix=true, unit="V", useUnitSpace=true) == "4.1 V"
doAssert formatEng(4.1, siPrefix=true) == "4.1" # Note lack of space
doAssert formatEng(4100, siPrefix=true) == "4.1 k"
doAssert formatEng(4.1, siPrefix=true, unit="", useUnitSpace=true) == "4.1 " # Includes space
doAssert formatEng(4100, siPrefix=true, unit="") == "4.1 k"
doAssert formatEng(4100) == "4.1e3"
doAssert formatEng(4100, unit="V", useUnitSpace=true) == "4.1e3 V"
doAssert formatEng(4100, unit="", useUnitSpace=true) == "4.1e3 "
# Don't use SI prefix as number is too big
doAssert formatEng(3.1e22, siPrefix=true, unit="a", useUnitSpace=true) == "31e21 a"
# Don't use SI prefix as number is too small
doAssert formatEng(3.1e-25, siPrefix=true, unit="A", useUnitSpace=true) == "310e-27 A"
proc staticTests =
doAssert align("abc", 4) == " abc" doAssert align("abc", 4) == " abc"
doAssert align("a", 0) == "a" doAssert align("a", 0) == "a"
doAssert align("1232", 6) == " 1232" doAssert align("1232", 6) == " 1232"
@ -2347,33 +2427,13 @@ when isMainModule:
longOutp = "ThisIsOn\neVeryLon\ngStringW\nhichWeWi\nllSplitI\nntoEight\nSeparate\nPartsNow" longOutp = "ThisIsOn\neVeryLon\ngStringW\nhichWeWi\nllSplitI\nntoEight\nSeparate\nPartsNow"
doAssert wordWrap(longInp, 8, true) == longOutp doAssert wordWrap(longInp, 8, true) == longOutp
doAssert formatBiggestFloat(1234.567, ffDecimal, -1) == "1234.567000"
doAssert formatBiggestFloat(1234.567, ffDecimal, 0) == "1235."
doAssert formatBiggestFloat(1234.567, ffDecimal, 1) == "1234.6"
doAssert formatBiggestFloat(0.00000000001, ffDecimal, 11) == "0.00000000001"
doAssert formatBiggestFloat(0.00000000001, ffScientific, 1, ',') in
["1,0e-11", "1,0e-011"]
# bug #6589
doAssert formatFloat(123.456, ffScientific, precision = -1) == "1.234560e+02"
doAssert "$# $3 $# $#" % ["a", "b", "c"] == "a c b c"
doAssert "${1}12 ${-1}$2" % ["a", "b"] == "a12 bb"
block: # formatSize tests
doAssert formatSize((1'i64 shl 31) + (300'i64 shl 20)) == "2.293GiB"
doAssert formatSize((2.234*1024*1024).int) == "2.234MiB"
doAssert formatSize(4096) == "4KiB"
doAssert formatSize(4096, prefix=bpColloquial, includeSpace=true) == "4 kB"
doAssert formatSize(4096, includeSpace=true) == "4 KiB"
doAssert formatSize(5_378_934, prefix=bpColloquial, decimalSep=',') == "5,13MB"
doAssert "$animal eats $food." % ["animal", "The cat", "food", "fish"] == doAssert "$animal eats $food." % ["animal", "The cat", "food", "fish"] ==
"The cat eats fish." "The cat eats fish."
doAssert "-ld a-ldz -ld".replaceWord("-ld") == " a-ldz " doAssert "-ld a-ldz -ld".replaceWord("-ld") == " a-ldz "
doAssert "-lda-ldz -ld abc".replaceWord("-ld") == "-lda-ldz abc" doAssert "-lda-ldz -ld abc".replaceWord("-ld") == "-lda-ldz abc"
doAssert "-lda-ldz -ld abc".replaceWord("") == "lda-ldz ld abc" doAssert "-lda-ldz -ld abc".replaceWord("") == "-lda-ldz -ld abc"
doAssert "oo".replace("", "abc") == "abcoabcoabc" doAssert "oo".replace("", "abc") == "abcoabcoabc"
type MyEnum = enum enA, enB, enC, enuD, enE type MyEnum = enum enA, enB, enC, enuD, enE
@ -2521,35 +2581,6 @@ bar
doAssert s.splitWhitespace(maxsplit=3) == @["this", "is", "an", "example "] doAssert s.splitWhitespace(maxsplit=3) == @["this", "is", "an", "example "]
doAssert s.splitWhitespace(maxsplit=4) == @["this", "is", "an", "example"] doAssert s.splitWhitespace(maxsplit=4) == @["this", "is", "an", "example"]
block: # formatEng tests
doAssert formatEng(0, 2, trim=false) == "0.00"
doAssert formatEng(0, 2) == "0"
doAssert formatEng(53, 2, trim=false) == "53.00"
doAssert formatEng(0.053, 2, trim=false) == "53.00e-3"
doAssert formatEng(0.053, 4, trim=false) == "53.0000e-3"
doAssert formatEng(0.053, 4, trim=true) == "53e-3"
doAssert formatEng(0.053, 0) == "53e-3"
doAssert formatEng(52731234) == "52.731234e6"
doAssert formatEng(-52731234) == "-52.731234e6"
doAssert formatEng(52731234, 1) == "52.7e6"
doAssert formatEng(-52731234, 1) == "-52.7e6"
doAssert formatEng(52731234, 1, decimalSep=',') == "52,7e6"
doAssert formatEng(-52731234, 1, decimalSep=',') == "-52,7e6"
doAssert formatEng(4100, siPrefix=true, unit="V") == "4.1 kV"
doAssert formatEng(4.1, siPrefix=true, unit="V", useUnitSpace=true) == "4.1 V"
doAssert formatEng(4.1, siPrefix=true) == "4.1" # Note lack of space
doAssert formatEng(4100, siPrefix=true) == "4.1 k"
doAssert formatEng(4.1, siPrefix=true, unit="", useUnitSpace=true) == "4.1 " # Includes space
doAssert formatEng(4100, siPrefix=true, unit="") == "4.1 k"
doAssert formatEng(4100) == "4.1e3"
doAssert formatEng(4100, unit="V", useUnitSpace=true) == "4.1e3 V"
doAssert formatEng(4100, unit="", useUnitSpace=true) == "4.1e3 "
# Don't use SI prefix as number is too big
doAssert formatEng(3.1e22, siPrefix=true, unit="a", useUnitSpace=true) == "31e21 a"
# Don't use SI prefix as number is too small
doAssert formatEng(3.1e-25, siPrefix=true, unit="A", useUnitSpace=true) == "310e-27 A"
block: # startsWith / endsWith char tests block: # startsWith / endsWith char tests
var s = "abcdef" var s = "abcdef"
doAssert s.startsWith('a') doAssert s.startsWith('a')
@ -2559,3 +2590,8 @@ bar
doAssert s.endsWith('\0') == false doAssert s.endsWith('\0') == false
#echo("strutils tests passed") #echo("strutils tests passed")
nonStaticTests()
staticTests()
static: staticTests()

View file

@ -31,8 +31,6 @@ type
SubexError* = object of ValueError ## exception that is raised for SubexError* = object of ValueError ## exception that is raised for
## an invalid subex ## an invalid subex
{.deprecated: [EInvalidSubex: SubexError].}
proc raiseInvalidFormat(msg: string) {.noinline.} = proc raiseInvalidFormat(msg: string) {.noinline.} =
raise newException(SubexError, "invalid format string: " & msg) raise newException(SubexError, "invalid format string: " & msg)
@ -44,7 +42,6 @@ type
else: else:
f: cstring f: cstring
num, i, lineLen: int num, i, lineLen: int
{.deprecated: [TFormatParser: FormatParser].}
template call(x: untyped): untyped = template call(x: untyped): untyped =
p.i = i p.i = i

View file

@ -29,8 +29,6 @@ when not hasThreadSupport:
var var
colorsFGCache = initTable[Color, string]() colorsFGCache = initTable[Color, string]()
colorsBGCache = initTable[Color, string]() colorsBGCache = initTable[Color, string]()
when not defined(windows):
var
styleCache = initTable[int, string]() styleCache = initTable[int, string]()
var var
@ -41,9 +39,7 @@ var
const const
fgPrefix = "\x1b[38;2;" fgPrefix = "\x1b[38;2;"
bgPrefix = "\x1b[48;2;" bgPrefix = "\x1b[48;2;"
ansiResetCode* = "\e[0m"
when not defined(windows):
const
stylePrefix = "\e[" stylePrefix = "\e["
when defined(windows): when defined(windows):
@ -468,7 +464,7 @@ proc resetAttributes*(f: File) =
else: else:
discard setConsoleTextAttribute(hStdout, oldStdoutAttr) discard setConsoleTextAttribute(hStdout, oldStdoutAttr)
else: else:
f.write("\e[0m") f.write(ansiResetCode)
type type
Style* = enum ## different styles for text output Style* = enum ## different styles for text output
@ -487,7 +483,7 @@ when not defined(windows):
gFG {.threadvar.}: int gFG {.threadvar.}: int
gBG {.threadvar.}: int gBG {.threadvar.}: int
proc getStyleStr(style: int): string = proc ansiStyleCode*(style: int): string =
when hasThreadSupport: when hasThreadSupport:
result = fmt"{stylePrefix}{style}m" result = fmt"{stylePrefix}{style}m"
else: else:
@ -497,6 +493,13 @@ when not defined(windows):
result = fmt"{stylePrefix}{style}m" result = fmt"{stylePrefix}{style}m"
styleCache[style] = result styleCache[style] = result
template ansiStyleCode*(style: Style): string =
ansiStyleCode(style.int)
# The styleCache can be skipped when `style` is known at compile-time
template ansiStyleCode*(style: static[Style]): string =
(static(stylePrefix & $style.int & "m"))
proc setStyle*(f: File, style: set[Style]) = proc setStyle*(f: File, style: set[Style]) =
## Sets the terminal style. ## Sets the terminal style.
when defined(windows): when defined(windows):
@ -510,7 +513,7 @@ proc setStyle*(f: File, style: set[Style]) =
discard setConsoleTextAttribute(h, old or a) discard setConsoleTextAttribute(h, old or a)
else: else:
for s in items(style): for s in items(style):
f.write(getStyleStr(ord(s))) f.write(ansiStyleCode(s))
proc writeStyled*(txt: string, style: set[Style] = {styleBright}) = proc writeStyled*(txt: string, style: set[Style] = {styleBright}) =
## Writes the text `txt` in a given `style` to stdout. ## Writes the text `txt` in a given `style` to stdout.
@ -524,9 +527,9 @@ proc writeStyled*(txt: string, style: set[Style] = {styleBright}) =
stdout.write(txt) stdout.write(txt)
stdout.resetAttributes() stdout.resetAttributes()
if gFG != 0: if gFG != 0:
stdout.write(getStyleStr(gFG)) stdout.write(ansiStyleCode(gFG))
if gBG != 0: if gBG != 0:
stdout.write(getStyleStr(gBG)) stdout.write(ansiStyleCode(gBG))
type type
ForegroundColor* = enum ## terminal's foreground colors ForegroundColor* = enum ## terminal's foreground colors
@ -572,7 +575,7 @@ proc setForegroundColor*(f: File, fg: ForegroundColor, bright=false) =
else: else:
gFG = ord(fg) gFG = ord(fg)
if bright: inc(gFG, 60) if bright: inc(gFG, 60)
f.write(getStyleStr(gFG)) f.write(ansiStyleCode(gFG))
proc setBackgroundColor*(f: File, bg: BackgroundColor, bright=false) = proc setBackgroundColor*(f: File, bg: BackgroundColor, bright=false) =
## Sets the terminal's background color. ## Sets the terminal's background color.
@ -594,10 +597,18 @@ proc setBackgroundColor*(f: File, bg: BackgroundColor, bright=false) =
else: else:
gBG = ord(bg) gBG = ord(bg)
if bright: inc(gBG, 60) if bright: inc(gBG, 60)
f.write(getStyleStr(gBG)) f.write(ansiStyleCode(gBG))
proc ansiForegroundColorCode*(fg: ForegroundColor, bright=false): string =
var style = ord(fg)
if bright: inc(style, 60)
return ansiStyleCode(style)
proc getFGColorStr(color: Color): string = template ansiForegroundColorCode*(fg: static[ForegroundColor],
bright: static[bool] = false): string =
ansiStyleCode(fg.int + bright.int * 60)
proc ansiForegroundColorCode*(color: Color): string =
when hasThreadSupport: when hasThreadSupport:
let rgb = extractRGB(color) let rgb = extractRGB(color)
result = fmt"{fgPrefix}{rgb.r};{rgb.g};{rgb.b}m" result = fmt"{fgPrefix}{rgb.r};{rgb.g};{rgb.b}m"
@ -609,7 +620,11 @@ proc getFGColorStr(color: Color): string =
result = fmt"{fgPrefix}{rgb.r};{rgb.g};{rgb.b}m" result = fmt"{fgPrefix}{rgb.r};{rgb.g};{rgb.b}m"
colorsFGCache[color] = result colorsFGCache[color] = result
proc getBGColorStr(color: Color): string = template ansiForegroundColorCode*(color: static[Color]): string =
const rgb = extractRGB(color)
(static(fmt"{fgPrefix}{rgb.r};{rgb.g};{rgb.b}m"))
proc ansiBackgroundColorCode*(color: Color): string =
when hasThreadSupport: when hasThreadSupport:
let rgb = extractRGB(color) let rgb = extractRGB(color)
result = fmt"{bgPrefix}{rgb.r};{rgb.g};{rgb.b}m" result = fmt"{bgPrefix}{rgb.r};{rgb.g};{rgb.b}m"
@ -621,15 +636,19 @@ proc getBGColorStr(color: Color): string =
result = fmt"{bgPrefix}{rgb.r};{rgb.g};{rgb.b}m" result = fmt"{bgPrefix}{rgb.r};{rgb.g};{rgb.b}m"
colorsFGCache[color] = result colorsFGCache[color] = result
template ansiBackgroundColorCode*(color: static[Color]): string =
const rgb = extractRGB(color)
(static(fmt"{bgPrefix}{rgb.r};{rgb.g};{rgb.b}m"))
proc setForegroundColor*(f: File, color: Color) = proc setForegroundColor*(f: File, color: Color) =
## Sets the terminal's foreground true color. ## Sets the terminal's foreground true color.
if trueColorIsEnabled: if trueColorIsEnabled:
f.write(getFGColorStr(color)) f.write(ansiForegroundColorCode(color))
proc setBackgroundColor*(f: File, color: Color) = proc setBackgroundColor*(f: File, color: Color) =
## Sets the terminal's background true color. ## Sets the terminal's background true color.
if trueColorIsEnabled: if trueColorIsEnabled:
f.write(getBGColorStr(color)) f.write(ansiBackgroundColorCode(color))
proc setTrueColor(f: File, color: Color) = proc setTrueColor(f: File, color: Color) =
if fgSetColor: if fgSetColor:
@ -759,6 +778,10 @@ when defined(windows):
x = runeLenAt(password.string, i) x = runeLenAt(password.string, i)
inc i, x inc i, x
password.string.setLen(max(password.len - x, 0)) password.string.setLen(max(password.len - x, 0))
of chr(0x0):
# modifier key - ignore - for details see
# https://github.com/nim-lang/Nim/issues/7764
continue
else: else:
password.string.add(toUTF8(c.Rune)) password.string.add(toUTF8(c.Rune))
stdout.write "\n" stdout.write "\n"

View file

@ -1173,8 +1173,12 @@ proc formatToken(dt: DateTime, token: string, buf: var string) =
of "dddd": of "dddd":
buf.add($dt.weekday) buf.add($dt.weekday)
of "h": of "h":
buf.add($(if dt.hour > 12: dt.hour - 12 else: dt.hour)) if dt.hour == 0: buf.add("12")
else: buf.add($(if dt.hour > 12: dt.hour - 12 else: dt.hour))
of "hh": of "hh":
if dt.hour == 0:
buf.add("12")
else:
let amerHour = if dt.hour > 12: dt.hour - 12 else: dt.hour let amerHour = if dt.hour > 12: dt.hour - 12 else: dt.hour
if amerHour < 10: if amerHour < 10:
buf.add('0') buf.add('0')
@ -1503,11 +1507,15 @@ proc parseToken(dt: var DateTime; token, value: string; j: var int) =
dt.second = value[j..j+1].parseInt() dt.second = value[j..j+1].parseInt()
j += 2 j += 2
of "t": of "t":
if value[j] == 'P' and dt.hour > 0 and dt.hour < 12: if value[j] == 'A' and dt.hour == 12:
dt.hour = 0
elif value[j] == 'P' and dt.hour > 0 and dt.hour < 12:
dt.hour += 12 dt.hour += 12
j += 1 j += 1
of "tt": of "tt":
if value[j..j+1] == "PM" and dt.hour > 0 and dt.hour < 12: if value[j..j+1] == "AM" and dt.hour == 12:
dt.hour = 0
elif value[j..j+1] == "PM" and dt.hour > 0 and dt.hour < 12:
dt.hour += 12 dt.hour += 12
j += 2 j += 2
of "yy": of "yy":

View file

@ -18,14 +18,12 @@ type
hostname*, port*, path*, query*, anchor*: string hostname*, port*, path*, query*, anchor*: string
opaque*: bool opaque*: bool
{.deprecated: [TUrl: Url, TUri: Uri].}
{.push warning[deprecated]: off.} {.push warning[deprecated]: off.}
proc `$`*(url: Url): string {.deprecated.} = proc `$`*(url: Url): string {.deprecated: "use Uri instead".} =
## **Deprecated since 0.9.6**: Use ``Uri`` instead. ## **Deprecated since 0.9.6**: Use ``Uri`` instead.
return string(url) return string(url)
proc `/`*(a, b: Url): Url {.deprecated.} = proc `/`*(a, b: Url): Url {.deprecated: "use Uri instead".} =
## Joins two URLs together, separating them with / if needed. ## Joins two URLs together, separating them with / if needed.
## ##
## **Deprecated since 0.9.6**: Use ``Uri`` instead. ## **Deprecated since 0.9.6**: Use ``Uri`` instead.
@ -40,32 +38,43 @@ proc `/`*(a, b: Url): Url {.deprecated.} =
urlS.add(bs) urlS.add(bs)
result = Url(urlS) result = Url(urlS)
proc add*(url: var Url, a: Url) {.deprecated.} = proc add*(url: var Url, a: Url) {.deprecated: "use Uri instead".} =
## Appends url to url. ## Appends url to url.
## ##
## **Deprecated since 0.9.6**: Use ``Uri`` instead. ## **Deprecated since 0.9.6**: Use ``Uri`` instead.
url = url / a url = url / a
{.pop.} {.pop.}
proc encodeUrl*(s: string): string = proc encodeUrl*(s: string, usePlus=true): string =
## Encodes a value to be HTTP safe: This means that characters in the set ## Encodes a URL according to RFC3986.
## ``{'A'..'Z', 'a'..'z', '0'..'9', '_'}`` are carried over to the result, ##
## a space is converted to ``'+'`` and every other character is encoded as ## This means that characters in the set
## ``'%xx'`` where ``xx`` denotes its hexadecimal value. ## ``{'a'..'z', 'A'..'Z', '0'..'9', '-', '.', '_', '~'}`` are
## carried over to the result.
## All other characters are encoded as ``''%xx'`` where ``xx``
## denotes its hexadecimal value.
##
## As a special rule, when the value of ``usePlus`` is true,
## spaces are encoded as ``'+'`` instead of ``'%20'``.
result = newStringOfCap(s.len + s.len shr 2) # assume 12% non-alnum-chars result = newStringOfCap(s.len + s.len shr 2) # assume 12% non-alnum-chars
for i in 0..s.len-1: let fromSpace = if usePlus: "+" else: "%20"
case s[i] for c in s:
of 'a'..'z', 'A'..'Z', '0'..'9', '_': add(result, s[i]) case c
of ' ': add(result, '+') of 'a'..'z', 'A'..'Z', '0'..'9', '-', '.', '_', '~': add(result, c)
of ' ': add(result, fromSpace)
else: else:
add(result, '%') add(result, '%')
add(result, toHex(ord(s[i]), 2)) add(result, toHex(ord(c), 2))
proc decodeUrl*(s: string): string = proc decodeUrl*(s: string, decodePlus=true): string =
## Decodes a value from its HTTP representation: This means that a ``'+'`` ## Decodes a URL according to RFC3986.
## is converted to a space, ``'%xx'`` (where ``xx`` denotes a hexadecimal ##
## value) is converted to the character with ordinal number ``xx``, and ## This means that any ``'%xx'`` (where ``xx`` denotes a hexadecimal
## value) are converted to the character with ordinal number ``xx``,
## and every other character is carried over. ## and every other character is carried over.
##
## As a special rule, when the value of ``decodePlus`` is true, ``'+'``
## characters are converted to a space.
proc handleHexChar(c: char, x: var int) {.inline.} = proc handleHexChar(c: char, x: var int) {.inline.} =
case c case c
of '0'..'9': x = (x shl 4) or (ord(c) - ord('0')) of '0'..'9': x = (x shl 4) or (ord(c) - ord('0'))
@ -84,7 +93,11 @@ proc decodeUrl*(s: string): string =
handleHexChar(s[i+2], x) handleHexChar(s[i+2], x)
inc(i, 2) inc(i, 2)
result[j] = chr(x) result[j] = chr(x)
of '+': result[j] = ' ' of '+':
if decodePlus:
result[j] = ' '
else:
result[j] = s[i]
else: result[j] = s[i] else: result[j] = s[i]
inc(i) inc(i)
inc(j) inc(j)
@ -370,6 +383,9 @@ when isMainModule:
const test1 = "abc\L+def xyz" const test1 = "abc\L+def xyz"
doAssert encodeUrl(test1) == "abc%0A%2Bdef+xyz" doAssert encodeUrl(test1) == "abc%0A%2Bdef+xyz"
doAssert decodeUrl(encodeUrl(test1)) == test1 doAssert decodeUrl(encodeUrl(test1)) == test1
doAssert encodeUrl(test1, false) == "abc%0A%2Bdef%20xyz"
doAssert decodeUrl(encodeUrl(test1, false), false) == test1
doAssert decodeUrl(encodeUrl(test1)) == test1
block: block:
let str = "http://localhost" let str = "http://localhost"

View file

@ -1069,17 +1069,15 @@ proc splitData*(textNode: PText, offset: int): PText =
var newNode: PText = textNode.fOwnerDocument.createTextNode(right) var newNode: PText = textNode.fOwnerDocument.createTextNode(right)
return newNode return newNode
# ProcessingInstruction # ProcessingInstruction
proc target*(pi: PProcessingInstruction): string = proc target*(pi: PProcessingInstruction): string =
## Returns the Processing Instructions target ## Returns the Processing Instructions target
return pi.fTarget return pi.fTarget
proc escapeXml*(s: string; result: var string) =
# --Other stuff-- ## Prepares a string for insertion into a XML document
# Writer ## by escaping the XML special characters.
proc addEscaped(s: string): string =
result = "" result = ""
for c in items(s): for c in items(s):
case c case c
@ -1089,11 +1087,20 @@ proc addEscaped(s: string): string =
of '"': result.add("&quot;") of '"': result.add("&quot;")
else: result.add(c) else: result.add(c)
proc escapeXml*(s: string): string =
## Prepares a string for insertion into a XML document
## by escaping the XML special characters.
result = newStringOfCap(s.len + s.len shr 4)
escapeXml(s, result)
# --Other stuff--
# Writer
proc nodeToXml(n: PNode, indent: int = 0): string = proc nodeToXml(n: PNode, indent: int = 0): string =
result = spaces(indent) & "<" & n.nodeName result = spaces(indent) & "<" & n.nodeName
if not isNil(n.attributes): if not isNil(n.attributes):
for i in items(n.attributes): for i in items(n.attributes):
result.add(" " & i.name & "=\"" & addEscaped(i.value) & "\"") result.add(" " & i.name & "=\"" & escapeXml(i.value) & "\"")
if isNil(n.childNodes) or n.childNodes.len() == 0: if isNil(n.childNodes) or n.childNodes.len() == 0:
result.add("/>") # No idea why this doesn't need a \n :O result.add("/>") # No idea why this doesn't need a \n :O
@ -1106,7 +1113,7 @@ proc nodeToXml(n: PNode, indent: int = 0): string =
result.add(nodeToXml(i, indent + 2)) result.add(nodeToXml(i, indent + 2))
of TextNode: of TextNode:
result.add(spaces(indent * 2)) result.add(spaces(indent * 2))
result.add(addEscaped(i.nodeValue)) result.add(escapeXml(i.nodeValue))
of CDataSectionNode: of CDataSectionNode:
result.add(spaces(indent * 2)) result.add(spaces(indent * 2))
result.add("<![CDATA[" & i.nodeValue & "]]>") result.add("<![CDATA[" & i.nodeValue & "]]>")

View file

@ -16,8 +16,6 @@ type
## for invalid XML. ## for invalid XML.
errors*: seq[string] ## All detected parsing errors. errors*: seq[string] ## All detected parsing errors.
{.deprecated: [EInvalidXml: XmlError].}
proc raiseInvalidXml(errors: seq[string]) = proc raiseInvalidXml(errors: seq[string]) =
var e: ref XmlError var e: ref XmlError
new(e) new(e)

View file

@ -33,9 +33,6 @@ type
fAttr: XmlAttributes fAttr: XmlAttributes
fClientData: int ## for other clients fClientData: int ## for other clients
{.deprecated: [PXmlNode: XmlNode, TXmlNodeKind: XmlNodeKind, PXmlAttributes:
XmlAttributes, TXmlNode: XmlNodeObj].}
proc newXmlNode(kind: XmlNodeKind): XmlNode = proc newXmlNode(kind: XmlNodeKind): XmlNode =
## creates a new ``XmlNode``. ## creates a new ``XmlNode``.
new(result) new(result)
@ -155,11 +152,6 @@ proc `[]`* (n: var XmlNode, i: int): var XmlNode {.inline.} =
assert n.k == xnElement assert n.k == xnElement
result = n.s[i] result = n.s[i]
proc mget*(n: var XmlNode, i: int): var XmlNode {.inline, deprecated.} =
## returns the `i`'th child of `n` so that it can be modified. Use ```[]```
## instead.
n[i]
iterator items*(n: XmlNode): XmlNode {.inline.} = iterator items*(n: XmlNode): XmlNode {.inline.} =
## iterates over any child of `n`. ## iterates over any child of `n`.
assert n.k == xnElement assert n.k == xnElement
@ -319,8 +311,8 @@ proc xmlConstructor(a: NimNode): NimNode {.compileTime.} =
if a.kind == nnkCall: if a.kind == nnkCall:
result = newCall("newXmlTree", toStrLit(a[0])) result = newCall("newXmlTree", toStrLit(a[0]))
var attrs = newNimNode(nnkBracket, a) var attrs = newNimNode(nnkBracket, a)
var newStringTabCall = newCall("newStringTable", attrs, var newStringTabCall = newCall(bindSym"newStringTable", attrs,
newIdentNode("modeCaseSensitive")) bindSym"modeCaseSensitive")
var elements = newNimNode(nnkBracket, a) var elements = newNimNode(nnkBracket, a)
for i in 1..a.len-1: for i in 1..a.len-1:
if a[i].kind == nnkExprEqExpr: if a[i].kind == nnkExprEqExpr:

View file

@ -4172,8 +4172,9 @@ template doAssertRaises*(exception, code: untyped): typed =
if wrong: if wrong:
raiseAssert(astToStr(exception) & " wasn't raised by:\n" & astToStr(code)) raiseAssert(astToStr(exception) & " wasn't raised by:\n" & astToStr(code))
when defined(cpp) and appType != "lib" and not defined(js) and when defined(cpp) and appType != "lib" and
not defined(nimscript) and hostOS != "standalone": not defined(js) and not defined(nimscript) and
hostOS != "standalone" and not defined(noCppExceptions):
proc setTerminate(handler: proc() {.noconv.}) proc setTerminate(handler: proc() {.noconv.})
{.importc: "std::set_terminate", header: "<exception>".} {.importc: "std::set_terminate", header: "<exception>".}
setTerminate proc() {.noconv.} = setTerminate proc() {.noconv.} =

View file

@ -74,7 +74,7 @@ proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) =
var dst = cast[ByteAddress](cast[PPointer](dest)[]) var dst = cast[ByteAddress](cast[PPointer](dest)[])
for i in 0..seq.len-1: for i in 0..seq.len-1:
genericAssignAux( genericAssignAux(
cast[pointer](dst +% i*% mt.base.size +% GenericSeqSize), cast[pointer](dst +% i *% mt.base.size +% GenericSeqSize),
cast[pointer](cast[ByteAddress](s2) +% i *% mt.base.size +% cast[pointer](cast[ByteAddress](s2) +% i *% mt.base.size +%
GenericSeqSize), GenericSeqSize),
mt.base, shallow) mt.base, shallow)
@ -100,8 +100,8 @@ proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) =
genericAssignAux(dest, src, mt.node, shallow) genericAssignAux(dest, src, mt.node, shallow)
of tyArray, tyArrayConstr: of tyArray, tyArrayConstr:
for i in 0..(mt.size div mt.base.size)-1: for i in 0..(mt.size div mt.base.size)-1:
genericAssignAux(cast[pointer](d +% i*% mt.base.size), genericAssignAux(cast[pointer](d +% i *% mt.base.size),
cast[pointer](s +% i*% mt.base.size), mt.base, shallow) cast[pointer](s +% i *% mt.base.size), mt.base, shallow)
of tyRef: of tyRef:
unsureAsgnRef(cast[PPointer](dest), cast[PPointer](s)[]) unsureAsgnRef(cast[PPointer](dest), cast[PPointer](s)[])
of tyOptAsRef: of tyOptAsRef:
@ -166,8 +166,8 @@ proc genericAssignOpenArray(dest, src: pointer, len: int,
d = cast[ByteAddress](dest) d = cast[ByteAddress](dest)
s = cast[ByteAddress](src) s = cast[ByteAddress](src)
for i in 0..len-1: for i in 0..len-1:
genericAssign(cast[pointer](d +% i*% mt.base.size), genericAssign(cast[pointer](d +% i *% mt.base.size),
cast[pointer](s +% i*% mt.base.size), mt.base) cast[pointer](s +% i *% mt.base.size), mt.base)
proc objectInit(dest: pointer, typ: PNimType) {.compilerProc, benign.} proc objectInit(dest: pointer, typ: PNimType) {.compilerProc, benign.}
proc objectInitAux(dest: pointer, n: ptr TNimNode) {.benign.} = proc objectInitAux(dest: pointer, n: ptr TNimNode) {.benign.} =
@ -235,7 +235,7 @@ proc genericReset(dest: pointer, mt: PNimType) =
pint[] = nil pint[] = nil
of tyArray, tyArrayConstr: of tyArray, tyArrayConstr:
for i in 0..(mt.size div mt.base.size)-1: for i in 0..(mt.size div mt.base.size)-1:
genericReset(cast[pointer](d +% i*% mt.base.size), mt.base) genericReset(cast[pointer](d +% i *% mt.base.size), mt.base)
else: else:
zeroMem(dest, mt.size) # set raw bits to zero zeroMem(dest, mt.size) # set raw bits to zero

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