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
via ``{.experimental: "notnil"}`` as we are still not pleased with how this
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
@ -38,6 +41,9 @@
#### Breaking changes in the compiler
- The undocumented ``#? braces`` parsing mode was removed.
- The undocumented PHP backend was removed.
### Library additions
- ``re.split`` now also supports the ``maxsplit`` parameter for consistency
@ -63,6 +69,11 @@
fields.
- ``system.SomeReal`` is now called ``SomeFloat`` for consistency and
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
@ -86,11 +97,18 @@
- ``nil`` for strings/seqs is finally gone. Instead the default value for
these is ``"" / @[]``.
- Accessing the binary zero terminator in Nim's native strings
is now invalid. Internally a Nim string still has the trailing zero for
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

View file

@ -1615,6 +1615,19 @@ proc originatingModule*(s: PSym): PSym =
proc isRoutine*(s: PSym): bool {.inline.} =
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.} =
result = isRoutine(s) and s.ast.sons[patternPos].kind != nkEmpty
@ -1671,7 +1684,7 @@ proc isException*(t: PType): bool =
var base = t
while base != nil:
if base.sym.magic == mException:
if base.sym != nil and base.sym.magic == mException:
return true
base = base.lastSon
return false

View file

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

View file

@ -265,7 +265,7 @@ proc rdCharLoc(a: TLoc): Rope =
proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc,
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
includeHeader(p.module, "<new>")
linefmt(p, section, "new ($1) $2;$n", rdLoc(a), getTypeDesc(p.module, t))
@ -746,7 +746,7 @@ proc genProcAux(m: BModule, prc: PSym) =
else:
fillResult(resNode)
assignParam(p, res)
resetLoc(p, res.loc)
if sfNoInit notin prc.flags: resetLoc(p, res.loc)
if skipTypes(res.typ, abstractInst).kind == tyArray:
#incl(res.loc.flags, lfIndirect)
res.loc.storage = OnUnknown

View file

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

View file

@ -790,7 +790,7 @@ proc writeOutputJson*(d: PDoc, filename, outExt: string,
discard "fixme: error report"
proc commandDoc*() =
var ast = parseFile(gProjectMainIdx.FileIndex, newIdentCache())
var ast = parseFile(gProjectMainIdx.FileIndex, newIdentCache(), newConfigRef())
if ast == nil: return
var d = newDocumentor(gProjectFull, options.gConfigVars)
d.hasToc = true
@ -840,7 +840,7 @@ proc commandRst2TeX*() =
commandRstAux(gProjectFull, TexExt)
proc commandJson*() =
var ast = parseFile(gProjectMainIdx.FileIndex, newIdentCache())
var ast = parseFile(gProjectMainIdx.FileIndex, newIdentCache(), newConfigRef())
if ast == nil: return
var d = newDocumentor(gProjectFull, options.gConfigVars)
d.hasToc = true
@ -855,7 +855,7 @@ proc commandJson*() =
writeRope(content, getOutFile(gProjectFull, JsonExt), useWarning = false)
proc commandTags*() =
var ast = parseFile(gProjectMainIdx.FileIndex, newIdentCache())
var ast = parseFile(gProjectMainIdx.FileIndex, newIdentCache(), newConfigRef())
if ast == nil: return
var d = newDocumentor(gProjectFull, options.gConfigVars)
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 ``()``
# `n` is then a nkSym or something similar
var totalParams = case n.kind
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit: n.len-1
of nkCallKinds: n.len-1
else: 0
var

View file

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

View file

@ -16,6 +16,13 @@ import
proc evalImport*(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) =
var check = strTableGet(c.importTable.symbols, s.name)
if check == nil:
@ -198,9 +205,5 @@ proc evalImportExcept*(c: PContext, n: PNode): PNode =
if m != nil:
n.sons[0] = newSymNode(m)
addDecl(c, m, n.info) # add symbol to symbol table of module
var exceptSet = initIntSet()
for i in countup(1, sonsLen(n) - 1):
let ident = lookups.considerQuotedIdent(n.sons[i])
exceptSet.incl(ident.id)
importAllSymbolsExcept(c, m, exceptSet)
importAllSymbolsExcept(c, m, readExceptSet(n))
#importForwarded(c, m.ast, exceptSet)

View file

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

View file

@ -129,9 +129,10 @@ proc commandEval(graph: ModuleGraph; cache: IdentCache; exp: string) =
interactivePasses(graph, cache)
compileSystemModule(graph, cache)
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 stream = llStreamOpen(f, fmRead)
if stream != nil:
@ -139,7 +140,7 @@ proc commandScan(cache: IdentCache) =
L: TLexer
tok: TToken
initToken(tok)
openLexer(L, f, stream, cache)
openLexer(L, f, stream, cache, config)
while true:
rawGetTok(L, tok)
printTok(tok)
@ -265,11 +266,11 @@ proc mainCommand*(graph: ModuleGraph; cache: IdentCache) =
of "parse":
gCmd = cmdParse
wantMainModule()
discard parseFile(FileIndex gProjectMainIdx, cache)
discard parseFile(FileIndex gProjectMainIdx, cache, graph.config)
of "scan":
gCmd = cmdScan
wantMainModule()
commandScan(cache)
commandScan(cache, graph.config)
msgWriteln("Beware: Indentation tokens depend on the parser's state!")
of "secret":
gCmd = cmdInteractive
@ -291,7 +292,7 @@ proc mainCommand*(graph: ModuleGraph; cache: IdentCache) =
let usedMem = formatSize(getMaxMem()) & " peakmem"
else:
let usedMem = formatSize(getTotalMem())
rawMessage(hintSuccessX, [$gLinesCompiled,
rawMessage(hintSuccessX, [$graph.config.linesCompiled,
formatFloat(epochTime() - gLastCmdTime, ffDecimal, 3),
usedMem,
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;
cache: IdentCache): PNode {.procvar.} =
result = syntaxes.parseFile(fileIdx, cache)
result = syntaxes.parseFile(fileIdx, cache, graph.config)
graph.addDep(s, fileIdx)
graph.addIncludeDep(s.position.FileIndex, fileIdx)

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -27,7 +27,7 @@ when isMainModule:
outp.close
import
llstream, lexer, idents, strutils, ast, astalgo, msgs
llstream, lexer, idents, strutils, ast, astalgo, msgs, options
type
TParser* = object # A TParser object represents a file that
@ -84,20 +84,20 @@ proc getTok(p: var TParser) =
p.hasProgress = true
proc openParser*(p: var TParser, fileIdx: FileIndex, inputStream: PLLStream,
cache: IdentCache;
cache: IdentCache; config: ConfigRef;
strongSpaces=false) =
## Open a parser, using the given arguments to set up its internal state.
##
initToken(p.tok)
openLexer(p.lex, fileIdx, inputStream, cache)
openLexer(p.lex, fileIdx, inputStream, cache, config)
getTok(p) # read the first token
p.firstTok = true
p.strongSpaces = strongSpaces
proc openParser*(p: var TParser, filename: string, inputStream: PLLStream,
cache: IdentCache;
cache: IdentCache; config: ConfigRef;
strongSpaces=false) =
openParser(p, filename.fileInfoIdx, inputStream, cache, strongSpaces)
openParser(p, filename.fileInfoIdx, inputStream, cache, config, strongSpaces)
proc closeParser(p: var TParser) =
## Close a parser, freeing up its resources.
@ -268,13 +268,9 @@ proc isUnary(p: TParser): bool =
proc checkBinary(p: TParser) {.inline.} =
## Check if the current parser token is a binary operator.
# 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:
parMessage(p, errGenerated,
"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")
parMessage(p, warnInconsistentSpacing, prettyTok(p.tok))
#| module = stmt ^* (';' / IND{=})
#|
@ -706,10 +702,17 @@ proc namedParams(p: var TParser, callee: PNode,
# progress guaranteed
exprColonEqExprListAux(p, endTok, result)
proc commandParam(p: var TParser): PNode =
proc commandParam(p: var TParser, isFirstParam: var bool): PNode =
result = parseExpr(p)
if p.tok.tokType == tkDo:
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 =
#| primarySuffix = '(' (exprColonEqExpr comma?)* ')' doBlocks?
@ -744,17 +747,19 @@ proc primarySuffix(p: var TParser, r: PNode, baseIndent: int): PNode =
# progress guaranteed
somePar()
result = namedParams(p, result, nkCurlyExpr, tkCurlyRi)
of tkSymbol, tkAccent, tkIntLit..tkCharLit, tkNil, tkCast, tkAddr, tkType:
if p.inPragma == 0:
of tkSymbol, tkAccent, tkIntLit..tkCharLit, tkNil, tkCast, tkAddr, tkType,
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
# solution, but pragmas.nim can't handle that
let a = result
result = newNodeP(nkCommand, p)
addSon(result, a)
var isFirstParam = true
when true:
# progress NOT guaranteed
p.hasProgress = false
addSon result, commandParam(p)
addSon result, commandParam(p, isFirstParam)
if not p.hasProgress: break
else:
while p.tok.tokType != tkEof:
@ -1306,17 +1311,18 @@ proc parseExprStmt(p: var TParser): PNode =
addSon(result, b)
else:
# 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:
result = a
while true:
getTok(p)
optInd(p, result)
addSon(result, commandParam(p))
addSon(result, commandParam(p, isFirstParam))
if p.tok.tokType != tkComma: break
elif p.tok.indent < 0 and isExprStart(p):
result = newNode(nkCommand, a.info, @[a])
while true:
addSon(result, commandParam(p))
addSon(result, commandParam(p, isFirstParam))
if p.tok.tokType != tkComma: break
getTok(p)
optInd(p, result)
@ -2181,8 +2187,8 @@ proc parseTopLevelStmt(p: var TParser): PNode =
if result.kind == nkEmpty: parMessage(p, errExprExpected, p.tok)
break
proc parseString*(s: string; cache: IdentCache; filename: string = "";
line: int = 0;
proc parseString*(s: string; cache: IdentCache; config: ConfigRef;
filename: string = ""; line: int = 0;
errorHandler: TErrorHandler = nil): PNode =
## Parses a string into an AST, returning the top node.
## `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
# spaces...
parser.lex.errorHandler = errorHandler
openParser(parser, filename, stream, cache, false)
openParser(parser, filename, stream, cache, config, false)
result = parser.parseAll
closeParser(parser)

View file

@ -207,7 +207,7 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream,
else:
s = stream
while true:
openParsers(p, fileIdx, s, cache)
openParsers(p, fileIdx, s, cache, graph.config)
if sfSystemModule notin module.flags:
# 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)
of wThreadVar:
noVal(it)
incl(sym.flags, sfThread)
incl(sym.flags, {sfThread, sfGlobal})
of wDeadCodeElimUnused: discard # deprecated, dead code elim always on
of wNoForward: pragmaNoForward(c, it)
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;
cache: IdentCache): PNode {.procvar.} =
result = syntaxes.parseFile(fileIdx, cache)
result = syntaxes.parseFile(fileIdx, cache, graph.config)
graph.addDep(s, 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;
config: ConfigRef): PEvalContext =
# For Nimble we need to export 'setupVM'.
result = newCtx(module, cache)
result = newCtx(module, cache, config)
result.mode = emRepl
registerAdditionalOps(result)

View file

@ -313,7 +313,7 @@ proc tryConstExpr(c: PContext, n: PNode): PNode =
msgs.gErrorMax = high(int)
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:
result = nil
else:
@ -334,7 +334,7 @@ proc semConstExpr(c: PContext, n: PNode): PNode =
result = getConstExpr(c.module, e)
if result == nil:
#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 e.info != n.info:
pushInfoContext(n.info)
@ -439,7 +439,7 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
#if c.evalContext == nil:
# 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:
result = semAfterMacroCall(c, n, result, sym, flags)
result = wrapInComesFrom(nOrig.info, sym, result)

View file

@ -89,6 +89,7 @@ type
ambiguousSymbols*: IntSet # ids of all ambiguous symbols (cannot
# store this info in the syms themselves!)
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
compilesContextId*: int # > 0 if we are in a ``compiles`` magic
compilesContextIdGenerator*: int

View file

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

View file

@ -199,6 +199,10 @@ proc semBindSym(c: PContext, n: PNode): PNode =
if s != nil:
# we need to mark all symbols:
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)
else:
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)
checkNilable(v)
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 =
result = copyNode(n)
@ -1753,9 +1754,11 @@ proc semPragmaBlock(c: PContext, n: PNode): PNode =
proc semStaticStmt(c: PContext, n: PNode): PNode =
#echo "semStaticStmt"
#writeStackTrace()
inc c.inStaticContext
let a = semStmt(c, n.sons[0])
dec c.inStaticContext
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.sons[0] = emptyNode

View file

@ -1962,7 +1962,8 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
inc(m.genericMatches)
if arg.typ == nil:
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)
elif arg.typ.isEmptyContainer:
result = arg.copyTree
@ -2032,8 +2033,9 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
y.calleeSym = m.calleeSym
z.calleeSym = m.calleeSym
var best = -1
for i in countup(0, sonsLen(arg) - 1):
if arg.sons[i].sym.kind in {skProc, skFunc, skMethod, skConverter, skIterator}:
for i in 0 ..< arg.len:
if arg.sons[i].sym.kind in {skProc, skFunc, skMethod, skConverter,
skIterator, skMacro, skTemplate}:
copyCandidate(z, m)
z.callee = arg.sons[i].typ
if tfUnresolved in z.callee.flags: continue
@ -2062,6 +2064,7 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
x = z
elif cmp == 0:
y = z # z is as good as x
if x.state == csEmpty:
result = nil
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!
# See tsymchoice_for_expr as an example. 'f.kind == tyExpr' should match
# anyway:
if f.kind == tyExpr: result = arg
if f.kind in {tyExpr, tyStmt}: result = arg
else: result = nil
else:
# 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
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)
if container.isNil:
container = newNodeIT(nkArgList, n.sons[a].info, arrayConstr(c, n.info))

View file

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

View file

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

View file

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

View file

@ -10,7 +10,7 @@
## 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.
import ast, passes, msgs, idents, intsets
import ast, passes, msgs, idents, intsets, options
const
byteExcess* = 128 # we use excess-K for immediates
@ -206,17 +206,19 @@ type
callbacks*: seq[tuple[key: string, value: VmCallback]]
errorFlag*: string
cache*: IdentCache
config*: ConfigRef
TPosition* = distinct int
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: @[],
globals: newNode(nkStmtListExpr), constants: newNode(nkStmtList), types: @[],
prc: PProc(blocks: @[]), module: module, loopIterations: MaxLoopIterations,
comesFromHeuristic: unknownLineInfo(), callbacks: @[], errorFlag: "",
cache: cache)
cache: cache, config: conf)
proc refresh*(c: PCtx, module: PSym) =
c.module = module

View file

@ -1554,7 +1554,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
of tyCString, tyString:
result = newNodeIT(nkStrLit, info, t)
result.strVal = ""
of tyVar, tyLent, tyPointer, tyPtr, tySequence, tyExpr,
of tyVar, tyLent, tyPointer, tyPtr, tyExpr,
tyStmt, tyTypeDesc, tyStatic, tyRef, tyNil:
result = newNodeIT(nkNilLit, info, t)
of tyProc:
@ -1585,6 +1585,8 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
result = newNodeIT(nkCurly, info, t)
of tyOpt:
result = newNodeIT(nkNilLit, info, t)
of tySequence:
result = newNodeIT(nkBracket, info, t)
else:
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
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
-----------
In module related statements, if any part of the module name /
@ -7798,8 +7801,9 @@ Future directions:
Threadvar pragma
----------------
A global variable can be marked with the ``threadvar`` pragma; it is
a `thread-local`:idx: variable then:
A variable can be marked with the ``threadvar`` pragma, which makes it a
`thread-local`:idx: variable; Additionally, this implies all the effects
of the ``global`` pragma.
.. code-block:: nim
var checkpoints* {.threadvar.}: seq[string]

View file

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

View file

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

View file

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

View file

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

View file

@ -13,9 +13,6 @@ type
SortOrder* = enum ## sort order
Descending, Ascending
{.deprecated: [TSortOrder: SortOrder].}
proc `*`*(x: int, order: SortOrder): int {.inline.} =
## flips `x` if ``order == Descending``;
## 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 =
## 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)
while result < b:
var mid = (result + b) div 2
@ -76,14 +82,9 @@ proc binarySearch*[T](a: openArray[T], key: T): int =
else: b = mid
if result >= len(a) or a[result] != key: result = -1
proc smartBinarySearch*[T](a: openArray[T], key: T): int =
## ``a.len`` must be a power of 2 for this to work.
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
proc smartBinarySearch*[T](a: openArray[T], key: T): int {.deprecated.} =
## **Deprecated since version 0.18.1**; Use ``binarySearch`` instead.
binarySearch(a,key)
const
onlySafeCode = true
@ -363,10 +364,11 @@ when isMainModule:
var srt1 = [1,2,3,4,4,4,4,5]
var srt2 = ["iello","hello"]
var srt3 = [1.0,1.0,1.0]
var srt4: seq[int] = @[]
var srt4: seq[int]
assert srt1.isSorted(cmp) == true
assert srt2.isSorted(cmp) == false
assert srt3.isSorted(cmp) == true
assert srt4.isSorted(cmp) == true
var srtseq = newSeq[int]()
assert srtseq.isSorted(cmp) == true
# Tests for reversed
@ -515,3 +517,23 @@ when isMainModule:
block fillEmptySeq:
var s = newSeq[int]()
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
cause*: FutureBase
{.deprecated: [PFutureBase: FutureBase, PFuture: Future].}
when not defined(release):
var currentID = 0

View file

@ -60,9 +60,6 @@ type
reusePort: bool
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,
maxBody = 8388608): AsyncHttpServer =
## Creates a new ``AsyncHttpServer`` instance.

View file

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

View file

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

View file

@ -120,6 +120,13 @@ iterator items*[A](s: HashSet[A]): A =
for h in 0..high(s.data):
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
growthFactor = 2
@ -690,6 +697,13 @@ iterator items*[A](s: OrderedSet[A]): A =
forAllOrderedPairs:
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] =
assert s.isValid, "The set needs to be initialized"
forAllOrderedPairs:

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -45,7 +45,6 @@ type
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``
## operator instead of ``mod`` for truncation of the hash value.
{.deprecated: [THash: Hash].}
proc `!&`*(h: Hash, val: int): Hash {.inline.} =
## 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
tagVideo, ## the HTML ``video`` element
tagWbr ## the HTML ``wbr`` element
{.deprecated: [THtmlTag: HtmlTag].}
const
tagToStr* = [

View file

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

View file

@ -45,10 +45,6 @@ type
## TCP/IP tunnel, usually used for proxies.
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
Http100* = HttpCode(100)

View file

@ -110,7 +110,6 @@ when false:
# TODO: Fix this, or get rid of it.
type
RequestMethod = enum reqGet, reqPost
{.deprecated: [TRequestMethod: RequestMethod].}
proc executeCgi(client: Socket, path, query: string, meth: RequestMethod) =
var env = newStringTable(modeCaseInsensitive)
@ -225,7 +224,6 @@ type
PAsyncHTTPServer* = ref AsyncHTTPServer
AsyncHTTPServer = object of Server
asyncSocket: AsyncSocket
{.deprecated: [TAsyncHTTPServer: AsyncHTTPServer, TServer: Server].}
proc open*(s: var Server, port = Port(80), reuseAddr = false) =
## 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)
proc newAsyncNativeSocket*(domain: cint, sockType: cint,
protocol: cint): AsyncFD {.deprecated.} =
protocol: cint): AsyncFD {.deprecated: "use createAsyncNativeSocket instead".} =
createAsyncNativeSocketImpl(domain, sockType, protocol)
proc newAsyncNativeSocket*(domain: Domain = Domain.AF_INET,
sockType: SockType = SOCK_STREAM,
protocol: Protocol = IPPROTO_TCP): AsyncFD
{.deprecated.} =
{.deprecated: "use createAsyncNativeSocket instead".} =
createAsyncNativeSocketImpl(domain, sockType, protocol)
when defined(windows) or defined(nimdoc):

View file

@ -12,50 +12,6 @@ when not defined(nimscript):
when defined(windows):
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 `$`*(err: OSErrorCode): string {.borrow.}

View file

@ -158,9 +158,6 @@ type
JsonKindError* = object of ValueError ## raised by the ``to`` macro if the
## JSON kind is incorrect.
{.deprecated: [TJsonEventKind: JsonEventKind, TJsonError: JsonError,
TJsonParser: JsonParser, TTokKind: TokKind].}
const
errorMessages: array[JsonError, string] = [
"no error",
@ -622,9 +619,6 @@ type
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.} =
## raises an `EJsonParsingError` exception.
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
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.
getBiggestInt(n, default)
@ -709,7 +703,7 @@ proc getFloat*(n: JsonNode, default: float = 0.0): float =
of JInt: return float(n.num)
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.
getFloat(n, default)
@ -720,7 +714,7 @@ proc getBool*(n: JsonNode, default: bool = false): bool =
if n.isNil or n.kind != JBool: return default
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.
getBool(n, default)
@ -946,7 +940,7 @@ proc contains*(node: JsonNode, val: JsonNode): bool =
assert(node.kind == JArray)
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.
proc `[]=`*(obj: JsonNode, key: string, val: JsonNode) {.inline.} =
@ -1277,7 +1271,6 @@ else:
from math import `mod`
type
JSObject = object
{.deprecated: [TJSObject: JSObject].}
proc parseNativeJson(x: cstring): JSObject {.importc: "JSON.parse".}

View file

@ -40,8 +40,6 @@ type
offsetBase*: int # use ``offsetBase + bufpos`` to get the offset
refillChars: set[char]
{.deprecated: [TBaseLexer: BaseLexer].}
const
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...
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
level {.threadvar.}: Level ## global log filter
handlers {.threadvar.}: seq[Logger] ## handlers with their own log levels

View file

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

View file

@ -29,11 +29,21 @@ proc binom*(n, k: int): int {.noSideEffect.} =
for i in countup(2, k):
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.
result = 1
for i in countup(2, n):
result = result * i
const factTable =
when sizeof(int) == 4:
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.}

View file

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

View file

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

View file

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

View file

@ -85,9 +85,6 @@ type
length*: int
addrList*: seq[string]
{.deprecated: [TPort: Port, TDomain: Domain, TType: SockType,
TProtocol: Protocol, TServent: Servent, THostent: Hostent].}
when useWinVersion:
let
osInvalidSocket* = winlean.INVALID_SOCKET
@ -640,7 +637,7 @@ proc pruneSocketSet(s: var seq[SocketHandle], fd: var TFdSet) =
inc(i)
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
## 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

View file

@ -110,9 +110,6 @@ when defineSsl:
serverGetPskFunc: SslServerGetPskFunc
clientGetPskFunc: SslClientGetPskFunc
{.deprecated: [ESSL: SSLError, TSSLCVerifyMode: SSLCVerifyMode,
TSSLProtVersion: SSLProtVersion, PSSLContext: SSLContext,
TSSLAcceptResult: SSLAcceptResult].}
else:
type
SslContext* = void # TODO: Workaround #4797.
@ -159,10 +156,6 @@ type
Peek,
SafeDisconn ## Ensures disconnection exceptions (ECONNRESET, EPIPE etc) are not thrown.
{.deprecated: [TSocketFlags: SocketFlag, ETimeout: TimeoutError,
TReadLineResult: ReadLineResult, TSOBool: SOBool, PSocket: Socket,
TSocketImpl: SocketImpl].}
type
IpAddressFamily* {.pure.} = enum ## Describes the type of an IP address
IPv6, ## IPv6 address
@ -176,8 +169,6 @@ type
of IpAddressFamily.IPv4:
address_v4*: array[0..3, uint8] ## Contains the IP address in bytes in
## case of IPv4
{.deprecated: [TIpAddress: IpAddress].}
proc socketError*(socket: Socket, err: int = -1, async = false,
lastError = (-1).OSErrorCode): void {.gcsafe.}
@ -969,7 +960,7 @@ when defined(posix) and not defined(nimdoc):
raise newException(ValueError, "socket path too long")
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) =
## Connects to Unix socket on `path`.
## 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
lines: array[0..20, cstring]
files: array[0..20, cstring]
{.deprecated: [TStackTrace: StackTrace].}
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:
@ -39,7 +38,6 @@ type
total: int
st: StackTrace
ProfileData = array[0..64*1024-1, ptr ProfileEntry]
{.deprecated: [TProfileEntry: ProfileEntry, TProfileData: ProfileData].}
proc `==`(a, b: StackTrace): bool =
for i in 0 .. high(a.lines):

View file

@ -23,8 +23,6 @@ type
fuzz: int32 ##
count: int32 ##
{.deprecated: [Toid: Oid].}
proc `==`*(oid1: Oid, oid2: Oid): bool =
## Compare two Mongo Object IDs for equality
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 =
## Returns the contents of this option or `otherwise` if the option is none.
if self.has:
if self.isSome:
self.val
else:
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] =
## Remove one level of structure in a nested Option.
if self.has:
if self.isSome:
self.val
else:
none(A)
@ -179,14 +179,14 @@ proc filter*[T](self: Option[T], callback: proc (input: T): bool): Option[T] =
proc `==`*(a, b: Option): bool =
## Returns ``true`` if both ``Option``s are ``none``,
## 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 =
## 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.
## 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.
if self.has:
if self.isSome:
"Some(" & $self.val & ")"
else:
"None[" & T.name & "]"

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -37,8 +37,6 @@ type
length: int
data: string # != nil if a leaf
{.deprecated: [PRope: Rope].}
proc isConc(r: Rope): bool {.inline.} = return isNil(r.data)
# Note that the left and right pointers are not needed for leafs.

View file

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

View file

@ -316,18 +316,18 @@ else:
include ioselects/ioselectors_poll
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.
s.registerHandle(fd, events, data)
proc setEvent*(ev: SelectEvent) {.deprecated.} =
proc setEvent*(ev: SelectEvent) {.deprecated: "use trigger instead".} =
## Trigger event ``ev``.
##
## **Deprecated since v0.18.0:** Use ``trigger`` instead.
ev.trigger()
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
## ``s`` with new events set ``event``.
##

View file

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

View file

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

View file

@ -57,8 +57,6 @@ type
tags: [WriteIOEffect], gcsafe.}
flushImpl*: proc (s: Stream) {.nimcall, tags: [WriteIOEffect], gcsafe.}
{.deprecated: [PStream: Stream, TStream: StreamObj].}
proc flush*(s: Stream) =
## flushes the buffers that the stream `s` might use.
if not isNil(s.flushImpl): s.flushImpl(s)
@ -76,27 +74,14 @@ proc atEnd*(s: Stream): bool =
## been read.
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) =
## sets the position `pos` of the stream `s`.
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 =
## retrieves the current position in the stream `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 =
## low level proc that reads data into an untyped `buffer` of `bufLen` size.
result = s.readDataImpl(s, buffer, bufLen)
@ -114,11 +99,6 @@ proc readAll*(s: Stream): string =
inc 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 =
## low level proc that reads data into an untyped `buffer` of `bufLen` size
## without moving stream position
@ -153,11 +133,6 @@ proc write*(s: Stream, x: string) =
else:
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, `$`]) =
## writes one or more strings to the the stream `s` followed
## by a new line. No length field or terminating zero is written.
@ -348,8 +323,6 @@ when not defined(js):
data*: string
pos: int
{.deprecated: [PStringStream: StringStream, TStringStream: StringStreamObj].}
proc ssAtEnd(s: Stream): bool =
var s = StringStream(s)
return s.pos >= s.data.len
@ -409,7 +382,6 @@ when not defined(js):
FileStream* = ref FileStreamObj ## a stream that encapsulates a `File`
FileStreamObj* = object of Stream
f: File
{.deprecated: [PFileStream: FileStream, TFileStream: FileStreamObj].}
proc fsClose(s: Stream) =
if FileStream(s).f != nil:
@ -472,9 +444,6 @@ else:
handle*: FileHandle
pos: int
{.deprecated: [PFileHandleStream: FileHandleStream,
TFileHandleStream: FileHandleStreamObj].}
proc newEOS(msg: string): ref OSError =
new(result)
result.msg = msg

View file

@ -17,9 +17,7 @@ import
when defined(js):
{.pragma: rtlFunc.}
{.pragma: deprecatedGetFunc.}
else:
{.pragma: deprecatedGetFunc, deprecatedGet.}
{.pragma: rtlFunc, rtl.}
import os
include "system/inclrtl"
@ -38,9 +36,6 @@ type
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".} =
## returns the number of keys in `t`.
result = t.counter
@ -73,10 +68,6 @@ type
useKey ## do not replace ``$key`` if it is not found
## in the table (or in the environment)
{.deprecated: [TFormatFlag: FormatFlag].}
# implementation
const
growthFactor = 2
startSize = 64
@ -118,17 +109,12 @@ template get(t: StringTableRef, key: string) =
raise newException(KeyError, "key not found")
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
## ``KeyError`` exception is raised. One can check with ``hasKey`` whether
## the key exists.
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 =
var index = rawGet(t, key)
if index >= 0: result = t.data[index].val
@ -193,7 +179,8 @@ proc newStringTable*(mode: StringTableMode): StringTableRef {.
result.counter = 0
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.
s.mode = mode
s.counter = 0

View file

@ -1262,21 +1262,20 @@ proc initSkipTable*(a: var SkipTable, sub: string)
{.noSideEffect, rtl, extern: "nsuInitSkipTable".} =
## Preprocess table `a` for `sub`.
let m = len(sub)
let m1 = m + 1
var i = 0
while i <= 0xff-7:
a[chr(i + 0)] = m1
a[chr(i + 1)] = m1
a[chr(i + 2)] = m1
a[chr(i + 3)] = m1
a[chr(i + 4)] = m1
a[chr(i + 5)] = m1
a[chr(i + 6)] = m1
a[chr(i + 7)] = m1
a[chr(i + 0)] = m
a[chr(i + 1)] = m
a[chr(i + 2)] = m
a[chr(i + 3)] = m
a[chr(i + 4)] = m
a[chr(i + 5)] = m
a[chr(i + 6)] = m
a[chr(i + 7)] = m
i += 8
for i in 0..m-1:
a[sub[i]] = m-i
for i in 0 ..< m - 1:
a[sub[i]] = m - 1 - i
proc find*(a: SkipTable, s, sub: string, start: Natural = 0, last: Natural = 0): int
{.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`.
##
## Searching is case-sensitive. If `sub` is not in `s`, -1 is returned.
let
last = if last==0: s.high else: last
m = len(sub)
n = last + 1
# search:
var j = start
while j <= n - m:
block match:
for k in 0..m-1:
if sub[k] != s[k+j]: break match
return j
inc(j, a[s[j+m]])
sLen = last - start + 1
subLast = sub.len - 1
if subLast == -1:
# this was an empty needle string,
# we count this as match in the first possible position:
return start
# This is an implementation of the Boyer-Moore Horspool algorithms
# 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
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,
rtl, extern: "nsuReplaceStr".} =
## Replaces `sub` in `s` by the string `by`.
var a {.noinit.}: SkipTable
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)
let last = s.high
var i = 0
@ -1465,11 +1497,7 @@ proc replace*(s, sub: string, by = ""): string {.noSideEffect,
if j < 0: break
add result, substr(s, i, j - 1)
add result, by
if sub.len == 0:
if i < s.len: add result, s[i]
i = j + 1
else:
i = j + sub.len
i = j + subLen
# copy the rest:
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
## (comparable to ``\\w`` in regular expressions), otherwise it is not
## replaced.
if sub.len == 0: return s
const wordChars = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\128'..'\255'}
var a {.noinit.}: SkipTable
result = ""
@ -2326,6 +2355,57 @@ proc removePrefix*(s: var string, prefix: string) {.
s.delete(0, prefix.len - 1)
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("a", 0) == "a"
doAssert align("1232", 6) == " 1232"
@ -2347,33 +2427,13 @@ when isMainModule:
longOutp = "ThisIsOn\neVeryLon\ngStringW\nhichWeWi\nllSplitI\nntoEight\nSeparate\nPartsNow"
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"] ==
"The cat eats fish."
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("") == "lda-ldz ld abc"
doAssert "-lda-ldz -ld abc".replaceWord("") == "-lda-ldz -ld abc"
doAssert "oo".replace("", "abc") == "abcoabcoabc"
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=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
var s = "abcdef"
doAssert s.startsWith('a')
@ -2559,3 +2590,8 @@ bar
doAssert s.endsWith('\0') == false
#echo("strutils tests passed")
nonStaticTests()
staticTests()
static: staticTests()

View file

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

View file

@ -29,8 +29,6 @@ when not hasThreadSupport:
var
colorsFGCache = initTable[Color, string]()
colorsBGCache = initTable[Color, string]()
when not defined(windows):
var
styleCache = initTable[int, string]()
var
@ -41,9 +39,7 @@ var
const
fgPrefix = "\x1b[38;2;"
bgPrefix = "\x1b[48;2;"
when not defined(windows):
const
ansiResetCode* = "\e[0m"
stylePrefix = "\e["
when defined(windows):
@ -468,7 +464,7 @@ proc resetAttributes*(f: File) =
else:
discard setConsoleTextAttribute(hStdout, oldStdoutAttr)
else:
f.write("\e[0m")
f.write(ansiResetCode)
type
Style* = enum ## different styles for text output
@ -487,7 +483,7 @@ when not defined(windows):
gFG {.threadvar.}: int
gBG {.threadvar.}: int
proc getStyleStr(style: int): string =
proc ansiStyleCode*(style: int): string =
when hasThreadSupport:
result = fmt"{stylePrefix}{style}m"
else:
@ -497,6 +493,13 @@ when not defined(windows):
result = fmt"{stylePrefix}{style}m"
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]) =
## Sets the terminal style.
when defined(windows):
@ -510,7 +513,7 @@ proc setStyle*(f: File, style: set[Style]) =
discard setConsoleTextAttribute(h, old or a)
else:
for s in items(style):
f.write(getStyleStr(ord(s)))
f.write(ansiStyleCode(s))
proc writeStyled*(txt: string, style: set[Style] = {styleBright}) =
## 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.resetAttributes()
if gFG != 0:
stdout.write(getStyleStr(gFG))
stdout.write(ansiStyleCode(gFG))
if gBG != 0:
stdout.write(getStyleStr(gBG))
stdout.write(ansiStyleCode(gBG))
type
ForegroundColor* = enum ## terminal's foreground colors
@ -572,7 +575,7 @@ proc setForegroundColor*(f: File, fg: ForegroundColor, bright=false) =
else:
gFG = ord(fg)
if bright: inc(gFG, 60)
f.write(getStyleStr(gFG))
f.write(ansiStyleCode(gFG))
proc setBackgroundColor*(f: File, bg: BackgroundColor, bright=false) =
## Sets the terminal's background color.
@ -594,10 +597,18 @@ proc setBackgroundColor*(f: File, bg: BackgroundColor, bright=false) =
else:
gBG = ord(bg)
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:
let rgb = extractRGB(color)
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"
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:
let rgb = extractRGB(color)
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"
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) =
## Sets the terminal's foreground true color.
if trueColorIsEnabled:
f.write(getFGColorStr(color))
f.write(ansiForegroundColorCode(color))
proc setBackgroundColor*(f: File, color: Color) =
## Sets the terminal's background true color.
if trueColorIsEnabled:
f.write(getBGColorStr(color))
f.write(ansiBackgroundColorCode(color))
proc setTrueColor(f: File, color: Color) =
if fgSetColor:
@ -759,6 +778,10 @@ when defined(windows):
x = runeLenAt(password.string, i)
inc i, x
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:
password.string.add(toUTF8(c.Rune))
stdout.write "\n"

View file

@ -1173,8 +1173,12 @@ proc formatToken(dt: DateTime, token: string, buf: var string) =
of "dddd":
buf.add($dt.weekday)
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":
if dt.hour == 0:
buf.add("12")
else:
let amerHour = if dt.hour > 12: dt.hour - 12 else: dt.hour
if amerHour < 10:
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()
j += 2
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
j += 1
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
j += 2
of "yy":

View file

@ -18,14 +18,12 @@ type
hostname*, port*, path*, query*, anchor*: string
opaque*: bool
{.deprecated: [TUrl: Url, TUri: Uri].}
{.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.
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.
##
## **Deprecated since 0.9.6**: Use ``Uri`` instead.
@ -40,32 +38,43 @@ proc `/`*(a, b: Url): Url {.deprecated.} =
urlS.add(bs)
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.
##
## **Deprecated since 0.9.6**: Use ``Uri`` instead.
url = url / a
{.pop.}
proc encodeUrl*(s: string): string =
## Encodes a value to be HTTP safe: This means that characters in the set
## ``{'A'..'Z', 'a'..'z', '0'..'9', '_'}`` are carried over to the result,
## a space is converted to ``'+'`` and every other character is encoded as
## ``'%xx'`` where ``xx`` denotes its hexadecimal value.
proc encodeUrl*(s: string, usePlus=true): string =
## Encodes a URL according to RFC3986.
##
## This means that characters in the set
## ``{'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
for i in 0..s.len-1:
case s[i]
of 'a'..'z', 'A'..'Z', '0'..'9', '_': add(result, s[i])
of ' ': add(result, '+')
let fromSpace = if usePlus: "+" else: "%20"
for c in s:
case c
of 'a'..'z', 'A'..'Z', '0'..'9', '-', '.', '_', '~': add(result, c)
of ' ': add(result, fromSpace)
else:
add(result, '%')
add(result, toHex(ord(s[i]), 2))
add(result, toHex(ord(c), 2))
proc decodeUrl*(s: string): string =
## Decodes a value from its HTTP representation: This means that a ``'+'``
## is converted to a space, ``'%xx'`` (where ``xx`` denotes a hexadecimal
## value) is converted to the character with ordinal number ``xx``, and
proc decodeUrl*(s: string, decodePlus=true): string =
## Decodes a URL according to RFC3986.
##
## 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.
##
## 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.} =
case c
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)
inc(i, 2)
result[j] = chr(x)
of '+': result[j] = ' '
of '+':
if decodePlus:
result[j] = ' '
else:
result[j] = s[i]
else: result[j] = s[i]
inc(i)
inc(j)
@ -370,6 +383,9 @@ when isMainModule:
const test1 = "abc\L+def xyz"
doAssert encodeUrl(test1) == "abc%0A%2Bdef+xyz"
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:
let str = "http://localhost"

View file

@ -1069,17 +1069,15 @@ proc splitData*(textNode: PText, offset: int): PText =
var newNode: PText = textNode.fOwnerDocument.createTextNode(right)
return newNode
# ProcessingInstruction
proc target*(pi: PProcessingInstruction): string =
## Returns the Processing Instructions target
return pi.fTarget
# --Other stuff--
# Writer
proc addEscaped(s: string): string =
proc escapeXml*(s: string; result: var string) =
## Prepares a string for insertion into a XML document
## by escaping the XML special characters.
result = ""
for c in items(s):
case c
@ -1089,11 +1087,20 @@ proc addEscaped(s: string): string =
of '"': result.add("&quot;")
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 =
result = spaces(indent) & "<" & n.nodeName
if not isNil(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:
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))
of TextNode:
result.add(spaces(indent * 2))
result.add(addEscaped(i.nodeValue))
result.add(escapeXml(i.nodeValue))
of CDataSectionNode:
result.add(spaces(indent * 2))
result.add("<![CDATA[" & i.nodeValue & "]]>")

View file

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

View file

@ -33,9 +33,6 @@ type
fAttr: XmlAttributes
fClientData: int ## for other clients
{.deprecated: [PXmlNode: XmlNode, TXmlNodeKind: XmlNodeKind, PXmlAttributes:
XmlAttributes, TXmlNode: XmlNodeObj].}
proc newXmlNode(kind: XmlNodeKind): XmlNode =
## creates a new ``XmlNode``.
new(result)
@ -155,11 +152,6 @@ proc `[]`* (n: var XmlNode, i: int): var XmlNode {.inline.} =
assert n.k == xnElement
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.} =
## iterates over any child of `n`.
assert n.k == xnElement
@ -319,8 +311,8 @@ proc xmlConstructor(a: NimNode): NimNode {.compileTime.} =
if a.kind == nnkCall:
result = newCall("newXmlTree", toStrLit(a[0]))
var attrs = newNimNode(nnkBracket, a)
var newStringTabCall = newCall("newStringTable", attrs,
newIdentNode("modeCaseSensitive"))
var newStringTabCall = newCall(bindSym"newStringTable", attrs,
bindSym"modeCaseSensitive")
var elements = newNimNode(nnkBracket, a)
for i in 1..a.len-1:
if a[i].kind == nnkExprEqExpr:

View file

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

View file

@ -76,6 +76,7 @@ proc rawNewStringNoInit(space: int): NimString {.compilerProc.} =
if s < 7: s = 7
result = allocStrNoInit(sizeof(TGenericSeq) + s + 1)
result.reserved = s
result.len = 0
when defined(gogc):
result.elemSize = 1
@ -84,6 +85,7 @@ proc rawNewString(space: int): NimString {.compilerProc.} =
if s < 7: s = 7
result = allocStr(sizeof(TGenericSeq) + s + 1)
result.reserved = s
result.len = 0
when defined(gogc):
result.elemSize = 1

View file

@ -38,7 +38,7 @@ when useWinVersion:
from winlean import SocketHandle
else:
const versions = "(.1.1|.38|.39|.41|.43|.44|.10|.1.0.2|.1.0.1|.1.0.0|.0.9.9|.0.9.8|)"
const versions = "(.1.1|.38|.39|.41|.43|.44|.45|.10|.1.0.2|.1.0.1|.1.0.0|.0.9.9|.0.9.8|)"
when defined(macosx):
const

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