fixes merge conflict
This commit is contained in:
commit
30597e643f
40 changed files with 1844 additions and 1695 deletions
|
|
@ -6,7 +6,7 @@
|
||||||
- ``macros.callsite`` is now deprecated. Since the introduction of ``varargs``
|
- ``macros.callsite`` is now deprecated. Since the introduction of ``varargs``
|
||||||
parameters this became unnecessary.
|
parameters this became unnecessary.
|
||||||
- Anonymous tuples with a single element can now be written as ``(1,)`` with a
|
- Anonymous tuples with a single element can now be written as ``(1,)`` with a
|
||||||
trailing comma. The underlying AST is ``nnkTupleConst(newLit 1)`` for this
|
trailing comma. The underlying AST is ``nnkTupleConstr(newLit 1)`` for this
|
||||||
example. ``nnkTupleConstr`` is a new node kind your macros need to be able
|
example. ``nnkTupleConstr`` is a new node kind your macros need to be able
|
||||||
to deal with!
|
to deal with!
|
||||||
- Indexing into a ``cstring`` for the JS target is now mapped
|
- Indexing into a ``cstring`` for the JS target is now mapped
|
||||||
|
|
|
||||||
|
|
@ -506,6 +506,7 @@ type
|
||||||
tfGenericTypeParam
|
tfGenericTypeParam
|
||||||
tfImplicitTypeParam
|
tfImplicitTypeParam
|
||||||
tfInferrableStatic
|
tfInferrableStatic
|
||||||
|
tfConceptMatchedTypeSym
|
||||||
tfExplicit # for typedescs, marks types explicitly prefixed with the
|
tfExplicit # for typedescs, marks types explicitly prefixed with the
|
||||||
# `type` operator (e.g. type int)
|
# `type` operator (e.g. type int)
|
||||||
tfWildcard # consider a proc like foo[T, I](x: Type[T, I])
|
tfWildcard # consider a proc like foo[T, I](x: Type[T, I])
|
||||||
|
|
|
||||||
|
|
@ -787,14 +787,13 @@ proc getOutFile2(conf: ConfigRef; filename, ext, dir: string): string =
|
||||||
|
|
||||||
proc writeOutput*(d: PDoc, filename, outExt: string, useWarning = false) =
|
proc writeOutput*(d: PDoc, filename, outExt: string, useWarning = false) =
|
||||||
var content = genOutFile(d)
|
var content = genOutFile(d)
|
||||||
var success = true
|
|
||||||
if optStdout in d.conf.globalOptions:
|
if optStdout in d.conf.globalOptions:
|
||||||
writeRope(stdout, content)
|
writeRope(stdout, content)
|
||||||
else:
|
else:
|
||||||
let outfile = getOutFile2(d.conf, filename, outExt, "htmldocs")
|
let outfile = getOutFile2(d.conf, filename, outExt, "htmldocs")
|
||||||
success = writeRope(content, outfile)
|
createDir(outfile.parentDir)
|
||||||
if not success:
|
if not writeRope(content, outfile):
|
||||||
rawMessage(d.conf, if useWarning: warnCannotOpenFile else: errCannotOpenFile, filename)
|
rawMessage(d.conf, if useWarning: warnCannotOpenFile else: errCannotOpenFile, outfile)
|
||||||
|
|
||||||
proc writeOutputJson*(d: PDoc, filename, outExt: string,
|
proc writeOutputJson*(d: PDoc, filename, outExt: string,
|
||||||
useWarning = false) =
|
useWarning = false) =
|
||||||
|
|
|
||||||
|
|
@ -174,20 +174,32 @@ proc impMod(c: PContext; it: PNode; importStmtResult: PNode) =
|
||||||
#importForwarded(c, m.ast, emptySet)
|
#importForwarded(c, m.ast, emptySet)
|
||||||
|
|
||||||
proc evalImport(c: PContext, n: PNode): PNode =
|
proc evalImport(c: PContext, n: PNode): PNode =
|
||||||
#result = n
|
|
||||||
result = newNodeI(nkImportStmt, n.info)
|
result = newNodeI(nkImportStmt, n.info)
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
let it = n.sons[i]
|
let it = n.sons[i]
|
||||||
if it.kind == nkInfix and it.len == 3 and it[2].kind == nkBracket:
|
if it.kind == nkInfix and it.len == 3 and it[2].kind == nkBracket:
|
||||||
let sep = it[0]
|
let sep = it[0]
|
||||||
let dir = it[1]
|
let dir = it[1]
|
||||||
let a = newNodeI(nkInfix, it.info)
|
var imp = newNodeI(nkInfix, it.info)
|
||||||
a.add sep
|
imp.add sep
|
||||||
a.add dir
|
imp.add dir
|
||||||
a.add sep # dummy entry, replaced in the loop
|
imp.add sep # dummy entry, replaced in the loop
|
||||||
for x in it[2]:
|
for x in it[2]:
|
||||||
a.sons[2] = x
|
if x.kind == nkInfix and x.sons[0].ident.s == "as":
|
||||||
impMod(c, a, result)
|
imp.sons[2] = x.sons[1]
|
||||||
|
let impAs = newNodeI(nkImportAs, it.info)
|
||||||
|
impAs.add imp
|
||||||
|
impAs.add x.sons[2]
|
||||||
|
imp = impAs
|
||||||
|
impMod(c, imp, result)
|
||||||
|
else:
|
||||||
|
imp.sons[2] = x
|
||||||
|
impMod(c, imp, result)
|
||||||
|
elif it.kind == nkInfix and it.sons[0].ident.s == "as":
|
||||||
|
let imp = newNodeI(nkImportAs, it.info)
|
||||||
|
imp.add it.sons[1]
|
||||||
|
imp.add it.sons[2]
|
||||||
|
impMod(c, imp, result)
|
||||||
else:
|
else:
|
||||||
impMod(c, it, result)
|
impMod(c, it, result)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1209,7 +1209,7 @@ proc rawGetTok*(L: var TLexer, tok: var TToken) =
|
||||||
tok.tokType = tkInvalid
|
tok.tokType = tkInvalid
|
||||||
lexMessage(L, errGenerated, "invalid token: " & c & " (\\" & $(ord(c)) & ')')
|
lexMessage(L, errGenerated, "invalid token: " & c & " (\\" & $(ord(c)) & ')')
|
||||||
of '\"':
|
of '\"':
|
||||||
# check for extended raw string literal:
|
# check for generalized raw string literal:
|
||||||
var rawMode = L.bufpos > 0 and L.buf[L.bufpos-1] in SymChars
|
var rawMode = L.bufpos > 0 and L.buf[L.bufpos-1] in SymChars
|
||||||
getString(L, tok, rawMode)
|
getString(L, tok, rawMode)
|
||||||
if rawMode:
|
if rawMode:
|
||||||
|
|
|
||||||
|
|
@ -161,7 +161,7 @@ proc ensureNoMissingOrUnusedSymbols(c: PContext; scope: PScope) =
|
||||||
var s = initTabIter(it, scope.symbols)
|
var s = initTabIter(it, scope.symbols)
|
||||||
var missingImpls = 0
|
var missingImpls = 0
|
||||||
while s != nil:
|
while s != nil:
|
||||||
if sfForward in s.flags and s.kind != skType:
|
if sfForward in s.flags and s.kind notin {skType, skModule}:
|
||||||
# too many 'implementation of X' errors are annoying
|
# too many 'implementation of X' errors are annoying
|
||||||
# and slow 'suggest' down:
|
# and slow 'suggest' down:
|
||||||
if missingImpls == 0:
|
if missingImpls == 0:
|
||||||
|
|
@ -259,7 +259,7 @@ proc errorUseQualifier*(c: PContext; info: TLineInfo; s: PSym) =
|
||||||
proc errorUndeclaredIdentifier*(c: PContext; info: TLineInfo; name: string) =
|
proc errorUndeclaredIdentifier*(c: PContext; info: TLineInfo; name: string) =
|
||||||
var err = "undeclared identifier: '" & name & "'"
|
var err = "undeclared identifier: '" & name & "'"
|
||||||
if c.recursiveDep.len > 0:
|
if c.recursiveDep.len > 0:
|
||||||
err.add "\nThis might be caused by a recursive module dependency: "
|
err.add "\nThis might be caused by a recursive module dependency:\n"
|
||||||
err.add c.recursiveDep
|
err.add c.recursiveDep
|
||||||
# prevent excessive errors for 'nim check'
|
# prevent excessive errors for 'nim check'
|
||||||
c.recursiveDep = ""
|
c.recursiveDep = ""
|
||||||
|
|
|
||||||
|
|
@ -126,13 +126,6 @@ proc getModuleName*(conf: ConfigRef; n: PNode): string =
|
||||||
of nkInfix:
|
of nkInfix:
|
||||||
let n0 = n[0]
|
let n0 = n[0]
|
||||||
let n1 = n[1]
|
let n1 = n[1]
|
||||||
if n0.kind == nkIdent and n0.ident.s == "as":
|
|
||||||
# XXX hack ahead:
|
|
||||||
n.kind = nkImportAs
|
|
||||||
n.sons[0] = n.sons[1]
|
|
||||||
n.sons[1] = n.sons[2]
|
|
||||||
n.sons.setLen(2)
|
|
||||||
return getModuleName(conf, n.sons[0])
|
|
||||||
when false:
|
when false:
|
||||||
if n1.kind == nkPrefix and n1[0].kind == nkIdent and n1[0].ident.s == "$":
|
if n1.kind == nkPrefix and n1[0].kind == nkIdent and n1[0].ident.s == "$":
|
||||||
if n0.kind == nkIdent and n0.ident.s == "/":
|
if n0.kind == nkIdent and n0.ident.s == "/":
|
||||||
|
|
|
||||||
|
|
@ -1638,7 +1638,7 @@ proc parseStaticOrDefer(p: var TParser; k: TNodeKind): PNode =
|
||||||
addSon(result, parseStmt(p))
|
addSon(result, parseStmt(p))
|
||||||
|
|
||||||
proc parseAsm(p: var TParser): PNode =
|
proc parseAsm(p: var TParser): PNode =
|
||||||
#| asmStmt = 'asm' pragma? (STR_LIT | RSTR_LIT | TRIPLE_STR_LIT)
|
#| asmStmt = 'asm' pragma? (STR_LIT | RSTR_LIT | TRIPLESTR_LIT)
|
||||||
result = newNodeP(nkAsmStmt, p)
|
result = newNodeP(nkAsmStmt, p)
|
||||||
getTokNoInd(p)
|
getTokNoInd(p)
|
||||||
if p.tok.tokType == tkCurlyDotLe: addSon(result, parsePragma(p))
|
if p.tok.tokType == tkCurlyDotLe: addSon(result, parsePragma(p))
|
||||||
|
|
|
||||||
|
|
@ -868,11 +868,17 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||||
of wExplain:
|
of wExplain:
|
||||||
sym.flags.incl sfExplain
|
sym.flags.incl sfExplain
|
||||||
of wDeprecated:
|
of wDeprecated:
|
||||||
if sym != nil and sym.kind in routineKinds:
|
if sym != nil and sym.kind in routineKinds + {skType}:
|
||||||
if it.kind in nkPragmaCallKinds: discard getStrLitNode(c, it)
|
if it.kind in nkPragmaCallKinds: discard getStrLitNode(c, it)
|
||||||
incl(sym.flags, sfDeprecated)
|
incl(sym.flags, sfDeprecated)
|
||||||
|
elif sym != nil and sym.kind != skModule:
|
||||||
|
# We don't support the extra annotation field
|
||||||
|
if it.kind in nkPragmaCallKinds:
|
||||||
|
localError(c.config, it.info, "annotation to deprecated not supported here")
|
||||||
|
incl(sym.flags, sfDeprecated)
|
||||||
|
# At this point we're quite sure this is a statement and applies to the
|
||||||
|
# whole module
|
||||||
elif it.kind in nkPragmaCallKinds: deprecatedStmt(c, it)
|
elif it.kind in nkPragmaCallKinds: deprecatedStmt(c, it)
|
||||||
elif sym != nil: incl(sym.flags, sfDeprecated)
|
|
||||||
else: incl(c.module.flags, sfDeprecated)
|
else: incl(c.module.flags, sfDeprecated)
|
||||||
of wVarargs:
|
of wVarargs:
|
||||||
noVal(c, it)
|
noVal(c, it)
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@
|
||||||
## Serialization utilities for the compiler.
|
## Serialization utilities for the compiler.
|
||||||
import strutils, math
|
import strutils, math
|
||||||
|
|
||||||
# MSVC prior to 2013 doesn't have C99 functions
|
# bcc on windows doesn't have C99 functions
|
||||||
when defined(windows) and (defined(vcc) or defined(bcc)):
|
when defined(windows) and defined(bcc):
|
||||||
{.emit: """#if defined(_MSC_VER) && _MSC_VER < 1900
|
{.emit: """#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
static int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) {
|
static int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) {
|
||||||
|
|
|
||||||
|
|
@ -399,12 +399,11 @@ proc updateDefaultParams(call: PNode) =
|
||||||
# the default params with `nfDefaultParam` and `instantiateProcType`
|
# the default params with `nfDefaultParam` and `instantiateProcType`
|
||||||
# computes correctly the default values for each instantiation.
|
# computes correctly the default values for each instantiation.
|
||||||
let calleeParams = call[0].sym.typ.n
|
let calleeParams = call[0].sym.typ.n
|
||||||
for i in countdown(call.len - 1, 1):
|
for i in 1..<call.len:
|
||||||
if nfDefaultParam notin call[i].flags:
|
if nfDefaultParam in call[i].flags:
|
||||||
return
|
let def = calleeParams[i].sym.ast
|
||||||
let def = calleeParams[i].sym.ast
|
if nfDefaultRefsParam in def.flags: call.flags.incl nfDefaultRefsParam
|
||||||
if nfDefaultRefsParam in def.flags: call.flags.incl nfDefaultRefsParam
|
call[i] = def
|
||||||
call[i] = def
|
|
||||||
|
|
||||||
proc semResolvedCall(c: PContext, x: TCandidate,
|
proc semResolvedCall(c: PContext, x: TCandidate,
|
||||||
n: PNode, flags: TExprFlags): PNode =
|
n: PNode, flags: TExprFlags): PNode =
|
||||||
|
|
|
||||||
|
|
@ -352,6 +352,11 @@ proc isOpImpl(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
res = t.kind == tyProc and
|
res = t.kind == tyProc and
|
||||||
t.callConv == ccClosure and
|
t.callConv == ccClosure and
|
||||||
tfIterator notin t.flags
|
tfIterator notin t.flags
|
||||||
|
of "iterator":
|
||||||
|
let t = skipTypes(t1, abstractRange)
|
||||||
|
res = t.kind == tyProc and
|
||||||
|
t.callConv == ccClosure and
|
||||||
|
tfIterator in t.flags
|
||||||
else:
|
else:
|
||||||
res = false
|
res = false
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -69,9 +69,13 @@ proc foldSub*(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
||||||
checkInRange(g.config, n, res):
|
checkInRange(g.config, n, res):
|
||||||
result = newIntNodeT(res, n, g)
|
result = newIntNodeT(res, n, g)
|
||||||
|
|
||||||
|
proc foldUnarySub(a: BiggestInt, n: PNode, g: ModuleGraph): PNode =
|
||||||
|
if a != firstOrd(g.config, n.typ):
|
||||||
|
result = newIntNodeT(-a, n, g)
|
||||||
|
|
||||||
proc foldAbs*(a: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
proc foldAbs*(a: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
||||||
if a != firstOrd(g.config, n.typ):
|
if a != firstOrd(g.config, n.typ):
|
||||||
result = newIntNodeT(a, n, g)
|
result = newIntNodeT(abs(a), n, g)
|
||||||
|
|
||||||
proc foldMod*(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
proc foldMod*(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
||||||
if b != 0'i64:
|
if b != 0'i64:
|
||||||
|
|
@ -173,32 +177,41 @@ proc makeRangeF(typ: PType, first, last: BiggestFloat; g: ModuleGraph): PType =
|
||||||
result.n = n
|
result.n = n
|
||||||
addSonSkipIntLit(result, skipTypes(typ, {tyRange}))
|
addSonSkipIntLit(result, skipTypes(typ, {tyRange}))
|
||||||
|
|
||||||
proc evalIs(n, a: PNode): PNode =
|
proc evalIs(n: PNode, lhs: PSym, g: ModuleGraph): PNode =
|
||||||
# XXX: This should use the standard isOpImpl
|
# XXX: This should use the standard isOpImpl
|
||||||
#internalAssert a.kind == nkSym and a.sym.kind == skType
|
internalAssert g.config,
|
||||||
#internalAssert n.sonsLen == 3 and
|
n.sonsLen == 3 and
|
||||||
# n[2].kind in {nkStrLit..nkTripleStrLit, nkType}
|
lhs.typ != nil and
|
||||||
|
n[2].kind in {nkStrLit..nkTripleStrLit, nkType}
|
||||||
|
|
||||||
let t1 = a.sym.typ
|
var
|
||||||
|
res = false
|
||||||
|
t1 = lhs.typ
|
||||||
|
t2 = n[2].typ
|
||||||
|
|
||||||
|
if t1.kind == tyTypeDesc and t2.kind != tyTypeDesc:
|
||||||
|
t1 = t1.base
|
||||||
|
|
||||||
if n[2].kind in {nkStrLit..nkTripleStrLit}:
|
if n[2].kind in {nkStrLit..nkTripleStrLit}:
|
||||||
case n[2].strVal.normalize
|
case n[2].strVal.normalize
|
||||||
of "closure":
|
of "closure":
|
||||||
let t = skipTypes(t1, abstractRange)
|
let t = skipTypes(t1, abstractRange)
|
||||||
result = newIntNode(nkIntLit, ord(t.kind == tyProc and
|
res = t.kind == tyProc and
|
||||||
t.callConv == ccClosure and
|
t.callConv == ccClosure and
|
||||||
tfIterator notin t.flags))
|
tfIterator notin t.flags
|
||||||
of "iterator":
|
of "iterator":
|
||||||
let t = skipTypes(t1, abstractRange)
|
let t = skipTypes(t1, abstractRange)
|
||||||
result = newIntNode(nkIntLit, ord(t.kind == tyProc and
|
res = t.kind == tyProc and
|
||||||
t.callConv == ccClosure and
|
t.callConv == ccClosure and
|
||||||
tfIterator in t.flags))
|
tfIterator in t.flags
|
||||||
else: discard
|
else:
|
||||||
|
res = false
|
||||||
else:
|
else:
|
||||||
# XXX semexprs.isOpImpl is slightly different and requires a context. yay.
|
# XXX semexprs.isOpImpl is slightly different and requires a context. yay.
|
||||||
let t2 = n[2].typ
|
let t2 = n[2].typ
|
||||||
var match = sameType(t1, t2)
|
res = sameType(t1, t2)
|
||||||
result = newIntNode(nkIntLit, ord(match))
|
|
||||||
|
result = newIntNode(nkIntLit, ord(res))
|
||||||
result.typ = n.typ
|
result.typ = n.typ
|
||||||
|
|
||||||
proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
|
proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
|
||||||
|
|
@ -207,7 +220,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
|
||||||
case m
|
case m
|
||||||
of mOrd: result = newIntNodeT(getOrdValue(a), n, g)
|
of mOrd: result = newIntNodeT(getOrdValue(a), n, g)
|
||||||
of mChr: result = newIntNodeT(getInt(a), n, g)
|
of mChr: result = newIntNodeT(getInt(a), n, g)
|
||||||
of mUnaryMinusI, mUnaryMinusI64: result = newIntNodeT(- getInt(a), n, g)
|
of mUnaryMinusI, mUnaryMinusI64: result = foldUnarySub(getInt(a), n, g)
|
||||||
of mUnaryMinusF64: result = newFloatNodeT(- getFloat(a), n, g)
|
of mUnaryMinusF64: result = newFloatNodeT(- getFloat(a), n, g)
|
||||||
of mNot: result = newIntNodeT(1 - getInt(a), n, g)
|
of mNot: result = newIntNodeT(1 - getInt(a), n, g)
|
||||||
of mCard: result = newIntNodeT(nimsets.cardSet(g.config, a), n, g)
|
of mCard: result = newIntNodeT(nimsets.cardSet(g.config, a), n, g)
|
||||||
|
|
@ -584,6 +597,9 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||||
result = copyTree(s.ast)
|
result = copyTree(s.ast)
|
||||||
of skProc, skFunc, skMethod:
|
of skProc, skFunc, skMethod:
|
||||||
result = n
|
result = n
|
||||||
|
of skParam:
|
||||||
|
if s.typ != nil and s.typ.kind == tyTypeDesc:
|
||||||
|
result = newSymNodeTypeDesc(s, n.info)
|
||||||
of skType:
|
of skType:
|
||||||
# XXX gensym'ed symbols can come here and cannot be resolved. This is
|
# XXX gensym'ed symbols can come here and cannot be resolved. This is
|
||||||
# dirty, but correct.
|
# dirty, but correct.
|
||||||
|
|
@ -651,9 +667,9 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||||
of mConStrStr:
|
of mConStrStr:
|
||||||
result = foldConStrStr(m, n, g)
|
result = foldConStrStr(m, n, g)
|
||||||
of mIs:
|
of mIs:
|
||||||
let a = getConstExpr(m, n[1], g)
|
let lhs = getConstExpr(m, n[1], g)
|
||||||
if a != nil and a.kind == nkSym and a.sym.kind == skType:
|
if lhs != nil and lhs.kind == nkSym:
|
||||||
result = evalIs(n, a)
|
result = evalIs(n, lhs.sym, g)
|
||||||
else:
|
else:
|
||||||
result = magicCall(m, n, g)
|
result = magicCall(m, n, g)
|
||||||
except OverflowError:
|
except OverflowError:
|
||||||
|
|
|
||||||
|
|
@ -372,7 +372,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
|
||||||
if n.kind == nkSym:
|
if n.kind == nkSym:
|
||||||
result = getGenSym(c, n.sym)
|
result = getGenSym(c, n.sym)
|
||||||
else:
|
else:
|
||||||
result = pickSym(c, n, {skType, skGenericParam})
|
result = pickSym(c, n, {skType, skGenericParam, skParam})
|
||||||
if result.isNil:
|
if result.isNil:
|
||||||
result = qualifiedLookUp(c, n, {checkAmbiguity, checkUndeclared})
|
result = qualifiedLookUp(c, n, {checkAmbiguity, checkUndeclared})
|
||||||
if result != nil:
|
if result != nil:
|
||||||
|
|
@ -1345,7 +1345,7 @@ proc semTypeClass(c: PContext, n: PNode, prev: PType): PType =
|
||||||
if modifier != tyNone:
|
if modifier != tyNone:
|
||||||
dummyName = param[0]
|
dummyName = param[0]
|
||||||
dummyType = c.makeTypeWithModifier(modifier, candidateTypeSlot)
|
dummyType = c.makeTypeWithModifier(modifier, candidateTypeSlot)
|
||||||
if modifier == tyTypeDesc: dummyType.flags.incl tfExplicit
|
if modifier == tyTypeDesc: dummyType.flags.incl tfConceptMatchedTypeSym
|
||||||
else:
|
else:
|
||||||
dummyName = param
|
dummyName = param
|
||||||
dummyType = candidateTypeSlot
|
dummyType = candidateTypeSlot
|
||||||
|
|
|
||||||
|
|
@ -993,7 +993,8 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
|
||||||
useTypeLoweringRuleInTypeClass = c.c.matchedConcept != nil and
|
useTypeLoweringRuleInTypeClass = c.c.matchedConcept != nil and
|
||||||
not c.isNoCall and
|
not c.isNoCall and
|
||||||
f.kind != tyTypeDesc and
|
f.kind != tyTypeDesc and
|
||||||
tfExplicit notin aOrig.flags
|
tfExplicit notin aOrig.flags and
|
||||||
|
tfConceptMatchedTypeSym notin aOrig.flags
|
||||||
|
|
||||||
aOrig = if useTypeLoweringRuleInTypeClass:
|
aOrig = if useTypeLoweringRuleInTypeClass:
|
||||||
aOrig.skipTypes({tyTypeDesc})
|
aOrig.skipTypes({tyTypeDesc})
|
||||||
|
|
|
||||||
|
|
@ -454,14 +454,23 @@ proc suggestSym*(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym;
|
||||||
suggestResult(conf, symToSuggest(conf, s, isLocal=false, ideOutline, info, 100, PrefixMatch.None, false, 0))
|
suggestResult(conf, symToSuggest(conf, s, isLocal=false, ideOutline, info, 100, PrefixMatch.None, false, 0))
|
||||||
|
|
||||||
proc warnAboutDeprecated(conf: ConfigRef; info: TLineInfo; s: PSym) =
|
proc warnAboutDeprecated(conf: ConfigRef; info: TLineInfo; s: PSym) =
|
||||||
|
var pragmaNode: PNode
|
||||||
|
|
||||||
if s.kind in routineKinds:
|
if s.kind in routineKinds:
|
||||||
let n = s.ast[pragmasPos]
|
pragmaNode = s.ast[pragmasPos]
|
||||||
if n.kind != nkEmpty:
|
elif s.kind in {skType}:
|
||||||
for it in n:
|
# s.ast = nkTypedef / nkPragmaExpr / [nkSym, nkPragma]
|
||||||
if whichPragma(it) == wDeprecated and it.safeLen == 2 and
|
pragmaNode = s.ast[0][1]
|
||||||
it[1].kind in {nkStrLit..nkTripleStrLit}:
|
|
||||||
message(conf, info, warnDeprecated, it[1].strVal & "; " & s.name.s)
|
doAssert pragmaNode == nil or pragmaNode.kind == nkPragma
|
||||||
return
|
|
||||||
|
if pragmaNode != nil:
|
||||||
|
for it in pragmaNode:
|
||||||
|
if whichPragma(it) == wDeprecated and it.safeLen == 2 and
|
||||||
|
it[1].kind in {nkStrLit..nkTripleStrLit}:
|
||||||
|
message(conf, info, warnDeprecated, it[1].strVal & "; " & s.name.s)
|
||||||
|
return
|
||||||
|
|
||||||
message(conf, info, warnDeprecated, s.name.s)
|
message(conf, info, warnDeprecated, s.name.s)
|
||||||
|
|
||||||
proc markUsed(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym) =
|
proc markUsed(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym) =
|
||||||
|
|
|
||||||
|
|
@ -428,6 +428,8 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||||
sfAnon notin t.sym.flags:
|
sfAnon notin t.sym.flags:
|
||||||
if t.kind == tyInt and isIntLit(t):
|
if t.kind == tyInt and isIntLit(t):
|
||||||
result = t.sym.name.s & " literal(" & $t.n.intVal & ")"
|
result = t.sym.name.s & " literal(" & $t.n.intVal & ")"
|
||||||
|
elif t.kind == tyAlias:
|
||||||
|
result = typeToString(t.sons[0])
|
||||||
elif prefer in {preferName, preferTypeName} or t.sym.owner.isNil:
|
elif prefer in {preferName, preferTypeName} or t.sym.owner.isNil:
|
||||||
result = t.sym.name.s
|
result = t.sym.name.s
|
||||||
if t.kind == tyGenericParam and t.sonsLen > 0:
|
if t.kind == tyGenericParam and t.sonsLen > 0:
|
||||||
|
|
|
||||||
|
|
@ -571,8 +571,8 @@ With parenthesis and semicolons ``(;)`` you can use statements where only
|
||||||
an expression is allowed:
|
an expression is allowed:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
# computes fac(4) at compile time:
|
|
||||||
:test: "nim c $1"
|
:test: "nim c $1"
|
||||||
|
# computes fac(4) at compile time:
|
||||||
const fac4 = (var x = 1; for i in 1..4: x *= i; x)
|
const fac4 = (var x = 1; for i in 1..4: x *= i; x)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -265,7 +265,7 @@ proc arcsech*[T: float32|float64](x: T): T = arccosh(1.0 / x)
|
||||||
proc arccsch*[T: float32|float64](x: T): T = arcsinh(1.0 / x)
|
proc arccsch*[T: float32|float64](x: T): T = arcsinh(1.0 / x)
|
||||||
## Computes the inverse hyperbolic cosecant of `x`
|
## Computes the inverse hyperbolic cosecant of `x`
|
||||||
|
|
||||||
const windowsCC89 = defined(windows) and (defined(vcc) or defined(bcc))
|
const windowsCC89 = defined(windows) and defined(bcc)
|
||||||
|
|
||||||
when not defined(JS): # C
|
when not defined(JS): # C
|
||||||
proc hypot*(x, y: float32): float32 {.importc: "hypotf", header: "<math.h>".}
|
proc hypot*(x, y: float32): float32 {.importc: "hypotf", header: "<math.h>".}
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,6 @@ type
|
||||||
length: int
|
length: int
|
||||||
data: string # != nil if a leaf
|
data: string # != nil if a leaf
|
||||||
|
|
||||||
proc isConc(r: Rope): bool {.inline.} = return r.length > 0
|
|
||||||
|
|
||||||
# Note that the left and right pointers are not needed for leafs.
|
# Note that the left and right pointers are not needed for leafs.
|
||||||
# Leaves have relatively high memory overhead (~30 bytes on a 32
|
# Leaves have relatively high memory overhead (~30 bytes on a 32
|
||||||
# bit machine) and we produce many of them. This is why we cache and
|
# bit machine) and we produce many of them. This is why we cache and
|
||||||
|
|
@ -50,12 +48,12 @@ proc isConc(r: Rope): bool {.inline.} = return r.length > 0
|
||||||
proc len*(a: Rope): int {.rtl, extern: "nro$1".} =
|
proc len*(a: Rope): int {.rtl, extern: "nro$1".} =
|
||||||
## the rope's length
|
## the rope's length
|
||||||
if a == nil: result = 0
|
if a == nil: result = 0
|
||||||
else: result = abs a.length
|
else: result = a.length
|
||||||
|
|
||||||
proc newRope(): Rope = new(result)
|
proc newRope(): Rope = new(result)
|
||||||
proc newRope(data: string): Rope =
|
proc newRope(data: string): Rope =
|
||||||
new(result)
|
new(result)
|
||||||
result.length = -len(data)
|
result.length = len(data)
|
||||||
result.data = data
|
result.data = data
|
||||||
|
|
||||||
var
|
var
|
||||||
|
|
@ -170,7 +168,9 @@ proc `&`*(a, b: Rope): Rope {.rtl, extern: "nroConcRopeRope".} =
|
||||||
result = a
|
result = a
|
||||||
else:
|
else:
|
||||||
result = newRope()
|
result = newRope()
|
||||||
result.length = abs(a.length) + abs(b.length)
|
result.length = a.length + b.length
|
||||||
|
result.left = a
|
||||||
|
result.right = b
|
||||||
|
|
||||||
proc `&`*(a: Rope, b: string): Rope {.rtl, extern: "nroConcRopeStr".} =
|
proc `&`*(a: Rope, b: string): Rope {.rtl, extern: "nroConcRopeStr".} =
|
||||||
## the concatenation operator for ropes.
|
## the concatenation operator for ropes.
|
||||||
|
|
@ -199,11 +199,11 @@ proc `[]`*(r: Rope, i: int): char {.rtl, extern: "nroCharAt".} =
|
||||||
var j = i
|
var j = i
|
||||||
if x == nil: return
|
if x == nil: return
|
||||||
while true:
|
while true:
|
||||||
if not isConc(x):
|
if x != nil and x.data.len > 0:
|
||||||
if x.data.len <% j: return x.data[j]
|
if j < x.data.len: return x.data[j]
|
||||||
return '\0'
|
return '\0'
|
||||||
else:
|
else:
|
||||||
if x.left.len >% j:
|
if x.left.length > j:
|
||||||
x = x.left
|
x = x.left
|
||||||
else:
|
else:
|
||||||
x = x.right
|
x = x.right
|
||||||
|
|
@ -215,7 +215,8 @@ iterator leaves*(r: Rope): string =
|
||||||
var stack = @[r]
|
var stack = @[r]
|
||||||
while stack.len > 0:
|
while stack.len > 0:
|
||||||
var it = stack.pop
|
var it = stack.pop
|
||||||
while isConc(it):
|
while it.left != nil:
|
||||||
|
assert(it.right != nil)
|
||||||
stack.add(it.right)
|
stack.add(it.right)
|
||||||
it = it.left
|
it = it.left
|
||||||
assert(it != nil)
|
assert(it != nil)
|
||||||
|
|
|
||||||
|
|
@ -423,18 +423,14 @@ proc toUnix*(t: Time): int64 {.benign, tags: [], raises: [], noSideEffect.} =
|
||||||
## Convert ``t`` to a unix timestamp (seconds since ``1970-01-01T00:00:00Z``).
|
## Convert ``t`` to a unix timestamp (seconds since ``1970-01-01T00:00:00Z``).
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
doAssert fromUnix(0).toUnix() == 0
|
doAssert fromUnix(0).toUnix() == 0
|
||||||
|
|
||||||
t.seconds
|
t.seconds
|
||||||
|
|
||||||
proc fromWinTime*(win: int64): Time =
|
proc fromWinTime*(win: int64): Time =
|
||||||
## Convert a Windows file time (100-nanosecond intervals since ``1601-01-01T00:00:00Z``)
|
## Convert a Windows file time (100-nanosecond intervals since ``1601-01-01T00:00:00Z``)
|
||||||
## to a ``Time``.
|
## to a ``Time``.
|
||||||
let hnsecsSinceEpoch = (win - epochDiff)
|
const hnsecsPerSec = convert(Seconds, Nanoseconds, 1) div 100
|
||||||
var seconds = hnsecsSinceEpoch div rateDiff
|
let nanos = floorMod(win, hnsecsPerSec) * 100
|
||||||
var nanos = ((hnsecsSinceEpoch mod rateDiff) * 100).int
|
let seconds = floorDiv(win - epochDiff, hnsecsPerSec)
|
||||||
if nanos < 0:
|
|
||||||
nanos += convert(Seconds, Nanoseconds, 1)
|
|
||||||
seconds -= 1
|
|
||||||
result = initTime(seconds, nanos)
|
result = initTime(seconds, nanos)
|
||||||
|
|
||||||
proc toWinTime*(t: Time): int64 =
|
proc toWinTime*(t: Time): int64 =
|
||||||
|
|
|
||||||
|
|
@ -3767,23 +3767,23 @@ template assert*(cond: bool, msg = "") =
|
||||||
## The compiler may not generate any code at all for ``assert`` if it is
|
## The compiler may not generate any code at all for ``assert`` if it is
|
||||||
## advised to do so through the ``-d:release`` or ``--assertions:off``
|
## advised to do so through the ``-d:release`` or ``--assertions:off``
|
||||||
## `command line switches <nimc.html#command-line-switches>`_.
|
## `command line switches <nimc.html#command-line-switches>`_.
|
||||||
|
# NOTE: `true` is correct here; --excessiveStackTrace:on will control whether
|
||||||
|
# or not to output full paths.
|
||||||
bind instantiationInfo
|
bind instantiationInfo
|
||||||
mixin failedAssertImpl
|
mixin failedAssertImpl
|
||||||
when compileOption("assertions"):
|
{.line: instantiationInfo(fullPaths = true).}:
|
||||||
{.line.}:
|
when compileOption("assertions"):
|
||||||
if not cond: failedAssertImpl(astToStr(cond) & ' ' & msg)
|
if not cond: failedAssertImpl(astToStr(cond) & ' ' & msg)
|
||||||
|
|
||||||
template doAssert*(cond: bool, msg = "") =
|
template doAssert*(cond: bool, msg = "") =
|
||||||
## same as `assert` but is always turned on and not affected by the
|
## same as `assert` but is always turned on and not affected by the
|
||||||
## ``--assertions`` command line switch.
|
## ``--assertions`` command line switch.
|
||||||
bind instantiationInfo
|
|
||||||
# NOTE: `true` is correct here; --excessiveStackTrace:on will control whether
|
# NOTE: `true` is correct here; --excessiveStackTrace:on will control whether
|
||||||
# or not to output full paths.
|
# or not to output full paths.
|
||||||
{.line: instantiationInfo(-1, true).}:
|
bind instantiationInfo
|
||||||
if not cond:
|
mixin failedAssertImpl
|
||||||
raiseAssert(astToStr(cond) & ' ' &
|
{.line: instantiationInfo(fullPaths = true).}:
|
||||||
instantiationInfo(-1, false).fileName & '(' &
|
if not cond: failedAssertImpl(astToStr(cond) & ' ' & msg)
|
||||||
$instantiationInfo(-1, false).line & ") " & msg)
|
|
||||||
|
|
||||||
iterator items*[T](a: seq[T]): T {.inline.} =
|
iterator items*[T](a: seq[T]): T {.inline.} =
|
||||||
## iterates over each item of `a`.
|
## iterates over each item of `a`.
|
||||||
|
|
|
||||||
11
tests/assert/tfaileddoassert.nim
Normal file
11
tests/assert/tfaileddoassert.nim
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
discard """
|
||||||
|
cmd: "nim $target -d:release $options $file"
|
||||||
|
output: '''
|
||||||
|
assertion occured!!!!!! false
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
onFailedAssert(msg):
|
||||||
|
echo("assertion occured!!!!!! ", msg)
|
||||||
|
|
||||||
|
doAssert(1 == 2)
|
||||||
|
|
@ -11,3 +11,15 @@ type Monoid = concept x, y
|
||||||
proc z(x: typedesc[int]): int = 0
|
proc z(x: typedesc[int]): int = 0
|
||||||
|
|
||||||
echo(int is Monoid)
|
echo(int is Monoid)
|
||||||
|
|
||||||
|
# https://github.com/nim-lang/Nim/issues/8126
|
||||||
|
type AdditiveMonoid* = concept x, y, type T
|
||||||
|
x + y is T
|
||||||
|
|
||||||
|
# some redundant checks to test an alternative approaches:
|
||||||
|
type TT = type(x)
|
||||||
|
x + y is type(x)
|
||||||
|
x + y is TT
|
||||||
|
|
||||||
|
doAssert(1 is AdditiveMonoid)
|
||||||
|
|
||||||
|
|
|
||||||
10
tests/deprecated/importme.nim
Normal file
10
tests/deprecated/importme.nim
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
type
|
||||||
|
Ty* {.deprecated.} = uint32
|
||||||
|
Ty1* {.deprecated: "hello".} = uint32
|
||||||
|
|
||||||
|
var aVar* {.deprecated.}: char
|
||||||
|
|
||||||
|
proc aProc*() {.deprecated.} = discard
|
||||||
|
proc aProc1*() {.deprecated: "hello".} = discard
|
||||||
|
|
||||||
|
{.deprecated: "goodbye".}
|
||||||
23
tests/deprecated/tmodule1.nim
Normal file
23
tests/deprecated/tmodule1.nim
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
discard """
|
||||||
|
nimout: '''tmodule1.nim(11, 8) Warning: goodbye; importme is deprecated [Deprecated]
|
||||||
|
tmodule1.nim(14, 10) Warning: Ty is deprecated [Deprecated]
|
||||||
|
tmodule1.nim(17, 10) Warning: hello; Ty1 is deprecated [Deprecated]
|
||||||
|
tmodule1.nim(20, 8) Warning: aVar is deprecated [Deprecated]
|
||||||
|
tmodule1.nim(22, 3) Warning: aProc is deprecated [Deprecated]
|
||||||
|
tmodule1.nim(23, 3) Warning: hello; aProc1 is deprecated [Deprecated]
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
import importme
|
||||||
|
|
||||||
|
block:
|
||||||
|
var z: Ty
|
||||||
|
z = 0
|
||||||
|
block:
|
||||||
|
var z: Ty1
|
||||||
|
z = 0
|
||||||
|
block:
|
||||||
|
echo aVar
|
||||||
|
block:
|
||||||
|
aProc()
|
||||||
|
aProc1()
|
||||||
7
tests/deprecated/tnoannot.nim
Normal file
7
tests/deprecated/tnoannot.nim
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
discard """
|
||||||
|
line: 7
|
||||||
|
errormsg: "annotation to deprecated not supported here"
|
||||||
|
"""
|
||||||
|
|
||||||
|
var foo* {.deprecated.} = 42
|
||||||
|
var foo1* {.deprecated: "no".} = 42
|
||||||
8
tests/errmsgs/t8339.nim
Normal file
8
tests/errmsgs/t8339.nim
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
discard """
|
||||||
|
line: 8
|
||||||
|
errormsg: "type mismatch: got <seq[int]> but expected 'seq[float]'"
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sequtils
|
||||||
|
|
||||||
|
var x: seq[float] = @[1].mapIt(it)
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
discard """
|
|
||||||
action: run
|
|
||||||
"""
|
|
||||||
|
|
||||||
import times
|
|
||||||
|
|
||||||
# $ date --date='@2147483647'
|
|
||||||
# Tue 19 Jan 03:14:07 GMT 2038
|
|
||||||
|
|
||||||
block yeardayTest:
|
|
||||||
doAssert fromUnix(2147483647).utc.yearday == 18
|
|
||||||
|
|
||||||
block localTime:
|
|
||||||
var local = now()
|
|
||||||
let utc = local.utc
|
|
||||||
doAssert local.toTime == utc.toTime
|
|
||||||
|
|
||||||
let a = fromUnix(1_000_000_000)
|
|
||||||
let b = fromUnix(1_500_000_000)
|
|
||||||
doAssert b - a == initDuration(seconds = 500_000_000)
|
|
||||||
|
|
||||||
# Because we can't change the timezone JS uses, we define a simple static timezone for testing.
|
|
||||||
|
|
||||||
proc zonedTimeFromTime(time: Time): ZonedTime =
|
|
||||||
result.utcOffset = -7200
|
|
||||||
result.isDst = false
|
|
||||||
result.time = time
|
|
||||||
|
|
||||||
proc zonedTimeFromAdjTime(adjTime: Time): ZonedTIme =
|
|
||||||
result.utcOffset = -7200
|
|
||||||
result.isDst = false
|
|
||||||
result.time = adjTime + initDuration(seconds = -7200)
|
|
||||||
|
|
||||||
let utcPlus2 = newTimezone("", zonedTimeFromTime, zonedTimeFromAdjTime)
|
|
||||||
|
|
||||||
block timezoneTests:
|
|
||||||
let dt = initDateTime(01, mJan, 2017, 12, 00, 00, utcPlus2)
|
|
||||||
doAssert $dt == "2017-01-01T12:00:00+02:00"
|
|
||||||
doAssert $dt.utc == "2017-01-01T10:00:00Z"
|
|
||||||
doAssert $dt.utc.inZone(utcPlus2) == $dt
|
|
||||||
|
|
||||||
doAssert $initDateTime(01, mJan, 1911, 12, 00, 00, utc()) == "1911-01-01T12:00:00Z"
|
|
||||||
doAssert $initDateTime(01, mJan, 0023, 12, 00, 00, utc()) == "0023-01-01T12:00:00Z"
|
|
||||||
29
tests/magics/t8693.nim
Normal file
29
tests/magics/t8693.nim
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
discard """
|
||||||
|
output: '''true
|
||||||
|
false
|
||||||
|
true
|
||||||
|
false
|
||||||
|
false
|
||||||
|
true
|
||||||
|
true
|
||||||
|
false
|
||||||
|
true
|
||||||
|
true
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
type Foo = int | float
|
||||||
|
|
||||||
|
proc bar(t1, t2: typedesc): bool =
|
||||||
|
echo (t1 is t2)
|
||||||
|
(t2 is t1)
|
||||||
|
|
||||||
|
proc bar[T](x: T, t2: typedesc): bool =
|
||||||
|
echo (T is t2)
|
||||||
|
(t2 is T)
|
||||||
|
|
||||||
|
echo bar(int, Foo)
|
||||||
|
echo bar(4, Foo)
|
||||||
|
echo bar(any, int)
|
||||||
|
echo bar(int, any)
|
||||||
|
echo bar(Foo, Foo)
|
||||||
|
|
@ -9,6 +9,7 @@ doAssertRaises(DivByZeroError): discard 1 mod 0
|
||||||
doAssertRaises(DivByZeroError): discard 1 div 0
|
doAssertRaises(DivByZeroError): discard 1 div 0
|
||||||
doAssertRaises(OverflowError): discard low(int8) div -1'i8
|
doAssertRaises(OverflowError): discard low(int8) div -1'i8
|
||||||
|
|
||||||
|
doAssertRaises(OverflowError): discard -low(int64)
|
||||||
doAssertRaises(OverflowError): discard low(int64) - 1'i64
|
doAssertRaises(OverflowError): discard low(int64) - 1'i64
|
||||||
doAssertRaises(OverflowError): discard high(int64) + 1'i64
|
doAssertRaises(OverflowError): discard high(int64) + 1'i64
|
||||||
|
|
||||||
|
|
@ -21,3 +22,6 @@ doAssertRaises(OverflowError): discard low(int64) * -1
|
||||||
doAssertRaises(OverflowError): discard high(int8) * 2
|
doAssertRaises(OverflowError): discard high(int8) * 2
|
||||||
doAssertRaises(OverflowError): discard high(int64) * 2
|
doAssertRaises(OverflowError): discard high(int64) * 2
|
||||||
|
|
||||||
|
doAssert abs(-1) == 1
|
||||||
|
doAssert 2 div 2 == 1
|
||||||
|
doAssert 2 * 3 == 6
|
||||||
1
tests/modules/t8665.nim
Normal file
1
tests/modules/t8665.nim
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
import treorder
|
||||||
11
tests/modules/timportas.nim
Normal file
11
tests/modules/timportas.nim
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
discard """
|
||||||
|
action: run
|
||||||
|
"""
|
||||||
|
|
||||||
|
import .. / modules / [definitions as foo]
|
||||||
|
import std / times as bar
|
||||||
|
import definitions as baz
|
||||||
|
|
||||||
|
discard foo.v
|
||||||
|
discard bar.now
|
||||||
|
discard baz.v
|
||||||
|
|
@ -40,3 +40,7 @@ static:
|
||||||
assert y isnot tuple
|
assert y isnot tuple
|
||||||
assert z isnot seq
|
assert z isnot seq
|
||||||
|
|
||||||
|
# XXX: These cases don't work properly at the moment:
|
||||||
|
# assert type[int] isnot int
|
||||||
|
# assert type(int) isnot int
|
||||||
|
|
||||||
|
|
|
||||||
10
tests/proc/t8357.nim
Normal file
10
tests/proc/t8357.nim
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
discard """
|
||||||
|
output: "Hello"
|
||||||
|
"""
|
||||||
|
|
||||||
|
type
|
||||||
|
T = ref int
|
||||||
|
|
||||||
|
let r = new(string)
|
||||||
|
r[] = "Hello"
|
||||||
|
echo r[]
|
||||||
11
tests/proc/t8683.nim
Normal file
11
tests/proc/t8683.nim
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
discard """
|
||||||
|
output: "1"
|
||||||
|
"""
|
||||||
|
|
||||||
|
proc foo[T](bar: proc (x, y: T): int = system.cmp, baz: int) =
|
||||||
|
echo "1"
|
||||||
|
|
||||||
|
proc foo[T](bar: proc (x, y: T): int = system.cmp) =
|
||||||
|
echo "2"
|
||||||
|
|
||||||
|
foo[int](baz = 5)
|
||||||
36
tests/stdlib/tropes.nim
Normal file
36
tests/stdlib/tropes.nim
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
discard """
|
||||||
|
file: "tropes.nim"
|
||||||
|
output: '''0
|
||||||
|
3
|
||||||
|
|
||||||
|
123
|
||||||
|
3
|
||||||
|
6
|
||||||
|
123
|
||||||
|
123456
|
||||||
|
2
|
||||||
|
3'''
|
||||||
|
"""
|
||||||
|
import ropes
|
||||||
|
|
||||||
|
var
|
||||||
|
r1 = rope("")
|
||||||
|
r2 = rope("123")
|
||||||
|
|
||||||
|
echo r1.len
|
||||||
|
echo r2.len
|
||||||
|
|
||||||
|
echo r1
|
||||||
|
echo r2
|
||||||
|
|
||||||
|
r1.add("123")
|
||||||
|
r2.add("456")
|
||||||
|
|
||||||
|
echo r1.len
|
||||||
|
echo r2.len
|
||||||
|
|
||||||
|
echo r1
|
||||||
|
echo r2
|
||||||
|
|
||||||
|
echo r1[1]
|
||||||
|
echo r2[2]
|
||||||
|
|
@ -1,12 +1,20 @@
|
||||||
# test the new time module
|
|
||||||
discard """
|
discard """
|
||||||
file: "ttimes.nim"
|
file: "ttimes.nim"
|
||||||
|
target: "c js"
|
||||||
output: '''[Suite] ttimes
|
output: '''[Suite] ttimes
|
||||||
'''
|
'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import
|
import times, strutils, unittest
|
||||||
times, os, strutils, unittest
|
|
||||||
|
when not defined(js):
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Normally testament configures unittest with environment variables,
|
||||||
|
# but that doesn't work for the JS target. So instead we must set the correct
|
||||||
|
# settings here.
|
||||||
|
addOutputFormatter(
|
||||||
|
newConsoleOutputFormatter(PRINT_FAILURES, colorOutput = false))
|
||||||
|
|
||||||
proc staticTz(hours, minutes, seconds: int = 0): Timezone {.noSideEffect.} =
|
proc staticTz(hours, minutes, seconds: int = 0): Timezone {.noSideEffect.} =
|
||||||
let offset = hours * 3600 + minutes * 60 + seconds
|
let offset = hours * 3600 + minutes * 60 + seconds
|
||||||
|
|
@ -23,99 +31,12 @@ proc staticTz(hours, minutes, seconds: int = 0): Timezone {.noSideEffect.} =
|
||||||
|
|
||||||
newTimezone("", zonedTimeFromTime, zonedTImeFromAdjTime)
|
newTimezone("", zonedTimeFromTime, zonedTImeFromAdjTime)
|
||||||
|
|
||||||
# $ date --date='@2147483647'
|
|
||||||
# Tue 19 Jan 03:14:07 GMT 2038
|
|
||||||
|
|
||||||
proc checkFormat(t: DateTime, format, expected: string) =
|
|
||||||
let actual = t.format(format)
|
|
||||||
if actual != expected:
|
|
||||||
echo "Formatting failure!"
|
|
||||||
echo "expected: ", expected
|
|
||||||
echo "actual : ", actual
|
|
||||||
doAssert false
|
|
||||||
|
|
||||||
let t2 = fromUnix(160070789).utc() # Mon 27 Jan 16:06:29 GMT 1975
|
|
||||||
t2.checkFormat("d dd ddd dddd h hh H HH m mm M MM MMM MMMM s" &
|
|
||||||
" ss t tt y yy yyy yyyy yyyyy z zz zzz",
|
|
||||||
"27 27 Mon Monday 4 04 16 16 6 06 1 01 Jan January 29 29 P PM 5 75 975 1975 01975 Z Z Z")
|
|
||||||
|
|
||||||
var t4 = fromUnix(876124714).utc # Mon 6 Oct 08:58:34 BST 1997
|
|
||||||
t4.checkFormat("M MM MMM MMMM", "10 10 Oct October")
|
|
||||||
|
|
||||||
# Interval tests
|
|
||||||
(t4 - initTimeInterval(years = 2)).checkFormat("yyyy", "1995")
|
|
||||||
(t4 - initTimeInterval(years = 7, minutes = 34, seconds = 24)).checkFormat("yyyy mm ss", "1990 24 10")
|
|
||||||
|
|
||||||
# checking dayOfWeek matches known days
|
|
||||||
doAssert getDayOfWeek(01, mJan, 0000) == dSat
|
|
||||||
doAssert getDayOfWeek(01, mJan, -0023) == dSat
|
|
||||||
doAssert getDayOfWeek(21, mSep, 1900) == dFri
|
|
||||||
doAssert getDayOfWeek(01, mJan, 1970) == dThu
|
|
||||||
doAssert getDayOfWeek(21, mSep, 1970) == dMon
|
|
||||||
doAssert getDayOfWeek(01, mJan, 2000) == dSat
|
|
||||||
doAssert getDayOfWeek(01, mJan, 2021) == dFri
|
|
||||||
|
|
||||||
# toUnix tests with GM timezone
|
|
||||||
let t4L = fromUnix(876124714).utc
|
|
||||||
doAssert toUnix(toTime(t4L)) == 876124714
|
|
||||||
doAssert toUnix(toTime(t4L)) + t4L.utcOffset == toUnix(toTime(t4))
|
|
||||||
|
|
||||||
# adding intervals
|
|
||||||
var
|
|
||||||
a1L = toUnix(toTime(t4L + initTimeInterval(hours = 1))) + t4L.utcOffset
|
|
||||||
a1G = toUnix(toTime(t4)) + 60 * 60
|
|
||||||
doAssert a1L == a1G
|
|
||||||
|
|
||||||
# subtracting intervals
|
|
||||||
a1L = toUnix(toTime(t4L - initTimeInterval(hours = 1))) + t4L.utcOffset
|
|
||||||
a1G = toUnix(toTime(t4)) - (60 * 60)
|
|
||||||
doAssert a1L == a1G
|
|
||||||
|
|
||||||
# Comparison between Time objects should be detected by compiler
|
|
||||||
# as 'noSideEffect'.
|
|
||||||
proc cmpTimeNoSideEffect(t1: Time, t2: Time): bool {.noSideEffect.} =
|
|
||||||
result = t1 == t2
|
|
||||||
doAssert cmpTimeNoSideEffect(0.fromUnix, 0.fromUnix)
|
|
||||||
# Additionally `==` generic for seq[T] has explicit 'noSideEffect' pragma
|
|
||||||
# so we can check above condition by comparing seq[Time] sequences
|
|
||||||
let seqA: seq[Time] = @[]
|
|
||||||
let seqB: seq[Time] = @[]
|
|
||||||
doAssert seqA == seqB
|
|
||||||
|
|
||||||
for tz in [
|
|
||||||
(staticTz(seconds = 0), "+0", "+00", "+00:00"), # UTC
|
|
||||||
(staticTz(seconds = -3600), "+1", "+01", "+01:00"), # CET
|
|
||||||
(staticTz(seconds = -39600), "+11", "+11", "+11:00"), # two digits
|
|
||||||
(staticTz(seconds = -1800), "+0", "+00", "+00:30"), # half an hour
|
|
||||||
(staticTz(seconds = 7200), "-2", "-02", "-02:00"), # positive
|
|
||||||
(staticTz(seconds = 38700), "-10", "-10", "-10:45")]: # positive with three quaters hour
|
|
||||||
let dt = initDateTime(1, mJan, 2000, 00, 00, 00, tz[0])
|
|
||||||
doAssert dt.format("z") == tz[1]
|
|
||||||
doAssert dt.format("zz") == tz[2]
|
|
||||||
doAssert dt.format("zzz") == tz[3]
|
|
||||||
|
|
||||||
block countLeapYears:
|
|
||||||
# 1920, 2004 and 2020 are leap years, and should be counted starting at the following year
|
|
||||||
doAssert countLeapYears(1920) + 1 == countLeapYears(1921)
|
|
||||||
doAssert countLeapYears(2004) + 1 == countLeapYears(2005)
|
|
||||||
doAssert countLeapYears(2020) + 1 == countLeapYears(2021)
|
|
||||||
|
|
||||||
block timezoneConversion:
|
|
||||||
var l = now()
|
|
||||||
let u = l.utc
|
|
||||||
l = u.local
|
|
||||||
|
|
||||||
doAssert l.timezone == local()
|
|
||||||
doAssert u.timezone == utc()
|
|
||||||
|
|
||||||
template parseTest(s, f, sExpected: string, ydExpected: int) =
|
template parseTest(s, f, sExpected: string, ydExpected: int) =
|
||||||
let
|
let
|
||||||
parsed = s.parse(f, utc())
|
parsed = s.parse(f, utc())
|
||||||
parsedStr = $parsed
|
parsedStr = $parsed
|
||||||
if parsedStr != sExpected:
|
|
||||||
echo "GOT ", parsedStr, " EXPECTED ", sExpected, " FORMAT ", f
|
|
||||||
check parsedStr == sExpected
|
check parsedStr == sExpected
|
||||||
check(parsed.yearday == ydExpected)
|
check parsed.yearday == ydExpected
|
||||||
|
|
||||||
template parseTestExcp(s, f: string) =
|
template parseTestExcp(s, f: string) =
|
||||||
expect ValueError:
|
expect ValueError:
|
||||||
|
|
@ -192,7 +113,7 @@ suite "ttimes":
|
||||||
|
|
||||||
# Generate tests for multiple timezone files where available
|
# Generate tests for multiple timezone files where available
|
||||||
# Set the TZ env var for each test
|
# Set the TZ env var for each test
|
||||||
when defined(Linux) or defined(macosx):
|
when defined(linux) or defined(macosx):
|
||||||
const tz_dir = "/usr/share/zoneinfo"
|
const tz_dir = "/usr/share/zoneinfo"
|
||||||
const f = "yyyy-MM-dd HH:mm zzz"
|
const f = "yyyy-MM-dd HH:mm zzz"
|
||||||
|
|
||||||
|
|
@ -333,7 +254,19 @@ suite "ttimes":
|
||||||
check isLeapYear(2000)
|
check isLeapYear(2000)
|
||||||
check (not isLeapYear(1900))
|
check (not isLeapYear(1900))
|
||||||
|
|
||||||
test "subtract months":
|
test "TimeInterval":
|
||||||
|
let t = fromUnix(876124714).utc # Mon 6 Oct 08:58:34 BST 1997
|
||||||
|
# Interval tests
|
||||||
|
let t2 = t - 2.years
|
||||||
|
check t2.year == 1995
|
||||||
|
let t3 = (t - 7.years - 34.minutes - 24.seconds)
|
||||||
|
check t3.year == 1990
|
||||||
|
check t3.minute == 24
|
||||||
|
check t3.second == 10
|
||||||
|
check (t + 1.hours).toTime.toUnix == t.toTime.toUnix + 60 * 60
|
||||||
|
check (t - 1.hours).toTime.toUnix == t.toTime.toUnix - 60 * 60
|
||||||
|
|
||||||
|
test "TimeInterval - months":
|
||||||
var dt = initDateTime(1, mFeb, 2017, 00, 00, 00, utc())
|
var dt = initDateTime(1, mFeb, 2017, 00, 00, 00, utc())
|
||||||
check $(dt - initTimeInterval(months = 1)) == "2017-01-01T00:00:00Z"
|
check $(dt - initTimeInterval(months = 1)) == "2017-01-01T00:00:00Z"
|
||||||
dt = initDateTime(15, mMar, 2017, 00, 00, 00, utc())
|
dt = initDateTime(15, mMar, 2017, 00, 00, 00, utc())
|
||||||
|
|
@ -404,14 +337,17 @@ suite "ttimes":
|
||||||
let day = 24.hours
|
let day = 24.hours
|
||||||
let tomorrow = now + day
|
let tomorrow = now + day
|
||||||
check tomorrow - now == initDuration(days = 1)
|
check tomorrow - now == initDuration(days = 1)
|
||||||
|
|
||||||
test "fromWinTime/toWinTime":
|
# Disabled for JS because it fails due to precision errors
|
||||||
check 0.fromUnix.toWinTime.fromWinTime.toUnix == 0
|
# (The JS target uses float64 for int64).
|
||||||
check (-1).fromWinTime.nanosecond == convert(Seconds, Nanoseconds, 1) - 100
|
when not defined(js):
|
||||||
check -1.fromWinTime.toWinTime == -1
|
test "fromWinTime/toWinTime":
|
||||||
# One nanosecond is discarded due to differences in time resolution
|
check 0.fromUnix.toWinTime.fromWinTime.toUnix == 0
|
||||||
check initTime(0, 101).toWinTime.fromWinTime.nanosecond == 100
|
check (-1).fromWinTime.nanosecond == convert(Seconds, Nanoseconds, 1) - 100
|
||||||
check initTime(0, 101).toWinTime.fromWinTime.nanosecond == 100
|
check (-1).fromWinTime.toWinTime == -1
|
||||||
|
# One nanosecond is discarded due to differences in time resolution
|
||||||
|
check initTime(0, 101).toWinTime.fromWinTime.nanosecond == 100
|
||||||
|
check initTime(0, 101).toWinTime.fromWinTime.nanosecond == 100
|
||||||
|
|
||||||
test "issue 7620":
|
test "issue 7620":
|
||||||
let layout = "M/d/yyyy' 'h:mm:ss' 'tt' 'z"
|
let layout = "M/d/yyyy' 'h:mm:ss' 'tt' 'z"
|
||||||
|
|
@ -477,6 +413,18 @@ suite "ttimes":
|
||||||
expect ValueError:
|
expect ValueError:
|
||||||
discard initTimeFormat("foo'")
|
discard initTimeFormat("foo'")
|
||||||
|
|
||||||
|
for tz in [
|
||||||
|
(staticTz(seconds = 0), "+0", "+00", "+00:00"), # UTC
|
||||||
|
(staticTz(seconds = -3600), "+1", "+01", "+01:00"), # CET
|
||||||
|
(staticTz(seconds = -39600), "+11", "+11", "+11:00"), # two digits
|
||||||
|
(staticTz(seconds = -1800), "+0", "+00", "+00:30"), # half an hour
|
||||||
|
(staticTz(seconds = 7200), "-2", "-02", "-02:00"), # positive
|
||||||
|
(staticTz(seconds = 38700), "-10", "-10", "-10:45")]: # positive with three quaters hour
|
||||||
|
let dt = initDateTime(1, mJan, 2000, 00, 00, 00, tz[0])
|
||||||
|
doAssert dt.format("z") == tz[1]
|
||||||
|
doAssert dt.format("zz") == tz[2]
|
||||||
|
doAssert dt.format("zzz") == tz[3]
|
||||||
|
|
||||||
test "parse":
|
test "parse":
|
||||||
check $parse("20180101", "yyyyMMdd", utc()) == "2018-01-01T00:00:00Z"
|
check $parse("20180101", "yyyyMMdd", utc()) == "2018-01-01T00:00:00Z"
|
||||||
parseTestExcp("+120180101", "yyyyMMdd")
|
parseTestExcp("+120180101", "yyyyMMdd")
|
||||||
|
|
@ -497,3 +445,26 @@ suite "ttimes":
|
||||||
discard parse("'", "''")
|
discard parse("'", "''")
|
||||||
|
|
||||||
parseTestExcp("2000 A", "yyyy g")
|
parseTestExcp("2000 A", "yyyy g")
|
||||||
|
|
||||||
|
test "countLeapYears":
|
||||||
|
# 1920, 2004 and 2020 are leap years, and should be counted starting at the following year
|
||||||
|
check countLeapYears(1920) + 1 == countLeapYears(1921)
|
||||||
|
check countLeapYears(2004) + 1 == countLeapYears(2005)
|
||||||
|
check countLeapYears(2020) + 1 == countLeapYears(2021)
|
||||||
|
|
||||||
|
test "timezoneConversion":
|
||||||
|
var l = now()
|
||||||
|
let u = l.utc
|
||||||
|
l = u.local
|
||||||
|
|
||||||
|
check l.timezone == local()
|
||||||
|
check u.timezone == utc()
|
||||||
|
|
||||||
|
test "getDayOfWeek":
|
||||||
|
check getDayOfWeek(01, mJan, 0000) == dSat
|
||||||
|
check getDayOfWeek(01, mJan, -0023) == dSat
|
||||||
|
check getDayOfWeek(21, mSep, 1900) == dFri
|
||||||
|
check getDayOfWeek(01, mJan, 1970) == dThu
|
||||||
|
check getDayOfWeek(21, mSep, 1970) == dMon
|
||||||
|
check getDayOfWeek(01, mJan, 2000) == dSat
|
||||||
|
check getDayOfWeek(01, mJan, 2021) == dFri
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,8 @@ proc generateTestResultPanelPartial(outfile: File, testResultRow: JsonNode) =
|
||||||
target = testResultRow["target"].str.htmlQuote()
|
target = testResultRow["target"].str.htmlQuote()
|
||||||
action = testResultRow["action"].str.htmlQuote()
|
action = testResultRow["action"].str.htmlQuote()
|
||||||
result = htmlQuote testResultRow["result"].str
|
result = htmlQuote testResultRow["result"].str
|
||||||
expected = testResultRow["expected"].str
|
expected = testResultRow["expected"].getStr
|
||||||
gotten = testResultRow["given"].str
|
gotten = testResultRow["given"].getStr
|
||||||
timestamp = "unknown"
|
timestamp = "unknown"
|
||||||
var
|
var
|
||||||
panelCtxClass, textCtxClass, bgCtxClass: string
|
panelCtxClass, textCtxClass, bgCtxClass: string
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue