Merge branch 'devel' into araq
This commit is contained in:
commit
617ba1a209
37 changed files with 353 additions and 69 deletions
23
changelog.md
23
changelog.md
|
|
@ -39,5 +39,26 @@
|
||||||
- Added ``typetraits.$`` as an alias for ``typetraits.name``.
|
- Added ``typetraits.$`` as an alias for ``typetraits.name``.
|
||||||
- ``os.getEnv`` now takes an optional ``default`` parameter that tells ``getEnv``
|
- ``os.getEnv`` now takes an optional ``default`` parameter that tells ``getEnv``
|
||||||
what to return if the environment variable does not exist.
|
what to return if the environment variable does not exist.
|
||||||
- Removed PDCurses wrapper from the stdlib and published it as a separate
|
- Removed PDCurses wrapper from the stdlib and published it as a separate
|
||||||
Nimble package.
|
Nimble package.
|
||||||
|
- Bodies of ``for`` loops now get their own scope:
|
||||||
|
|
||||||
|
.. code-block:: nim
|
||||||
|
# now compiles:
|
||||||
|
for i in 0..4:
|
||||||
|
let i = i + 1
|
||||||
|
echo i
|
||||||
|
|
||||||
|
- The parsing rules of ``if`` expressions were changed so that multiple
|
||||||
|
statements are allowed in the branches. We found few code examples that
|
||||||
|
now fail because of this change, but here is one:
|
||||||
|
|
||||||
|
.. code-block:: nim
|
||||||
|
|
||||||
|
t[ti] = if exp_negative: '-' else: '+'; inc(ti)
|
||||||
|
|
||||||
|
This now needs to be written as:
|
||||||
|
|
||||||
|
.. code-block:: nim
|
||||||
|
|
||||||
|
t[ti] = (if exp_negative: '-' else: '+'); inc(ti)
|
||||||
|
|
|
||||||
|
|
@ -1067,7 +1067,7 @@ proc genArrayAddr(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
else:
|
else:
|
||||||
r.res = "chckIndx($1, $2, strlen($3))-$2" % [b.res, rope(first), a.res]
|
r.res = "chckIndx($1, $2, strlen($3))-$2" % [b.res, rope(first), a.res]
|
||||||
else:
|
else:
|
||||||
r.res = "chckIndx($1, $2, $3.length-1)-$2" % [b.res, rope(first), a.res]
|
r.res = "chckIndx($1, $2, $3.length+$2-1)-$2" % [b.res, rope(first), a.res]
|
||||||
elif first != 0:
|
elif first != 0:
|
||||||
r.res = "($1)-$2" % [b.res, rope(first)]
|
r.res = "($1)-$2" % [b.res, rope(first)]
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -764,7 +764,10 @@ proc semCaptureSym*(s, owner: PSym) =
|
||||||
var o = owner.skipGenericOwner
|
var o = owner.skipGenericOwner
|
||||||
while o.kind != skModule and o != nil:
|
while o.kind != skModule and o != nil:
|
||||||
if s.owner == o:
|
if s.owner == o:
|
||||||
owner.typ.callConv = ccClosure
|
if owner.typ.callConv in {ccClosure, ccDefault} or owner.kind == skIterator:
|
||||||
|
owner.typ.callConv = ccClosure
|
||||||
|
else:
|
||||||
|
discard "do not produce an error here, but later"
|
||||||
#echo "computing .closure for ", owner.name.s, " ", owner.info, " because of ", s.name.s
|
#echo "computing .closure for ", owner.name.s, " ", owner.info, " because of ", s.name.s
|
||||||
o = o.skipGenericOwner
|
o = o.skipGenericOwner
|
||||||
# since the analysis is not entirely correct, we don't set 'tfCapturesEnv'
|
# since the analysis is not entirely correct, we don't set 'tfCapturesEnv'
|
||||||
|
|
|
||||||
|
|
@ -52,17 +52,19 @@ proc lookupParam(params, dest: PNode): PSym =
|
||||||
if params[i].kind == nkSym and params[i].sym.name.id == dest.ident.id:
|
if params[i].kind == nkSym and params[i].sym.name.id == dest.ident.id:
|
||||||
return params[i].sym
|
return params[i].sym
|
||||||
|
|
||||||
proc liftLocalsIfRequested*(prc: PSym) =
|
proc liftLocalsIfRequested*(prc: PSym; n: PNode): PNode =
|
||||||
let liftDest = getPragmaVal(prc.ast, wLiftLocals)
|
let liftDest = getPragmaVal(prc.ast, wLiftLocals)
|
||||||
if liftDest == nil: return
|
if liftDest == nil: return n
|
||||||
let partialParam = lookupParam(prc.typ.n, liftDest)
|
let partialParam = lookupParam(prc.typ.n, liftDest)
|
||||||
if partialParam.isNil:
|
if partialParam.isNil:
|
||||||
localError(liftDest.info, "'$1' is not a parameter of '$2'" %
|
localError(liftDest.info, "'$1' is not a parameter of '$2'" %
|
||||||
[$liftDest, prc.name.s])
|
[$liftDest, prc.name.s])
|
||||||
return
|
return n
|
||||||
let objType = partialParam.typ.skipTypes(abstractPtrs)
|
let objType = partialParam.typ.skipTypes(abstractPtrs)
|
||||||
if objType.kind != tyObject or tfPartial notin objType.flags:
|
if objType.kind != tyObject or tfPartial notin objType.flags:
|
||||||
localError(liftDest.info, "parameter '$1' is not a pointer to a partial object" % $liftDest)
|
localError(liftDest.info, "parameter '$1' is not a pointer to a partial object" % $liftDest)
|
||||||
return
|
return n
|
||||||
var c = Ctx(partialParam: partialParam, objType: objType)
|
var c = Ctx(partialParam: partialParam, objType: objType)
|
||||||
liftLocals(prc.ast, bodyPos, c)
|
let w = newTree(nkStmtList, n)
|
||||||
|
liftLocals(w, 0, c)
|
||||||
|
result = w[0]
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,7 @@ proc resolveDollar(project, source, pkg, subdir: string; info: TLineInfo): strin
|
||||||
|
|
||||||
proc scriptableImport(pkg, sub: string; info: TLineInfo): string =
|
proc scriptableImport(pkg, sub: string; info: TLineInfo): string =
|
||||||
result = resolveDollar(gProjectFull, info.toFullPath(), pkg, sub, info)
|
result = resolveDollar(gProjectFull, info.toFullPath(), pkg, sub, info)
|
||||||
|
if result.isNil: result = ""
|
||||||
|
|
||||||
proc lookupPackage(pkg, subdir: PNode): string =
|
proc lookupPackage(pkg, subdir: PNode): string =
|
||||||
let sub = if subdir != nil: renderTree(subdir, {renderNoComments}).replace(" ") else: ""
|
let sub = if subdir != nil: renderTree(subdir, {renderNoComments}).replace(" ") else: ""
|
||||||
|
|
@ -166,7 +167,8 @@ proc checkModuleName*(n: PNode; doLocalError=true): int32 =
|
||||||
let fullPath = findModule(modulename, n.info.toFullPath)
|
let fullPath = findModule(modulename, n.info.toFullPath)
|
||||||
if fullPath.len == 0:
|
if fullPath.len == 0:
|
||||||
if doLocalError:
|
if doLocalError:
|
||||||
localError(n.info, errCannotOpenFile, modulename)
|
let m = if modulename.len > 0: modulename else: $n
|
||||||
|
localError(n.info, errCannotOpenFile, m)
|
||||||
result = InvalidFileIDX
|
result = InvalidFileIDX
|
||||||
else:
|
else:
|
||||||
result = fullPath.fileInfoIdx
|
result = fullPath.fileInfoIdx
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ type
|
||||||
errBaseTypeMustBeOrdinal, errInheritanceOnlyWithNonFinalObjects,
|
errBaseTypeMustBeOrdinal, errInheritanceOnlyWithNonFinalObjects,
|
||||||
errInheritanceOnlyWithEnums, errIllegalRecursionInTypeX,
|
errInheritanceOnlyWithEnums, errIllegalRecursionInTypeX,
|
||||||
errCannotInstantiateX, errExprHasNoAddress, errXStackEscape,
|
errCannotInstantiateX, errExprHasNoAddress, errXStackEscape,
|
||||||
errVarForOutParamNeeded,
|
errVarForOutParamNeededX,
|
||||||
errPureTypeMismatch, errTypeMismatch, errButExpected, errButExpectedX,
|
errPureTypeMismatch, errTypeMismatch, errButExpected, errButExpectedX,
|
||||||
errAmbiguousCallXYZ, errWrongNumberOfArguments,
|
errAmbiguousCallXYZ, errWrongNumberOfArguments,
|
||||||
errWrongNumberOfArgumentsInCall,
|
errWrongNumberOfArgumentsInCall,
|
||||||
|
|
@ -268,7 +268,7 @@ const
|
||||||
errCannotInstantiateX: "cannot instantiate: \'$1\'",
|
errCannotInstantiateX: "cannot instantiate: \'$1\'",
|
||||||
errExprHasNoAddress: "expression has no address",
|
errExprHasNoAddress: "expression has no address",
|
||||||
errXStackEscape: "address of '$1' may not escape its stack frame",
|
errXStackEscape: "address of '$1' may not escape its stack frame",
|
||||||
errVarForOutParamNeeded: "for a \'var\' type a variable needs to be passed",
|
errVarForOutParamNeededX: "for a \'var\' type a variable needs to be passed; but '$1' is immutable",
|
||||||
errPureTypeMismatch: "type mismatch",
|
errPureTypeMismatch: "type mismatch",
|
||||||
errTypeMismatch: "type mismatch: got (",
|
errTypeMismatch: "type mismatch: got (",
|
||||||
errButExpected: "but expected one of: ",
|
errButExpected: "but expected one of: ",
|
||||||
|
|
|
||||||
|
|
@ -785,21 +785,58 @@ proc parseIfExpr(p: var TParser, kind: TNodeKind): PNode =
|
||||||
#| 'else' colcom expr
|
#| 'else' colcom expr
|
||||||
#| ifExpr = 'if' condExpr
|
#| ifExpr = 'if' condExpr
|
||||||
#| whenExpr = 'when' condExpr
|
#| whenExpr = 'when' condExpr
|
||||||
result = newNodeP(kind, p)
|
when true:
|
||||||
while true:
|
result = newNodeP(kind, p)
|
||||||
getTok(p) # skip `if`, `elif`
|
while true:
|
||||||
var branch = newNodeP(nkElifExpr, p)
|
getTok(p) # skip `if`, `when`, `elif`
|
||||||
|
var branch = newNodeP(nkElifExpr, p)
|
||||||
|
optInd(p, branch)
|
||||||
|
addSon(branch, parseExpr(p))
|
||||||
|
colcom(p, branch)
|
||||||
|
addSon(branch, parseStmt(p))
|
||||||
|
skipComment(p, branch)
|
||||||
|
addSon(result, branch)
|
||||||
|
if p.tok.tokType != tkElif: break # or not sameOrNoInd(p): break
|
||||||
|
if p.tok.tokType == tkElse: # and sameOrNoInd(p):
|
||||||
|
var branch = newNodeP(nkElseExpr, p)
|
||||||
|
eat(p, tkElse)
|
||||||
|
colcom(p, branch)
|
||||||
|
addSon(branch, parseStmt(p))
|
||||||
|
addSon(result, branch)
|
||||||
|
else:
|
||||||
|
var
|
||||||
|
b: PNode
|
||||||
|
wasIndented = false
|
||||||
|
result = newNodeP(kind, p)
|
||||||
|
|
||||||
|
getTok(p)
|
||||||
|
let branch = newNodeP(nkElifExpr, p)
|
||||||
addSon(branch, parseExpr(p))
|
addSon(branch, parseExpr(p))
|
||||||
colcom(p, branch)
|
colcom(p, branch)
|
||||||
|
let oldInd = p.currInd
|
||||||
|
if realInd(p):
|
||||||
|
p.currInd = p.tok.indent
|
||||||
|
wasIndented = true
|
||||||
|
echo result.info, " yes ", p.currInd
|
||||||
addSon(branch, parseExpr(p))
|
addSon(branch, parseExpr(p))
|
||||||
optInd(p, branch)
|
result.add branch
|
||||||
addSon(result, branch)
|
while sameInd(p) or not wasIndented:
|
||||||
if p.tok.tokType != tkElif: break
|
case p.tok.tokType
|
||||||
var branch = newNodeP(nkElseExpr, p)
|
of tkElif:
|
||||||
eat(p, tkElse)
|
b = newNodeP(nkElifExpr, p)
|
||||||
colcom(p, branch)
|
getTok(p)
|
||||||
addSon(branch, parseExpr(p))
|
optInd(p, b)
|
||||||
addSon(result, branch)
|
addSon(b, parseExpr(p))
|
||||||
|
of tkElse:
|
||||||
|
b = newNodeP(nkElseExpr, p)
|
||||||
|
getTok(p)
|
||||||
|
else: break
|
||||||
|
colcom(p, b)
|
||||||
|
addSon(b, parseStmt(p))
|
||||||
|
addSon(result, b)
|
||||||
|
if b.kind == nkElseExpr: break
|
||||||
|
if wasIndented:
|
||||||
|
p.currInd = oldInd
|
||||||
|
|
||||||
proc parsePragma(p: var TParser): PNode =
|
proc parsePragma(p: var TParser): PNode =
|
||||||
#| pragma = '{.' optInd (exprColonExpr comma?)* optPar ('.}' | '}')
|
#| pragma = '{.' optInd (exprColonExpr comma?)* optPar ('.}' | '}')
|
||||||
|
|
@ -2036,8 +2073,13 @@ proc parseStmt(p: var TParser): PNode =
|
||||||
if a.kind != nkEmpty:
|
if a.kind != nkEmpty:
|
||||||
addSon(result, a)
|
addSon(result, a)
|
||||||
else:
|
else:
|
||||||
parMessage(p, errExprExpected, p.tok)
|
# This is done to make the new 'if' expressions work better.
|
||||||
getTok(p)
|
# XXX Eventually we need to be more strict here.
|
||||||
|
if p.tok.tokType notin {tkElse, tkElif}:
|
||||||
|
parMessage(p, errExprExpected, p.tok)
|
||||||
|
getTok(p)
|
||||||
|
else:
|
||||||
|
break
|
||||||
if not p.hasProgress and p.tok.tokType == tkEof: break
|
if not p.hasProgress and p.tok.tokType == tkEof: break
|
||||||
else:
|
else:
|
||||||
# the case statement is only needed for better error messages:
|
# the case statement is only needed for better error messages:
|
||||||
|
|
|
||||||
|
|
@ -465,7 +465,7 @@ proc newHiddenAddrTaken(c: PContext, n: PNode): PNode =
|
||||||
result = newNodeIT(nkHiddenAddr, n.info, makeVarType(c, n.typ))
|
result = newNodeIT(nkHiddenAddr, n.info, makeVarType(c, n.typ))
|
||||||
addSon(result, n)
|
addSon(result, n)
|
||||||
if isAssignable(c, n) notin {arLValue, arLocalLValue}:
|
if isAssignable(c, n) notin {arLValue, arLocalLValue}:
|
||||||
localError(n.info, errVarForOutParamNeeded)
|
localError(n.info, errVarForOutParamNeededX, $n)
|
||||||
|
|
||||||
proc analyseIfAddressTaken(c: PContext, n: PNode): PNode =
|
proc analyseIfAddressTaken(c: PContext, n: PNode): PNode =
|
||||||
result = n
|
result = n
|
||||||
|
|
@ -509,9 +509,10 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
|
||||||
for i in countup(1, sonsLen(n) - 1):
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
if i < sonsLen(t) and t.sons[i] != nil and
|
if i < sonsLen(t) and t.sons[i] != nil and
|
||||||
skipTypes(t.sons[i], abstractInst-{tyTypeDesc}).kind == tyVar:
|
skipTypes(t.sons[i], abstractInst-{tyTypeDesc}).kind == tyVar:
|
||||||
if isAssignable(c, n.sons[i]) notin {arLValue, arLocalLValue}:
|
let it = n[i]
|
||||||
if n.sons[i].kind != nkHiddenAddr:
|
if isAssignable(c, it) notin {arLValue, arLocalLValue}:
|
||||||
localError(n.sons[i].info, errVarForOutParamNeeded)
|
if it.kind != nkHiddenAddr:
|
||||||
|
localError(it.info, errVarForOutParamNeededX, $it)
|
||||||
return
|
return
|
||||||
for i in countup(1, sonsLen(n) - 1):
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
if n.sons[i].kind == nkHiddenCallConv:
|
if n.sons[i].kind == nkHiddenCallConv:
|
||||||
|
|
|
||||||
|
|
@ -335,8 +335,10 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||||
n.sons[L - 2] = semGenericStmt(c, n.sons[L-2], flags, ctx)
|
n.sons[L - 2] = semGenericStmt(c, n.sons[L-2], flags, ctx)
|
||||||
for i in countup(0, L - 3):
|
for i in countup(0, L - 3):
|
||||||
addTempDecl(c, n.sons[i], skForVar)
|
addTempDecl(c, n.sons[i], skForVar)
|
||||||
|
openScope(c)
|
||||||
n.sons[L - 1] = semGenericStmt(c, n.sons[L-1], flags, ctx)
|
n.sons[L - 1] = semGenericStmt(c, n.sons[L-1], flags, ctx)
|
||||||
closeScope(c)
|
closeScope(c)
|
||||||
|
closeScope(c)
|
||||||
of nkBlockStmt, nkBlockExpr, nkBlockType:
|
of nkBlockStmt, nkBlockExpr, nkBlockType:
|
||||||
checkSonsLen(n, 2)
|
checkSonsLen(n, 2)
|
||||||
openScope(c)
|
openScope(c)
|
||||||
|
|
|
||||||
|
|
@ -697,7 +697,9 @@ proc semForVars(c: PContext, n: PNode): PNode =
|
||||||
if sfGenSym notin v.flags and not isDiscardUnderscore(v):
|
if sfGenSym notin v.flags and not isDiscardUnderscore(v):
|
||||||
addForVarDecl(c, v)
|
addForVarDecl(c, v)
|
||||||
inc(c.p.nestedLoopCounter)
|
inc(c.p.nestedLoopCounter)
|
||||||
|
openScope(c)
|
||||||
n.sons[length-1] = semStmt(c, n.sons[length-1])
|
n.sons[length-1] = semStmt(c, n.sons[length-1])
|
||||||
|
closeScope(c)
|
||||||
dec(c.p.nestedLoopCounter)
|
dec(c.p.nestedLoopCounter)
|
||||||
|
|
||||||
proc implicitIterator(c: PContext, it: string, arg: PNode): PNode =
|
proc implicitIterator(c: PContext, it: string, arg: PNode): PNode =
|
||||||
|
|
|
||||||
|
|
@ -366,8 +366,10 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
n.sons[L-2] = semTemplBody(c, n.sons[L-2])
|
n.sons[L-2] = semTemplBody(c, n.sons[L-2])
|
||||||
for i in countup(0, L - 3):
|
for i in countup(0, L - 3):
|
||||||
addLocalDecl(c, n.sons[i], skForVar)
|
addLocalDecl(c, n.sons[i], skForVar)
|
||||||
|
openScope(c)
|
||||||
n.sons[L-1] = semTemplBody(c, n.sons[L-1])
|
n.sons[L-1] = semTemplBody(c, n.sons[L-1])
|
||||||
closeScope(c)
|
closeScope(c)
|
||||||
|
closeScope(c)
|
||||||
of nkBlockStmt, nkBlockExpr, nkBlockType:
|
of nkBlockStmt, nkBlockExpr, nkBlockType:
|
||||||
checkSonsLen(n, 2)
|
checkSonsLen(n, 2)
|
||||||
openScope(c)
|
openScope(c)
|
||||||
|
|
|
||||||
|
|
@ -1057,9 +1057,10 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
|
||||||
else: isNone
|
else: isNone
|
||||||
|
|
||||||
of tyUserTypeClass, tyUserTypeClassInst:
|
of tyUserTypeClass, tyUserTypeClassInst:
|
||||||
if c.c.matchedConcept != nil:
|
if c.c.matchedConcept != nil and c.c.matchedConcept.depth <= 4:
|
||||||
# consider this: 'var g: Node' *within* a concept where 'Node'
|
# consider this: 'var g: Node' *within* a concept where 'Node'
|
||||||
# is a concept too (tgraph)
|
# is a concept too (tgraph)
|
||||||
|
inc c.c.matchedConcept.depth
|
||||||
let x = typeRel(c, a, f, flags + {trDontBind})
|
let x = typeRel(c, a, f, flags + {trDontBind})
|
||||||
if x >= isGeneric:
|
if x >= isGeneric:
|
||||||
return isGeneric
|
return isGeneric
|
||||||
|
|
|
||||||
|
|
@ -978,7 +978,7 @@ proc transformBody*(module: PSym, n: PNode, prc: PSym): PNode =
|
||||||
liftDefer(c, result)
|
liftDefer(c, result)
|
||||||
#result = liftLambdas(prc, result)
|
#result = liftLambdas(prc, result)
|
||||||
when useEffectSystem: trackProc(prc, result)
|
when useEffectSystem: trackProc(prc, result)
|
||||||
liftLocalsIfRequested(prc)
|
result = liftLocalsIfRequested(prc, result)
|
||||||
if c.needsDestroyPass and newDestructors:
|
if c.needsDestroyPass and newDestructors:
|
||||||
result = injectDestructorCalls(prc, result)
|
result = injectDestructorCalls(prc, result)
|
||||||
incl(result.flags, nfTransf)
|
incl(result.flags, nfTransf)
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@ path="$lib/pure"
|
||||||
clang.options.linker = "-landroid-glob"
|
clang.options.linker = "-landroid-glob"
|
||||||
clang.cpp.options.linker = "-landroid-glob"
|
clang.cpp.options.linker = "-landroid-glob"
|
||||||
tcc.options.linker = "-landroid-glob"
|
tcc.options.linker = "-landroid-glob"
|
||||||
define:"useShPath:/system/bin/sh"
|
|
||||||
@end
|
@end
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -316,7 +316,7 @@ factor.
|
||||||
immediate pragma
|
immediate pragma
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
See `Ordinary vs immediate templates`_.
|
See `Typed vs untyped parameters`_.
|
||||||
|
|
||||||
|
|
||||||
compilation option pragmas
|
compilation option pragmas
|
||||||
|
|
|
||||||
|
|
@ -262,7 +262,7 @@ proc socket*(domain: Domain = AF_INET, typ: SockType = SOCK_STREAM,
|
||||||
|
|
||||||
# TODO: Perhaps this should just raise EOS when an error occurs.
|
# TODO: Perhaps this should just raise EOS when an error occurs.
|
||||||
when defined(Windows):
|
when defined(Windows):
|
||||||
result = newTSocket(winlean.socket(ord(domain), ord(typ), ord(protocol)), buffered)
|
result = newTSocket(winlean.socket(cint(domain), cint(typ), cint(protocol)), buffered)
|
||||||
else:
|
else:
|
||||||
result = newTSocket(posix.socket(toInt(domain), toInt(typ), toInt(protocol)), buffered)
|
result = newTSocket(posix.socket(toInt(domain), toInt(typ), toInt(protocol)), buffered)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -798,7 +798,8 @@ proc renderImage(d: PDoc, n: PRstNode, result: var string) =
|
||||||
if arg.valid:
|
if arg.valid:
|
||||||
let htmlOut = if isObject:
|
let htmlOut = if isObject:
|
||||||
"<object data=\"$1\" type=\"image/svg+xml\"$2 >" & content & "</object>"
|
"<object data=\"$1\" type=\"image/svg+xml\"$2 >" & content & "</object>"
|
||||||
else: "<img src=\"$1\"$2 />"
|
else:
|
||||||
|
"<img src=\"$1\"$2 />"
|
||||||
dispA(d.target, result, htmlOut, "\\includegraphics$2{$1}",
|
dispA(d.target, result, htmlOut, "\\includegraphics$2{$1}",
|
||||||
[arg, options])
|
[arg, options])
|
||||||
if len(n) >= 3: renderRstToOut(d, n.sons[2], result)
|
if len(n) >= 3: renderRstToOut(d, n.sons[2], result)
|
||||||
|
|
|
||||||
|
|
@ -767,7 +767,9 @@ elif not defined(useNimRtl):
|
||||||
var sysCommand: string
|
var sysCommand: string
|
||||||
var sysArgsRaw: seq[string]
|
var sysArgsRaw: seq[string]
|
||||||
if poEvalCommand in options:
|
if poEvalCommand in options:
|
||||||
const useShPath {.strdefine.} = "/bin/sh"
|
const useShPath {.strdefine.} =
|
||||||
|
when not defined(android): "/bin/sh"
|
||||||
|
else: "/system/bin/sh"
|
||||||
sysCommand = useShPath
|
sysCommand = useShPath
|
||||||
sysArgsRaw = @[sysCommand, "-c", command]
|
sysArgsRaw = @[sysCommand, "-c", command]
|
||||||
assert args.len == 0, "`args` has to be empty when using poEvalCommand."
|
assert args.len == 0, "`args` has to be empty when using poEvalCommand."
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
## runtime efficiency.
|
## runtime efficiency.
|
||||||
|
|
||||||
include "system/inclrtl"
|
include "system/inclrtl"
|
||||||
|
import streams
|
||||||
|
|
||||||
{.deadCodeElim: on.}
|
{.deadCodeElim: on.}
|
||||||
|
|
||||||
|
|
@ -130,7 +131,7 @@ proc insertInCache(s: string, tree: Rope): Rope =
|
||||||
result.left = t
|
result.left = t
|
||||||
t.right = nil
|
t.right = nil
|
||||||
|
|
||||||
proc rope*(s: string): Rope {.rtl, extern: "nro$1Str".} =
|
proc rope*(s: string = nil): Rope {.rtl, extern: "nro$1Str".} =
|
||||||
## Converts a string to a rope.
|
## Converts a string to a rope.
|
||||||
if s.len == 0:
|
if s.len == 0:
|
||||||
result = nil
|
result = nil
|
||||||
|
|
@ -242,10 +243,13 @@ proc write*(f: File, r: Rope) {.rtl, extern: "nro$1".} =
|
||||||
## writes a rope to a file.
|
## writes a rope to a file.
|
||||||
for s in leaves(r): write(f, s)
|
for s in leaves(r): write(f, s)
|
||||||
|
|
||||||
|
proc write*(s: Stream, r: Rope) {.rtl, extern: "nroWriteStream".} =
|
||||||
|
## writes a rope to a stream.
|
||||||
|
for rs in leaves(r): write(s, rs)
|
||||||
|
|
||||||
proc `$`*(r: Rope): string {.rtl, extern: "nroToString".}=
|
proc `$`*(r: Rope): string {.rtl, extern: "nroToString".}=
|
||||||
## converts a rope back to a string.
|
## converts a rope back to a string.
|
||||||
result = newString(r.len)
|
result = newStringOfCap(r.len)
|
||||||
setLen(result, 0)
|
|
||||||
for s in leaves(r): add(result, s)
|
for s in leaves(r): add(result, s)
|
||||||
|
|
||||||
when false:
|
when false:
|
||||||
|
|
|
||||||
|
|
@ -578,15 +578,46 @@ iterator split*(s: string, seps: set[char] = Whitespace,
|
||||||
else:
|
else:
|
||||||
splitCommon(s, seps, maxsplit, 1)
|
splitCommon(s, seps, maxsplit, 1)
|
||||||
|
|
||||||
iterator splitWhitespace*(s: string): string =
|
iterator splitWhitespace*(s: string, maxsplit: int = -1): string =
|
||||||
## Splits at whitespace.
|
## Splits the string ``s`` at whitespace stripping leading and trailing
|
||||||
oldSplit(s, Whitespace, -1)
|
## whitespace if necessary. If ``maxsplit`` is specified and is positive,
|
||||||
|
## no more than ``maxsplit`` splits is made.
|
||||||
|
##
|
||||||
|
## The following code:
|
||||||
|
##
|
||||||
|
## .. code-block:: nim
|
||||||
|
## let s = " foo \t bar baz "
|
||||||
|
## for ms in [-1, 1, 2, 3]:
|
||||||
|
## echo "------ maxsplit = ", ms, ":"
|
||||||
|
## for item in s.splitWhitespace(maxsplit=ms):
|
||||||
|
## echo '"', item, '"'
|
||||||
|
##
|
||||||
|
## ...results in:
|
||||||
|
##
|
||||||
|
## .. code-block::
|
||||||
|
## ------ maxsplit = -1:
|
||||||
|
## "foo"
|
||||||
|
## "bar"
|
||||||
|
## "baz"
|
||||||
|
## ------ maxsplit = 1:
|
||||||
|
## "foo"
|
||||||
|
## "bar baz "
|
||||||
|
## ------ maxsplit = 2:
|
||||||
|
## "foo"
|
||||||
|
## "bar"
|
||||||
|
## "baz "
|
||||||
|
## ------ maxsplit = 3:
|
||||||
|
## "foo"
|
||||||
|
## "bar"
|
||||||
|
## "baz"
|
||||||
|
##
|
||||||
|
oldSplit(s, Whitespace, maxsplit)
|
||||||
|
|
||||||
proc splitWhitespace*(s: string): seq[string] {.noSideEffect,
|
proc splitWhitespace*(s: string, maxsplit: int = -1): seq[string] {.noSideEffect,
|
||||||
rtl, extern: "nsuSplitWhitespace".} =
|
rtl, extern: "nsuSplitWhitespace".} =
|
||||||
## The same as the `splitWhitespace <#splitWhitespace.i,string>`_
|
## The same as the `splitWhitespace <#splitWhitespace.i,string,int>`_
|
||||||
## iterator, but is a proc that returns a sequence of substrings.
|
## iterator, but is a proc that returns a sequence of substrings.
|
||||||
accumulateResult(splitWhitespace(s))
|
accumulateResult(splitWhitespace(s, maxsplit))
|
||||||
|
|
||||||
iterator split*(s: string, sep: char, maxsplit: int = -1): string =
|
iterator split*(s: string, sep: char, maxsplit: int = -1): string =
|
||||||
## Splits the string `s` into substrings using a single separator.
|
## Splits the string `s` into substrings using a single separator.
|
||||||
|
|
@ -671,7 +702,7 @@ iterator rsplit*(s: string, seps: set[char] = Whitespace,
|
||||||
maxsplit: int = -1): string =
|
maxsplit: int = -1): string =
|
||||||
## Splits the string `s` into substrings from the right using a
|
## Splits the string `s` into substrings from the right using a
|
||||||
## string separator. Works exactly the same as `split iterator
|
## string separator. Works exactly the same as `split iterator
|
||||||
## <#split.i,string,char>`_ except in reverse order.
|
## <#split.i,string,char,int>`_ except in reverse order.
|
||||||
##
|
##
|
||||||
## .. code-block:: nim
|
## .. code-block:: nim
|
||||||
## for piece in "foo bar".rsplit(WhiteSpace):
|
## for piece in "foo bar".rsplit(WhiteSpace):
|
||||||
|
|
@ -691,7 +722,7 @@ iterator rsplit*(s: string, sep: char,
|
||||||
maxsplit: int = -1): string =
|
maxsplit: int = -1): string =
|
||||||
## Splits the string `s` into substrings from the right using a
|
## Splits the string `s` into substrings from the right using a
|
||||||
## string separator. Works exactly the same as `split iterator
|
## string separator. Works exactly the same as `split iterator
|
||||||
## <#split.i,string,char>`_ except in reverse order.
|
## <#split.i,string,char,int>`_ except in reverse order.
|
||||||
##
|
##
|
||||||
## .. code-block:: nim
|
## .. code-block:: nim
|
||||||
## for piece in "foo:bar".rsplit(':'):
|
## for piece in "foo:bar".rsplit(':'):
|
||||||
|
|
@ -710,7 +741,7 @@ iterator rsplit*(s: string, sep: string, maxsplit: int = -1,
|
||||||
keepSeparators: bool = false): string =
|
keepSeparators: bool = false): string =
|
||||||
## Splits the string `s` into substrings from the right using a
|
## Splits the string `s` into substrings from the right using a
|
||||||
## string separator. Works exactly the same as `split iterator
|
## string separator. Works exactly the same as `split iterator
|
||||||
## <#split.i,string,string>`_ except in reverse order.
|
## <#split.i,string,string,int>`_ except in reverse order.
|
||||||
##
|
##
|
||||||
## .. code-block:: nim
|
## .. code-block:: nim
|
||||||
## for piece in "foothebar".rsplit("the"):
|
## for piece in "foothebar".rsplit("the"):
|
||||||
|
|
@ -791,13 +822,13 @@ proc countLines*(s: string): int {.noSideEffect,
|
||||||
|
|
||||||
proc split*(s: string, seps: set[char] = Whitespace, maxsplit: int = -1): seq[string] {.
|
proc split*(s: string, seps: set[char] = Whitespace, maxsplit: int = -1): seq[string] {.
|
||||||
noSideEffect, rtl, extern: "nsuSplitCharSet".} =
|
noSideEffect, rtl, extern: "nsuSplitCharSet".} =
|
||||||
## The same as the `split iterator <#split.i,string,set[char]>`_, but is a
|
## The same as the `split iterator <#split.i,string,set[char],int>`_, but is a
|
||||||
## proc that returns a sequence of substrings.
|
## proc that returns a sequence of substrings.
|
||||||
accumulateResult(split(s, seps, maxsplit))
|
accumulateResult(split(s, seps, maxsplit))
|
||||||
|
|
||||||
proc split*(s: string, sep: char, maxsplit: int = -1): seq[string] {.noSideEffect,
|
proc split*(s: string, sep: char, maxsplit: int = -1): seq[string] {.noSideEffect,
|
||||||
rtl, extern: "nsuSplitChar".} =
|
rtl, extern: "nsuSplitChar".} =
|
||||||
## The same as the `split iterator <#split.i,string,char>`_, but is a proc
|
## The same as the `split iterator <#split.i,string,char,int>`_, but is a proc
|
||||||
## that returns a sequence of substrings.
|
## that returns a sequence of substrings.
|
||||||
accumulateResult(split(s, sep, maxsplit))
|
accumulateResult(split(s, sep, maxsplit))
|
||||||
|
|
||||||
|
|
@ -806,7 +837,7 @@ proc split*(s: string, sep: string, maxsplit: int = -1): seq[string] {.noSideEff
|
||||||
## Splits the string `s` into substrings using a string separator.
|
## Splits the string `s` into substrings using a string separator.
|
||||||
##
|
##
|
||||||
## Substrings are separated by the string `sep`. This is a wrapper around the
|
## Substrings are separated by the string `sep`. This is a wrapper around the
|
||||||
## `split iterator <#split.i,string,string>`_.
|
## `split iterator <#split.i,string,string,int>`_.
|
||||||
doAssert(sep.len > 0)
|
doAssert(sep.len > 0)
|
||||||
|
|
||||||
accumulateResult(split(s, sep, maxsplit))
|
accumulateResult(split(s, sep, maxsplit))
|
||||||
|
|
@ -814,7 +845,7 @@ proc split*(s: string, sep: string, maxsplit: int = -1): seq[string] {.noSideEff
|
||||||
proc rsplit*(s: string, seps: set[char] = Whitespace,
|
proc rsplit*(s: string, seps: set[char] = Whitespace,
|
||||||
maxsplit: int = -1): seq[string]
|
maxsplit: int = -1): seq[string]
|
||||||
{.noSideEffect, rtl, extern: "nsuRSplitCharSet".} =
|
{.noSideEffect, rtl, extern: "nsuRSplitCharSet".} =
|
||||||
## The same as the `rsplit iterator <#rsplit.i,string,set[char]>`_, but is a
|
## The same as the `rsplit iterator <#rsplit.i,string,set[char],int>`_, but is a
|
||||||
## proc that returns a sequence of substrings.
|
## proc that returns a sequence of substrings.
|
||||||
##
|
##
|
||||||
## A possible common use case for `rsplit` is path manipulation,
|
## A possible common use case for `rsplit` is path manipulation,
|
||||||
|
|
@ -836,7 +867,7 @@ proc rsplit*(s: string, seps: set[char] = Whitespace,
|
||||||
|
|
||||||
proc rsplit*(s: string, sep: char, maxsplit: int = -1): seq[string]
|
proc rsplit*(s: string, sep: char, maxsplit: int = -1): seq[string]
|
||||||
{.noSideEffect, rtl, extern: "nsuRSplitChar".} =
|
{.noSideEffect, rtl, extern: "nsuRSplitChar".} =
|
||||||
## The same as the `split iterator <#rsplit.i,string,char>`_, but is a proc
|
## The same as the `rsplit iterator <#rsplit.i,string,char,int>`_, but is a proc
|
||||||
## that returns a sequence of substrings.
|
## that returns a sequence of substrings.
|
||||||
##
|
##
|
||||||
## A possible common use case for `rsplit` is path manipulation,
|
## A possible common use case for `rsplit` is path manipulation,
|
||||||
|
|
@ -858,7 +889,7 @@ proc rsplit*(s: string, sep: char, maxsplit: int = -1): seq[string]
|
||||||
|
|
||||||
proc rsplit*(s: string, sep: string, maxsplit: int = -1): seq[string]
|
proc rsplit*(s: string, sep: string, maxsplit: int = -1): seq[string]
|
||||||
{.noSideEffect, rtl, extern: "nsuRSplitString".} =
|
{.noSideEffect, rtl, extern: "nsuRSplitString".} =
|
||||||
## The same as the `split iterator <#rsplit.i,string,string>`_, but is a proc
|
## The same as the `rsplit iterator <#rsplit.i,string,string,int>`_, but is a proc
|
||||||
## that returns a sequence of substrings.
|
## that returns a sequence of substrings.
|
||||||
##
|
##
|
||||||
## A possible common use case for `rsplit` is path manipulation,
|
## A possible common use case for `rsplit` is path manipulation,
|
||||||
|
|
@ -2599,6 +2630,12 @@ bar
|
||||||
doAssert s.split(' ', maxsplit=1) == @["", "this is an example "]
|
doAssert s.split(' ', maxsplit=1) == @["", "this is an example "]
|
||||||
doAssert s.split(" ", maxsplit=4) == @["", "this", "is", "an", "example "]
|
doAssert s.split(" ", maxsplit=4) == @["", "this", "is", "an", "example "]
|
||||||
|
|
||||||
|
doAssert s.splitWhitespace() == @["this", "is", "an", "example"]
|
||||||
|
doAssert s.splitWhitespace(maxsplit=1) == @["this", "is an example "]
|
||||||
|
doAssert s.splitWhitespace(maxsplit=2) == @["this", "is", "an example "]
|
||||||
|
doAssert s.splitWhitespace(maxsplit=3) == @["this", "is", "an", "example "]
|
||||||
|
doAssert s.splitWhitespace(maxsplit=4) == @["this", "is", "an", "example"]
|
||||||
|
|
||||||
block: # formatEng tests
|
block: # formatEng tests
|
||||||
doAssert formatEng(0, 2, trim=false) == "0.00"
|
doAssert formatEng(0, 2, trim=false) == "0.00"
|
||||||
doAssert formatEng(0, 2) == "0"
|
doAssert formatEng(0, 2) == "0"
|
||||||
|
|
|
||||||
|
|
@ -3531,14 +3531,14 @@ proc `[]`*[Idx, T, U, V](a: array[Idx, T], x: HSlice[U, V]): seq[T] =
|
||||||
let xa = a ^^ x.a
|
let xa = a ^^ x.a
|
||||||
let L = (a ^^ x.b) - xa + 1
|
let L = (a ^^ x.b) - xa + 1
|
||||||
result = newSeq[T](L)
|
result = newSeq[T](L)
|
||||||
for i in 0..<L: result[i] = a[Idx(i + xa + int low(a))]
|
for i in 0..<L: result[i] = a[Idx(i + xa)]
|
||||||
|
|
||||||
proc `[]=`*[Idx, T, U, V](a: var array[Idx, T], x: HSlice[U, V], b: openArray[T]) =
|
proc `[]=`*[Idx, T, U, V](a: var array[Idx, T], x: HSlice[U, V], b: openArray[T]) =
|
||||||
## slice assignment for arrays.
|
## slice assignment for arrays.
|
||||||
let xa = a ^^ x.a
|
let xa = a ^^ x.a
|
||||||
let L = (a ^^ x.b) - xa + 1
|
let L = (a ^^ x.b) - xa + 1
|
||||||
if L == b.len:
|
if L == b.len:
|
||||||
for i in 0..<L: a[Idx(i + xa + int low(a))] = b[i]
|
for i in 0..<L: a[Idx(i + xa)] = b[i]
|
||||||
else:
|
else:
|
||||||
sysFatal(RangeError, "different lengths for slice assignment")
|
sysFatal(RangeError, "different lengths for slice assignment")
|
||||||
|
|
||||||
|
|
@ -3565,18 +3565,20 @@ proc `[]=`*[T, U, V](s: var seq[T], x: HSlice[U, V], b: openArray[T]) =
|
||||||
else:
|
else:
|
||||||
spliceImpl(s, a, L, b)
|
spliceImpl(s, a, L, b)
|
||||||
|
|
||||||
proc `[]`*[T](s: openArray[T]; i: BackwardsIndex): T {.inline.} = s[s.len - int(i)]
|
proc `[]`*[T](s: openArray[T]; i: BackwardsIndex): T {.inline.} =
|
||||||
|
system.`[]`(s, s.len - int(i))
|
||||||
|
|
||||||
proc `[]`*[Idx, T](a: array[Idx, T]; i: BackwardsIndex): T {.inline.} =
|
proc `[]`*[Idx, T](a: array[Idx, T]; i: BackwardsIndex): T {.inline.} =
|
||||||
a[Idx(a.len - int(i) + int low(a))]
|
a[Idx(a.len - int(i) + int low(a))]
|
||||||
proc `[]`*(s: string; i: BackwardsIndex): char {.inline.} = s[s.len - int(i)]
|
proc `[]`*(s: string; i: BackwardsIndex): char {.inline.} = s[s.len - int(i)]
|
||||||
|
|
||||||
proc `[]`*[T](s: var openArray[T]; i: BackwardsIndex): var T {.inline.} =
|
proc `[]`*[T](s: var openArray[T]; i: BackwardsIndex): var T {.inline.} =
|
||||||
s[s.len - int(i)]
|
system.`[]`(s, s.len - int(i))
|
||||||
proc `[]`*[Idx, T](a: var array[Idx, T]; i: BackwardsIndex): var T {.inline.} =
|
proc `[]`*[Idx, T](a: var array[Idx, T]; i: BackwardsIndex): var T {.inline.} =
|
||||||
a[Idx(a.len - int(i) + int low(a))]
|
a[Idx(a.len - int(i) + int low(a))]
|
||||||
|
|
||||||
proc `[]=`*[T](s: var openArray[T]; i: BackwardsIndex; x: T) {.inline.} =
|
proc `[]=`*[T](s: var openArray[T]; i: BackwardsIndex; x: T) {.inline.} =
|
||||||
s[s.len - int(i)] = x
|
system.`[]=`(s, s.len - int(i), x)
|
||||||
proc `[]=`*[Idx, T](a: var array[Idx, T]; i: BackwardsIndex; x: T) {.inline.} =
|
proc `[]=`*[Idx, T](a: var array[Idx, T]; i: BackwardsIndex; x: T) {.inline.} =
|
||||||
a[Idx(a.len - int(i) + int low(a))] = x
|
a[Idx(a.len - int(i) + int low(a))] = x
|
||||||
proc `[]=`*(s: var string; i: BackwardsIndex; x: char) {.inline.} =
|
proc `[]=`*(s: var string; i: BackwardsIndex; x: char) {.inline.} =
|
||||||
|
|
|
||||||
|
|
@ -509,7 +509,7 @@ proc nimParseBiggestFloat(s: string, number: var BiggestFloat,
|
||||||
|
|
||||||
# insert exponent
|
# insert exponent
|
||||||
t[ti] = 'E'; inc(ti)
|
t[ti] = 'E'; inc(ti)
|
||||||
t[ti] = if exp_negative: '-' else: '+'; inc(ti)
|
t[ti] = (if exp_negative: '-' else: '+'); inc(ti)
|
||||||
inc(ti, 3)
|
inc(ti, 3)
|
||||||
|
|
||||||
# insert adjusted exponent
|
# insert adjusted exponent
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,7 @@ However, if you are short on time, you can just run the tests specific to your
|
||||||
changes by only running the corresponding categories of tests. Travis CI verifies
|
changes by only running the corresponding categories of tests. Travis CI verifies
|
||||||
that all tests pass before allowing the pull request to be accepted, so only
|
that all tests pass before allowing the pull request to be accepted, so only
|
||||||
running specific tests should be harmless.
|
running specific tests should be harmless.
|
||||||
|
Integration tests should go in ``tests/untestable``.
|
||||||
|
|
||||||
If you're looking for ways to contribute, please look at our [issue tracker][nim-issues].
|
If you're looking for ways to contribute, please look at our [issue tracker][nim-issues].
|
||||||
There are always plenty of issues labelled [``Easy``][nim-issues-easy]; these should
|
There are always plenty of issues labelled [``Easy``][nim-issues-easy]; these should
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,8 @@ discard """
|
||||||
3
|
3
|
||||||
@[(Field0: 1, Field1: 2), (Field0: 3, Field1: 5)]
|
@[(Field0: 1, Field1: 2), (Field0: 3, Field1: 5)]
|
||||||
2
|
2
|
||||||
@[a, new one, c]'''
|
@[a, new one, c]
|
||||||
|
@[1, 2, 3]'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
proc foo[T](x, y: T): T = x
|
proc foo[T](x, y: T): T = x
|
||||||
|
|
@ -35,3 +36,8 @@ useOpenarray([1, 2, 3])
|
||||||
var z = @["a", "b", "c"]
|
var z = @["a", "b", "c"]
|
||||||
mutOpenarray(z)
|
mutOpenarray(z)
|
||||||
echo z
|
echo z
|
||||||
|
|
||||||
|
# bug #6675
|
||||||
|
var y: array[1..5, int] = [1,2,3,4,5]
|
||||||
|
y[3..5] = [1, 2, 3]
|
||||||
|
echo y[3..5]
|
||||||
|
|
|
||||||
46
tests/array/troofregression.nim
Normal file
46
tests/array/troofregression.nim
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
###############################
|
||||||
|
#### part from Arraymancer
|
||||||
|
|
||||||
|
type
|
||||||
|
MetadataArray* = object
|
||||||
|
data*: array[8, int]
|
||||||
|
len*: int
|
||||||
|
|
||||||
|
# Commenting the converter removes the error "lib/system.nim(3536, 3) Error: for a 'var' type a variable needs to be passed"
|
||||||
|
converter toMetadataArray*(se: varargs[int]): MetadataArray {.inline.} =
|
||||||
|
result.len = se.len
|
||||||
|
for i in 0..<se.len:
|
||||||
|
result.data[i] = se[i]
|
||||||
|
|
||||||
|
|
||||||
|
when NimVersion >= "0.17.3":
|
||||||
|
type Index = int or BackwardsIndex
|
||||||
|
template `^^`(s, i: untyped): untyped =
|
||||||
|
when i is BackwardsIndex:
|
||||||
|
s.len - int(i)
|
||||||
|
else: i
|
||||||
|
else:
|
||||||
|
type Index = int
|
||||||
|
template `^^`(s, i: untyped): untyped =
|
||||||
|
i
|
||||||
|
|
||||||
|
## With Nim devel from the start of the week (~Oct30) I managed to trigger "lib/system.nim(3536, 4) Error: expression has no address"
|
||||||
|
## but I can't anymore after updating Nim (Nov5)
|
||||||
|
## Now commenting this plain compiles and removes the error "lib/system.nim(3536, 3) Error: for a 'var' type a variable needs to be passed"
|
||||||
|
proc `[]`*(a: var MetadataArray, idx: Index): var int {.inline.} =
|
||||||
|
a.data[a ^^ idx]
|
||||||
|
|
||||||
|
|
||||||
|
##############################
|
||||||
|
### Completely unrelated lib that triggers the issue
|
||||||
|
|
||||||
|
type
|
||||||
|
MySeq[T] = ref object
|
||||||
|
data: seq[T]
|
||||||
|
|
||||||
|
proc test[T](sx: MySeq[T]) =
|
||||||
|
# Removing the backward index removes the error "lib/system.nim(3536, 3) Error: for a 'var' type a variable needs to be passed"
|
||||||
|
echo sx.data[^1] # error here
|
||||||
|
|
||||||
|
let s = MySeq[int](data: @[1, 2, 3])
|
||||||
|
s.test()
|
||||||
|
|
@ -4,6 +4,7 @@ discard """
|
||||||
OK AF_INET
|
OK AF_INET
|
||||||
OK AF_INET6
|
OK AF_INET6
|
||||||
'''
|
'''
|
||||||
|
disabled: "travis"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import
|
import
|
||||||
|
|
|
||||||
12
tests/closure/tinvalidclosure3.nim
Normal file
12
tests/closure/tinvalidclosure3.nim
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
discard """
|
||||||
|
line: 9
|
||||||
|
errormsg: "illegal capture 'x'"
|
||||||
|
"""
|
||||||
|
|
||||||
|
proc outer(arg: string) =
|
||||||
|
var x = 0
|
||||||
|
proc inner {.inline.} =
|
||||||
|
echo "inner", x
|
||||||
|
inner()
|
||||||
|
|
||||||
|
outer("abc")
|
||||||
13
tests/concepts/tinfrecursion.nim
Normal file
13
tests/concepts/tinfrecursion.nim
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
|
||||||
|
# bug #6691
|
||||||
|
type
|
||||||
|
ConceptA = concept c
|
||||||
|
|
||||||
|
ConceptB = concept c
|
||||||
|
c.myProc(ConceptA)
|
||||||
|
|
||||||
|
Obj = object
|
||||||
|
|
||||||
|
proc myProc(obj: Obj, x: ConceptA) = discard
|
||||||
|
|
||||||
|
echo Obj is ConceptB
|
||||||
44
tests/js/tarrayboundscheck.nim
Executable file
44
tests/js/tarrayboundscheck.nim
Executable file
|
|
@ -0,0 +1,44 @@
|
||||||
|
discard """
|
||||||
|
output: '''idx out of bounds: -1
|
||||||
|
month out of bounds: 0
|
||||||
|
Jan
|
||||||
|
Feb
|
||||||
|
Mar
|
||||||
|
Apr
|
||||||
|
May
|
||||||
|
Jun
|
||||||
|
Jul
|
||||||
|
Aug
|
||||||
|
Sep
|
||||||
|
Oct
|
||||||
|
Nov
|
||||||
|
Dec
|
||||||
|
month out of bounds: 13
|
||||||
|
idx out of bounds: 14
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
{.push boundChecks:on.}
|
||||||
|
|
||||||
|
# see issue #6532:
|
||||||
|
# js backend 0.17.3: array bounds check for non zero based arrays is buggy
|
||||||
|
|
||||||
|
proc test_arrayboundscheck() =
|
||||||
|
var months: array[1..12, string] =
|
||||||
|
["Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||||
|
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
|
||||||
|
|
||||||
|
var indices = [0,1,2,3,4,5,6,7,8,9,10,11,12,13]
|
||||||
|
|
||||||
|
for i in -1 .. 14:
|
||||||
|
try:
|
||||||
|
let idx = indices[i]
|
||||||
|
try:
|
||||||
|
echo months[idx]
|
||||||
|
except:
|
||||||
|
echo "month out of bounds: ", idx
|
||||||
|
except:
|
||||||
|
echo "idx out of bounds: ", i
|
||||||
|
|
||||||
|
test_arrayboundscheck()
|
||||||
|
{.pop.}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
discard """
|
discard """
|
||||||
line: 24
|
line: 24
|
||||||
errormsg: "expression expected, but found 'keyword else'"
|
errormsg: "invalid indentation"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import macros
|
import macros
|
||||||
|
|
@ -11,7 +11,7 @@ var x = if 4 != 5:
|
||||||
else:
|
else:
|
||||||
"no"
|
"no"
|
||||||
|
|
||||||
macro mymacro(n): untyped {.immediate.} =
|
macro mymacro(n, b): untyped =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
mymacro:
|
mymacro:
|
||||||
|
|
|
||||||
|
|
@ -32,3 +32,21 @@ let other = x:
|
||||||
echo "no"
|
echo "no"
|
||||||
let outer = y(5):
|
let outer = y(5):
|
||||||
echo "yes"
|
echo "yes"
|
||||||
|
|
||||||
|
|
||||||
|
# bug #6609
|
||||||
|
type
|
||||||
|
TextureInternalFormat = enum RED, RGB, RGBA
|
||||||
|
|
||||||
|
const channels = 4
|
||||||
|
|
||||||
|
let format =
|
||||||
|
if channels == 1:
|
||||||
|
TextureInternalFormat.RED
|
||||||
|
elif channels == 3:
|
||||||
|
TextureInternalFormat.RGB
|
||||||
|
elif channels == 4:
|
||||||
|
TextureInternalFormat.RGBA
|
||||||
|
else:
|
||||||
|
echo "Texture Format Unknown, assuming RGB" #This echo causes an error
|
||||||
|
TextureInternalFormat.RGB
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ discard """
|
||||||
cmd: "nim c --threads:on -d:ssl $file"
|
cmd: "nim c --threads:on -d:ssl $file"
|
||||||
exitcode: 0
|
exitcode: 0
|
||||||
output: "OK"
|
output: "OK"
|
||||||
|
disabled: "travis"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import strutils
|
import strutils
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ discard """
|
||||||
cmd: "nim c --threads:on $file"
|
cmd: "nim c --threads:on $file"
|
||||||
exitcode: 0
|
exitcode: 0
|
||||||
output: "OK"
|
output: "OK"
|
||||||
|
disabled: "travis"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os, net, nativesockets, asyncdispatch
|
import os, net, nativesockets, asyncdispatch
|
||||||
|
|
|
||||||
|
|
@ -418,8 +418,9 @@ proc `&?.`(a, b: string): string =
|
||||||
|
|
||||||
proc processSingleTest(r: var TResults, cat: Category, options, test: string) =
|
proc processSingleTest(r: var TResults, cat: Category, options, test: string) =
|
||||||
let test = "tests" & DirSep &.? cat.string / test
|
let test = "tests" & DirSep &.? cat.string / test
|
||||||
|
let target = if cat.string.normalize == "js": targetJS else: targetC
|
||||||
|
|
||||||
if existsFile(test): testSpec r, makeTest(test, options, cat)
|
if existsFile(test): testSpec r, makeTest(test, options, cat, target = target)
|
||||||
else: echo "[Warning] - ", test, " test does not exist"
|
else: echo "[Warning] - ", test, " test does not exist"
|
||||||
|
|
||||||
proc processCategory(r: var TResults, cat: Category, options: string) =
|
proc processCategory(r: var TResults, cat: Category, options: string) =
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@ import parseutils, strutils, os, osproc, streams, parsecfg
|
||||||
|
|
||||||
var compilerPrefix* = "compiler" / "nim "
|
var compilerPrefix* = "compiler" / "nim "
|
||||||
|
|
||||||
|
let isTravis = existsEnv("TRAVIS")
|
||||||
|
|
||||||
proc cmdTemplate*(): string =
|
proc cmdTemplate*(): string =
|
||||||
compilerPrefix & "$target --lib:lib --hints:on -d:testing $options $file"
|
compilerPrefix & "$target --lib:lib --hints:on -d:testing $options $file"
|
||||||
|
|
||||||
|
|
@ -174,6 +176,8 @@ proc parseSpec*(filename: string): TSpec =
|
||||||
when defined(unix): result.err = reIgnored
|
when defined(unix): result.err = reIgnored
|
||||||
of "posix":
|
of "posix":
|
||||||
when defined(posix): result.err = reIgnored
|
when defined(posix): result.err = reIgnored
|
||||||
|
of "travis":
|
||||||
|
if isTravis: result.err = reIgnored
|
||||||
else:
|
else:
|
||||||
raise newException(ValueError, "cannot interpret as a bool: " & e.value)
|
raise newException(ValueError, "cannot interpret as a bool: " & e.value)
|
||||||
of "cmd":
|
of "cmd":
|
||||||
|
|
|
||||||
|
|
@ -439,6 +439,8 @@ proc main() =
|
||||||
var optPrintResults = false
|
var optPrintResults = false
|
||||||
var optFailing = false
|
var optFailing = false
|
||||||
|
|
||||||
|
var targetsStr = ""
|
||||||
|
|
||||||
var p = initOptParser()
|
var p = initOptParser()
|
||||||
p.next()
|
p.next()
|
||||||
while p.kind == cmdLongoption:
|
while p.kind == cmdLongoption:
|
||||||
|
|
@ -446,7 +448,9 @@ proc main() =
|
||||||
of "print", "verbose": optPrintResults = true
|
of "print", "verbose": optPrintResults = true
|
||||||
of "failing": optFailing = true
|
of "failing": optFailing = true
|
||||||
of "pedantic": discard "now always enabled"
|
of "pedantic": discard "now always enabled"
|
||||||
of "targets": targets = parseTargets(p.val.string)
|
of "targets":
|
||||||
|
targetsStr = p.val.string
|
||||||
|
targets = parseTargets(targetsStr)
|
||||||
of "nim": compilerPrefix = p.val.string
|
of "nim": compilerPrefix = p.val.string
|
||||||
else: quit Usage
|
else: quit Usage
|
||||||
p.next()
|
p.next()
|
||||||
|
|
@ -457,7 +461,9 @@ proc main() =
|
||||||
case action
|
case action
|
||||||
of "all":
|
of "all":
|
||||||
let testsDir = "tests" & DirSep
|
let testsDir = "tests" & DirSep
|
||||||
let myself = quoteShell(findExe("tests" / "testament" / "tester"))
|
var myself = quoteShell(findExe("tests" / "testament" / "tester"))
|
||||||
|
if targetsStr.len > 0:
|
||||||
|
myself &= " '--targets:" & targetsStr & "'"
|
||||||
var cmds: seq[string] = @[]
|
var cmds: seq[string] = @[]
|
||||||
let rest = if p.cmdLineRest.string.len > 0: " " & p.cmdLineRest.string else: ""
|
let rest = if p.cmdLineRest.string.len > 0: " " & p.cmdLineRest.string else: ""
|
||||||
for kind, dir in walkDir(testsDir):
|
for kind, dir in walkDir(testsDir):
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,9 @@
|
||||||
This directory contains tests which are not automatically executed
|
This directory contains integration tests which are not automatically executed
|
||||||
for various reasons. Mainly due to dependencies on external services.
|
for various reasons:
|
||||||
|
- dependency on external services
|
||||||
|
- dependency on files / configuration / state of the local host
|
||||||
|
- tests that are extremely slow or require large amounts of memory or storage
|
||||||
|
- tests that spawn local daemons
|
||||||
|
|
||||||
|
Integration tests can become stale very quickly. Automated ./koch tests are
|
||||||
|
strongly recommended.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue