Merge branch 'devel' into araq-better-docgen

This commit is contained in:
Araq
2018-09-14 15:48:07 +02:00
27 changed files with 383 additions and 160 deletions

View File

@@ -1540,18 +1540,18 @@ proc genConStrStr(p: PProc, n: PNode, r: var TCompRes) =
if skipTypes(n.sons[1].typ, abstractVarRange).kind == tyChar:
r.res.add("[$1].concat(" % [a.res])
else:
r.res.add("($1.slice(0,-1)).concat(" % [a.res])
r.res.add("($1).concat(" % [a.res])
for i in countup(2, sonsLen(n) - 2):
gen(p, n.sons[i], a)
if skipTypes(n.sons[i].typ, abstractVarRange).kind == tyChar:
r.res.add("[$1]," % [a.res])
else:
r.res.add("$1.slice(0,-1)," % [a.res])
r.res.add("$1," % [a.res])
gen(p, n.sons[sonsLen(n) - 1], a)
if skipTypes(n.sons[sonsLen(n) - 1].typ, abstractVarRange).kind == tyChar:
r.res.add("[$1, 0])" % [a.res])
r.res.add("[$1])" % [a.res])
else:
r.res.add("$1)" % [a.res])
@@ -1658,14 +1658,20 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
else: unaryExpr(p, n, r, "subInt", "subInt($1, 1)")
of mAppendStrCh:
binaryExpr(p, n, r, "addChar",
"if ($1 != null) { addChar($1, $2); } else { $1 = [$2, 0]; }")
"if ($1 != null) { addChar($1, $2); } else { $1 = [$2]; }")
of mAppendStrStr:
var lhs, rhs: TCompRes
gen(p, n[1], lhs)
gen(p, n[2], rhs)
let rhsIsLit = n[2].kind in nkStrKinds
if skipTypes(n.sons[1].typ, abstractVarRange).kind == tyCString:
binaryExpr(p, n, r, "", "if ($1 != null) { $1 += $2; } else { $1 = $2; }")
r.res = "if ($1 != null) { $1 += $2; } else { $1 = $2$3; }" % [
lhs.rdLoc, rhs.rdLoc, if rhsIsLit: nil else: ~".slice()"]
else:
binaryExpr(p, n, r, "",
"if ($1 != null) { $1 = ($1.slice(0, -1)).concat($2); } else { $1 = $2;}")
# XXX: make a copy of $2, because of Javascript's sucking semantics
r.res = "if ($1 != null) { $1 = ($1).concat($2); } else { $1 = $2$3; }" % [
lhs.rdLoc, rhs.rdLoc, if rhsIsLit: nil else: ~".slice()"]
r.kind = resExpr
of mAppendSeqElem:
var x, y: TCompRes
gen(p, n.sons[1], x)
@@ -1693,21 +1699,12 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
of mSizeOf: r.res = rope(getSize(p.config, n.sons[1].typ))
of mChr, mArrToSeq: gen(p, n.sons[1], r) # nothing to do
of mOrd: genOrd(p, n, r)
of mLengthStr:
if n.sons[1].typ.skipTypes(abstractInst).kind == tyCString:
unaryExpr(p, n, r, "", "($1 != null ? $1.length : 0)")
else:
unaryExpr(p, n, r, "", "($1 != null ? $1.length-1 : 0)")
of mXLenStr: unaryExpr(p, n, r, "", "$1.length-1")
of mLengthSeq, mLengthOpenArray, mLengthArray:
of mLengthStr, mLengthSeq, mLengthOpenArray, mLengthArray:
unaryExpr(p, n, r, "", "($1 != null ? $1.length : 0)")
of mXLenSeq:
of mXLenStr, mXLenSeq:
unaryExpr(p, n, r, "", "$1.length")
of mHigh:
if skipTypes(n.sons[1].typ, abstractVar).kind == tyString:
unaryExpr(p, n, r, "", "($1 != null ? ($1.length-2) : -1)")
else:
unaryExpr(p, n, r, "", "($1 != null ? ($1.length-1) : -1)")
unaryExpr(p, n, r, "", "($1 != null ? ($1.length-1) : -1)")
of mInc:
if n[1].typ.skipTypes(abstractRange).kind in tyUInt .. tyUInt64:
binaryUintExpr(p, n, r, "+", true)
@@ -1721,7 +1718,7 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 -= $2")
else: binaryExpr(p, n, r, "subInt", "$1 = subInt($1, $2)")
of mSetLengthStr:
binaryExpr(p, n, r, "", "$1.length = $2+1; $1[$1.length-1] = 0")
binaryExpr(p, n, r, "", "$1.length = $2")
of mSetLengthSeq:
var x, y: TCompRes
gen(p, n.sons[1], x)
@@ -1750,8 +1747,6 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
localError(p.config, n.info, errXMustBeCompileTime % n.sons[0].sym.name.s)
of mCopyStr:
binaryExpr(p, n, r, "", "($1.slice($2))")
of mCopyStrLast:
ternaryExpr(p, n, r, "", "($1.slice($2, ($3)+1).concat(0))")
of mNewString: unaryExpr(p, n, r, "mnewString", "mnewString($1)")
of mNewStringOfCap:
unaryExpr(p, n, r, "mnewString", "mnewString(0)")
@@ -2076,8 +2071,11 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
r.kind = resExpr
of nkStrLit..nkTripleStrLit:
if skipTypes(n.typ, abstractVarRange).kind == tyString:
useMagic(p, "makeNimstrLit")
r.res = "makeNimstrLit($1)" % [makeJSString(n.strVal)]
if n.strVal.len != 0:
useMagic(p, "makeNimstrLit")
r.res = "makeNimstrLit($1)" % [makeJSString(n.strVal)]
else:
r.res = rope"[]"
else:
r.res = makeJSString(n.strVal, false)
r.kind = resExpr

View File

@@ -87,9 +87,9 @@ proc endsWithOpr*(x: string): bool =
result = x.endsWith(LineContinuationOprs)
proc continueLine(line: string, inTripleString: bool): bool {.inline.} =
result = inTripleString or
line[0] == ' ' or
line.endsWith(LineContinuationOprs+AdditionalLineContinuationOprs)
result = inTripleString or line.len > 0 and (
line[0] == ' ' or
line.endsWith(LineContinuationOprs+AdditionalLineContinuationOprs))
proc countTriples(s: string): int =
var i = 0

View File

@@ -538,7 +538,7 @@ proc parsePar(p: var TParser): PNode =
flexComment(p, result)
if p.tok.tokType in {tkDiscard, tkInclude, tkIf, tkWhile, tkCase,
tkTry, tkDefer, tkFinally, tkExcept, tkFor, tkBlock,
tkConst, tkLet, tkWhen, tkVar,
tkConst, tkLet, tkWhen, tkVar, tkFor,
tkMixin}:
# XXX 'bind' used to be an expression, so we exclude it here;
# tests/reject/tbind2 fails otherwise.
@@ -1113,7 +1113,7 @@ proc parseProcExpr(p: var TParser; isExpr: bool; kind: TNodeKind): PNode =
proc isExprStart(p: TParser): bool =
case p.tok.tokType
of tkSymbol, tkAccent, tkOpr, tkNot, tkNil, tkCast, tkIf,
of tkSymbol, tkAccent, tkOpr, tkNot, tkNil, tkCast, tkIf, tkFor,
tkProc, tkFunc, tkIterator, tkBind, tkBuiltInMagics,
tkParLe, tkBracketLe, tkCurlyLe, tkIntLit..tkCharLit, tkVar, tkRef, tkPtr,
tkTuple, tkObject, tkWhen, tkCase, tkOut:
@@ -1153,16 +1153,35 @@ proc parseTypeDescKAux(p: var TParser, kind: TNodeKind,
result.addSon list
parseSymbolList(p, list)
proc parseFor(p: var TParser): PNode =
#| forStmt = 'for' (identWithPragma ^+ comma) 'in' expr colcom stmt
#| forExpr = forStmt
result = newNodeP(nkForStmt, p)
getTokNoInd(p)
var a = identWithPragma(p)
addSon(result, a)
while p.tok.tokType == tkComma:
getTok(p)
optInd(p, a)
a = identWithPragma(p)
addSon(result, a)
eat(p, tkIn)
addSon(result, parseExpr(p))
colcom(p, result)
addSon(result, parseStmt(p))
proc parseExpr(p: var TParser): PNode =
#| expr = (blockExpr
#| | ifExpr
#| | whenExpr
#| | caseExpr
#| | forExpr
#| | tryExpr)
#| / simpleExpr
case p.tok.tokType:
of tkBlock: result = parseBlock(p)
of tkIf: result = parseIfExpr(p, nkIfExpr)
of tkFor: result = parseFor(p)
of tkWhen: result = parseIfExpr(p, nkWhenExpr)
of tkCase: result = parseCase(p)
of tkTry: result = parseTry(p, isExpr=true)
@@ -1569,22 +1588,6 @@ proc parseExceptBlock(p: var TParser, kind: TNodeKind): PNode =
colcom(p, result)
addSon(result, parseStmt(p))
proc parseFor(p: var TParser): PNode =
#| forStmt = 'for' (identWithPragma ^+ comma) 'in' expr colcom stmt
result = newNodeP(nkForStmt, p)
getTokNoInd(p)
var a = identWithPragma(p)
addSon(result, a)
while p.tok.tokType == tkComma:
getTok(p)
optInd(p, a)
a = identWithPragma(p)
addSon(result, a)
eat(p, tkIn)
addSon(result, parseExpr(p))
colcom(p, result)
addSon(result, parseStmt(p))
proc parseBlock(p: var TParser): PNode =
#| blockStmt = 'block' symbol? colcom stmt
#| blockExpr = 'block' symbol? colcom stmt

View File

@@ -37,7 +37,7 @@ proc changeType(c: PContext; n: PNode, newType: PType, check: bool)
proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode
proc semTypeNode(c: PContext, n: PNode, prev: PType): PType
proc semStmt(c: PContext, n: PNode): PNode
proc semStmt(c: PContext, n: PNode; flags: TExprFlags): PNode
proc semOpAux(c: PContext, n: PNode)
proc semParamList(c: PContext, n, genericParams: PNode, s: PSym)
proc addParams(c: PContext, n: PNode, kind: TSymKind)
@@ -399,7 +399,7 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
excl(result.flags, nfSem)
#resetSemFlag n
if s.typ.sons[0] == nil:
result = semStmt(c, result)
result = semStmt(c, result, flags)
else:
case s.typ.sons[0].kind
of tyExpr:
@@ -408,7 +408,7 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
# semExprWithType(c, result)
result = semExpr(c, result, flags)
of tyStmt:
result = semStmt(c, result)
result = semStmt(c, result, flags)
of tyTypeDesc:
if result.kind == nkStmtList: result.kind = nkStmtListType
var typ = semTypeNode(c, result, nil)
@@ -557,7 +557,7 @@ proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
result = semAllTypeSections(c, n)
else:
result = n
result = semStmt(c, result)
result = semStmt(c, result, {})
when false:
# Code generators are lazy now and can deal with undeclared procs, so these
# steps are not required anymore and actually harmful for the upcoming

View File

@@ -113,6 +113,7 @@ proc checkConvertible(c: PContext, castDest, src: PType): TConvStatus =
if castDest.kind notin IntegralTypes+{tyRange}:
result = convNotNeedeed
return
# Save for later
var d = skipTypes(castDest, abstractVar)
var s = src
if s.kind in tyUserTypeClasses and s.isResolvedUserTypeClass:
@@ -135,7 +136,7 @@ proc checkConvertible(c: PContext, castDest, src: PType): TConvStatus =
# we use d, s here to speed up that operation a bit:
case cmpTypes(c, d, s)
of isNone, isGeneric:
if not compareTypes(castDest, src, dcEqIgnoreDistinct):
if not compareTypes(castDest.skipTypes(abstractVar), src, dcEqIgnoreDistinct):
result = convNotLegal
else:
discard
@@ -917,7 +918,7 @@ proc semExprNoType(c: PContext, n: PNode): PNode =
let isPush = hintExtendedContext in c.config.notes
if isPush: pushInfoContext(c.config, n.info)
result = semExpr(c, n, {efWantStmt})
discardCheck(c, result)
discardCheck(c, result, {})
if isPush: popInfoContext(c.config)
proc isTypeExpr(n: PNode): bool =
@@ -1529,7 +1530,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
# unfortunately we need to rewrite ``(x, y) = foo()`` already here so
# that overloading of the assignment operator still works. Usually we
# prefer to do these rewritings in transf.nim:
return semStmt(c, lowerTupleUnpackingForAsgn(c.graph, n, c.p.owner))
return semStmt(c, lowerTupleUnpackingForAsgn(c.graph, n, c.p.owner), {})
else:
a = semExprWithType(c, a, {efLValue})
else:
@@ -1613,7 +1614,7 @@ proc semProcBody(c: PContext, n: PNode): PNode =
a.sons[1] = result
result = semAsgn(c, a)
else:
discardCheck(c, result)
discardCheck(c, result, {})
if c.p.owner.kind notin {skMacro, skTemplate} and
c.p.resultSym != nil and c.p.resultSym.typ.isMetaType:
@@ -1989,7 +1990,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
var x = n.lastSon
if x.kind == nkDo: x = x.sons[bodyPos]
inc c.inParallelStmt
result.sons[1] = semStmt(c, x)
result.sons[1] = semStmt(c, x, {})
dec c.inParallelStmt
of mSpawn:
result = setMs(n, s)
@@ -2240,7 +2241,7 @@ proc isTupleType(n: PNode): bool =
include semobjconstr
proc semBlock(c: PContext, n: PNode): PNode =
proc semBlock(c: PContext, n: PNode; flags: TExprFlags): PNode =
result = n
inc(c.p.nestedBlockCounter)
checkSonsLen(n, 2, c.config)
@@ -2252,7 +2253,7 @@ proc semBlock(c: PContext, n: PNode): PNode =
n.sons[0] = newSymNode(labl, n.sons[0].info)
suggestSym(c.config, n.sons[0].info, labl, c.graph.usageSym)
styleCheckDef(c.config, labl)
n.sons[1] = semExpr(c, n.sons[1])
n.sons[1] = semExpr(c, n.sons[1], flags)
n.typ = n.sons[1].typ
if isEmptyType(n.typ): n.kind = nkBlockStmt
else: n.kind = nkBlockExpr
@@ -2497,7 +2498,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
checkSonsLen(n, 1, c.config)
n.sons[0] = semExpr(c, n.sons[0], flags)
of nkCast: result = semCast(c, n)
of nkIfExpr, nkIfStmt: result = semIf(c, n)
of nkIfExpr, nkIfStmt: result = semIf(c, n, flags)
of nkHiddenStdConv, nkHiddenSubConv, nkConv, nkHiddenCallConv:
checkSonsLen(n, 2, c.config)
considerGenSyms(c, n)
@@ -2518,7 +2519,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
discard
of nkStaticExpr: result = semStaticExpr(c, n[0])
of nkAsgn: result = semAsgn(c, n)
of nkBlockStmt, nkBlockExpr: result = semBlock(c, n)
of nkBlockStmt, nkBlockExpr: result = semBlock(c, n, flags)
of nkStmtList, nkStmtListExpr: result = semStmtList(c, n, flags)
of nkRaiseStmt: result = semRaise(c, n)
of nkVarSection: result = semVarOrLet(c, n, skVar)
@@ -2526,11 +2527,11 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
of nkConstSection: result = semConst(c, n)
of nkTypeSection: result = semTypeSection(c, n)
of nkDiscardStmt: result = semDiscard(c, n)
of nkWhileStmt: result = semWhile(c, n)
of nkTryStmt: result = semTry(c, n)
of nkWhileStmt: result = semWhile(c, n, flags)
of nkTryStmt: result = semTry(c, n, flags)
of nkBreakStmt, nkContinueStmt: result = semBreakOrContinue(c, n)
of nkForStmt, nkParForStmt: result = semFor(c, n)
of nkCaseStmt: result = semCase(c, n)
of nkForStmt, nkParForStmt: result = semFor(c, n, flags)
of nkCaseStmt: result = semCase(c, n, flags)
of nkReturnStmt: result = semReturn(c, n)
of nkUsingStmt: result = semUsing(c, n)
of nkAsmStmt: result = semAsm(c, n)

View File

@@ -70,7 +70,7 @@ proc semForObjectFields(c: TFieldsCtx, typ, forLoop, father: PNode) =
openScope(c.c)
inc c.c.inUnrolledContext
let body = instFieldLoopBody(fc, lastSon(forLoop), forLoop)
father.add(semStmt(c.c, body))
father.add(semStmt(c.c, body, {}))
dec c.c.inUnrolledContext
closeScope(c.c)
of nkNilLit: discard
@@ -145,7 +145,7 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
fc.replaceByFieldName = m == mFieldPairs
var body = instFieldLoopBody(fc, loopBody, n)
inc c.inUnrolledContext
stmts.add(semStmt(c, body))
stmts.add(semStmt(c, body, {}))
dec c.inUnrolledContext
closeScope(c)
else:

View File

@@ -214,7 +214,24 @@ proc evalIs(n: PNode, lhs: PSym, g: ModuleGraph): PNode =
result = newIntNode(nkIntLit, ord(res))
result.typ = n.typ
proc fitLiteral(c: ConfigRef, n: PNode): PNode =
# Trim the literal value in order to make it fit in the destination type
if n == nil:
# `n` may be nil if the overflow check kicks in
return
doAssert n.kind in {nkIntLit, nkCharLit}
result = n
let typ = n.typ.skipTypes(abstractRange)
if typ.kind in tyUInt..tyUint32:
result.intVal = result.intVal and lastOrd(c, typ, fixedUnsigned=true)
proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
template doAndFit(op: untyped): untyped =
# Implements wrap-around behaviour for unsigned types
fitLiteral(g.config, op)
# b and c may be nil
result = nil
case m
@@ -224,12 +241,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
of mUnaryMinusF64: result = newFloatNodeT(- getFloat(a), n, g)
of mNot: result = newIntNodeT(1 - getInt(a), n, g)
of mCard: result = newIntNodeT(nimsets.cardSet(g.config, a), n, g)
of mBitnotI:
case skipTypes(n.typ, abstractRange).kind
of tyUInt..tyUInt64:
result = newIntNodeT((not getInt(a)) and lastOrd(g.config, a.typ, fixedUnsigned=true), n, g)
else:
result = newIntNodeT(not getInt(a), n, g)
of mBitnotI: result = doAndFit(newIntNodeT(not getInt(a), n, g))
of mLengthArray: result = newIntNodeT(lengthOrd(g.config, a.typ), n, g)
of mLengthSeq, mLengthOpenArray, mXLenSeq, mLengthStr, mXLenStr:
if a.kind == nkNilLit:
@@ -251,9 +263,9 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
of mToU8: result = newIntNodeT(getInt(a) and 0x000000FF, n, g)
of mToU16: result = newIntNodeT(getInt(a) and 0x0000FFFF, n, g)
of mToU32: result = newIntNodeT(getInt(a) and 0x00000000FFFFFFFF'i64, n, g)
of mUnaryLt: result = foldSub(getOrdValue(a), 1, n, g)
of mSucc: result = foldAdd(getOrdValue(a), getInt(b), n, g)
of mPred: result = foldSub(getOrdValue(a), getInt(b), n, g)
of mUnaryLt: result = doAndFit(foldSub(getOrdValue(a), 1, n, g))
of mSucc: result = doAndFit(foldAdd(getOrdValue(a), getInt(b), n, g))
of mPred: result = doAndFit(foldSub(getOrdValue(a), getInt(b), n, g))
of mAddI: result = foldAdd(getInt(a), getInt(b), n, g)
of mSubI: result = foldSub(getInt(a), getInt(b), n, g)
of mMulI: result = foldMul(getInt(a), getInt(b), n, g)
@@ -271,7 +283,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
of tyInt64, tyInt:
result = newIntNodeT(`shl`(getInt(a), getInt(b)), n, g)
of tyUInt..tyUInt64:
result = newIntNodeT(`shl`(getInt(a), getInt(b)) and lastOrd(g.config, a.typ, fixedUnsigned=true), n, g)
result = doAndFit(newIntNodeT(`shl`(getInt(a), getInt(b)), n, g))
else: internalError(g.config, n.info, "constant folding for shl")
of mShrI:
case skipTypes(n.typ, abstractRange).kind
@@ -324,14 +336,14 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
result = newIntNodeT(ord(`<%`(getOrdValue(a), getOrdValue(b))), n, g)
of mLeU, mLeU64:
result = newIntNodeT(ord(`<=%`(getOrdValue(a), getOrdValue(b))), n, g)
of mBitandI, mAnd: result = newIntNodeT(a.getInt and b.getInt, n, g)
of mBitorI, mOr: result = newIntNodeT(getInt(a) or getInt(b), n, g)
of mBitxorI, mXor: result = newIntNodeT(a.getInt xor b.getInt, n, g)
of mAddU: result = newIntNodeT(`+%`(getInt(a), getInt(b)), n, g)
of mSubU: result = newIntNodeT(`-%`(getInt(a), getInt(b)), n, g)
of mMulU: result = newIntNodeT(`*%`(getInt(a), getInt(b)), n, g)
of mModU: result = foldModU(getInt(a), getInt(b), n, g)
of mDivU: result = foldDivU(getInt(a), getInt(b), n, g)
of mBitandI, mAnd: result = doAndFit(newIntNodeT(a.getInt and b.getInt, n, g))
of mBitorI, mOr: result = doAndFit(newIntNodeT(getInt(a) or getInt(b), n, g))
of mBitxorI, mXor: result = doAndFit(newIntNodeT(a.getInt xor b.getInt, n, g))
of mAddU: result = doAndFit(newIntNodeT(`+%`(getInt(a), getInt(b)), n, g))
of mSubU: result = doAndFit(newIntNodeT(`-%`(getInt(a), getInt(b)), n, g))
of mMulU: result = doAndFit(newIntNodeT(`*%`(getInt(a), getInt(b)), n, g))
of mModU: result = doAndFit(foldModU(getInt(a), getInt(b), n, g))
of mDivU: result = doAndFit(foldDivU(getInt(a), getInt(b), n, g))
of mLeSet: result = newIntNodeT(ord(containsSets(g.config, a, b)), n, g)
of mEqSet: result = newIntNodeT(ord(equalSets(g.config, a, b)), n, g)
of mLtSet:
@@ -462,17 +474,24 @@ proc foldConv(n, a: PNode; g: ModuleGraph; check = false): PNode =
result = newIntNodeT(int(getFloat(a)), n, g)
of tyChar:
result = newIntNodeT(getOrdValue(a), n, g)
of tyUInt8..tyUInt32, tyInt8..tyInt32:
let fromSigned = srcTyp.kind in tyInt..tyInt64
of tyUInt..tyUInt64, tyInt..tyInt64:
let toSigned = dstTyp.kind in tyInt..tyInt64
var val = a.getOrdValue
let mask = lastOrd(g.config, dstTyp, fixedUnsigned=true)
var val =
if toSigned:
a.getOrdValue mod mask
else:
a.getOrdValue and mask
if dstTyp.kind in {tyInt, tyInt64, tyUint, tyUInt64}:
# No narrowing needed
discard
elif dstTyp.kind in {tyInt..tyInt64}:
# Signed type: Overflow check (if requested) and conversion
if check: rangeCheck(n, val, g)
let mask = (`shl`(1, getSize(g.config, dstTyp) * 8) - 1)
let valSign = val < 0
val = abs(val) and mask
if valSign: val = -val
else:
# Unsigned type: Conversion
let mask = (`shl`(1, getSize(g.config, dstTyp) * 8) - 1)
val = val and mask
result = newIntNodeT(val, n, g)
else:

View File

@@ -76,17 +76,19 @@ proc semAsm(c: PContext, n: PNode): PNode =
if marker == '\0': marker = '`' # default marker
result = semAsmOrEmit(c, n, marker)
proc semWhile(c: PContext, n: PNode): PNode =
proc semWhile(c: PContext, n: PNode; flags: TExprFlags): PNode =
result = n
checkSonsLen(n, 2, c.config)
openScope(c)
n.sons[0] = forceBool(c, semExprWithType(c, n.sons[0]))
inc(c.p.nestedLoopCounter)
n.sons[1] = semStmt(c, n.sons[1])
n.sons[1] = semStmt(c, n.sons[1], flags)
dec(c.p.nestedLoopCounter)
closeScope(c)
if n.sons[1].typ == c.enforceVoidContext:
result.typ = c.enforceVoidContext
elif efInTypeof in flags:
result.typ = n[1].typ
proc toCover(c: PContext, t: PType): BiggestInt =
let t2 = skipTypes(t, abstractVarRange-{tyTypeDesc})
@@ -97,8 +99,8 @@ proc toCover(c: PContext, t: PType): BiggestInt =
proc semProc(c: PContext, n: PNode): PNode
proc semExprBranch(c: PContext, n: PNode): PNode =
result = semExpr(c, n)
proc semExprBranch(c: PContext, n: PNode; flags: TExprFlags = {}): PNode =
result = semExpr(c, n, flags)
if result.typ != nil:
# XXX tyGenericInst here?
if result.typ.kind in {tyVar, tyLent}: result = newDeref(result)
@@ -130,8 +132,9 @@ proc fixNilType(c: PContext; n: PNode) =
for it in n: fixNilType(c, it)
n.typ = nil
proc discardCheck(c: PContext, result: PNode) =
if c.matchedConcept != nil: return
proc discardCheck(c: PContext, result: PNode, flags: TExprFlags) =
if c.matchedConcept != nil or efInTypeof in flags: return
if result.typ != nil and result.typ.kind notin {tyStmt, tyVoid}:
if implicitlyDiscardable(result):
var n = newNodeI(nkDiscardStmt, result.info, 1)
@@ -148,7 +151,7 @@ proc discardCheck(c: PContext, result: PNode) =
s.add "; for a function call use ()"
localError(c.config, n.info, s)
proc semIf(c: PContext, n: PNode): PNode =
proc semIf(c: PContext, n: PNode; flags: TExprFlags): PNode =
result = n
var typ = commonTypeBegin
var hasElse = false
@@ -165,8 +168,9 @@ proc semIf(c: PContext, n: PNode): PNode =
it.sons[0] = semExprBranchScope(c, it.sons[0])
typ = commonType(typ, it.sons[0])
else: illFormedAst(it, c.config)
if isEmptyType(typ) or typ.kind in {tyNil, tyExpr} or not hasElse:
for it in n: discardCheck(c, it.lastSon)
if isEmptyType(typ) or typ.kind in {tyNil, tyExpr} or
(not hasElse and efInTypeof notin flags):
for it in n: discardCheck(c, it.lastSon, flags)
result.kind = nkIfStmt
# propagate any enforced VoidContext:
if typ == c.enforceVoidContext: result.typ = c.enforceVoidContext
@@ -178,8 +182,7 @@ proc semIf(c: PContext, n: PNode): PNode =
result.kind = nkIfExpr
result.typ = typ
proc semTry(c: PContext, n: PNode): PNode =
proc semTry(c: PContext, n: PNode; flags: TExprFlags): PNode =
var check = initIntSet()
template semExceptBranchType(typeNode: PNode): bool =
# returns true if exception type is imported type
@@ -246,12 +249,12 @@ proc semTry(c: PContext, n: PNode): PNode =
dec c.p.inTryStmt
if isEmptyType(typ) or typ.kind in {tyNil, tyExpr}:
discardCheck(c, n.sons[0])
for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon)
discardCheck(c, n.sons[0], flags)
for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon, flags)
if typ == c.enforceVoidContext:
result.typ = c.enforceVoidContext
else:
if n.lastSon.kind == nkFinally: discardCheck(c, n.lastSon.lastSon)
if n.lastSon.kind == nkFinally: discardCheck(c, n.lastSon.lastSon, flags)
n.sons[0] = fitNode(c, typ, n.sons[0], n.sons[0].info)
for i in 1..last:
var it = n.sons[i]
@@ -570,7 +573,7 @@ proc symForVar(c: PContext, n: PNode): PSym =
if n.kind == nkPragmaExpr:
pragma(c, result, n.sons[1], forVarPragmas)
proc semForVars(c: PContext, n: PNode): PNode =
proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
result = n
var length = sonsLen(n)
let iterBase = n.sons[length-2].typ
@@ -601,7 +604,7 @@ proc semForVars(c: PContext, n: PNode): PNode =
addForVarDecl(c, v)
inc(c.p.nestedLoopCounter)
openScope(c)
n.sons[length-1] = semStmt(c, n.sons[length-1])
n.sons[length-1] = semExprBranch(c, n.sons[length-1], flags)
closeScope(c)
dec(c.p.nestedLoopCounter)
@@ -685,7 +688,7 @@ proc handleCaseStmtMacro(c: PContext; n: PNode): PNode =
when false:
result = handleStmtMacro(c, n, n[0], "CaseStmt")
proc semFor(c: PContext, n: PNode): PNode =
proc semFor(c: PContext, n: PNode; flags: TExprFlags): PNode =
checkMinSonsLen(n, 3, c.config)
var length = sonsLen(n)
if forLoopMacros in c.features:
@@ -702,14 +705,14 @@ proc semFor(c: PContext, n: PNode): PNode =
if isCallExpr and call[0].kind == nkSym and
call[0].sym.magic in {mFields, mFieldPairs, mOmpParFor}:
if call.sons[0].sym.magic == mOmpParFor:
result = semForVars(c, n)
result = semForVars(c, n, flags)
result.kind = nkParForStmt
else:
result = semForFields(c, n, call.sons[0].sym.magic)
elif isCallExpr and call.sons[0].typ.callConv == ccClosure and
tfIterator in call.sons[0].typ.flags:
# first class iterator:
result = semForVars(c, n)
result = semForVars(c, n, flags)
elif not isCallExpr or call.sons[0].kind != nkSym or
call.sons[0].sym.kind != skIterator:
if length == 3:
@@ -718,15 +721,17 @@ proc semFor(c: PContext, n: PNode): PNode =
n.sons[length-2] = implicitIterator(c, "pairs", n.sons[length-2])
else:
localError(c.config, n.sons[length-2].info, "iterator within for loop context expected")
result = semForVars(c, n)
result = semForVars(c, n, flags)
else:
result = semForVars(c, n)
result = semForVars(c, n, flags)
# propagate any enforced VoidContext:
if n.sons[length-1].typ == c.enforceVoidContext:
result.typ = c.enforceVoidContext
elif efInTypeof in flags:
result.typ = result.lastSon.typ
closeScope(c)
proc semCase(c: PContext, n: PNode): PNode =
proc semCase(c: PContext, n: PNode; flags: TExprFlags): PNode =
result = n
checkMinSonsLen(n, 2, c.config)
openScope(c)
@@ -782,8 +787,9 @@ proc semCase(c: PContext, n: PNode): PNode =
else:
localError(c.config, n.info, "not all cases are covered")
closeScope(c)
if isEmptyType(typ) or typ.kind in {tyNil, tyExpr} or not hasElse:
for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon)
if isEmptyType(typ) or typ.kind in {tyNil, tyExpr} or
(not hasElse and efInTypeof notin flags):
for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon, flags)
# propagate any enforced VoidContext:
if typ == c.enforceVoidContext:
result.typ = c.enforceVoidContext
@@ -1173,6 +1179,9 @@ proc semBorrow(c: PContext, n: PNode, s: PSym) =
if b != nil:
# store the alias:
n.sons[bodyPos] = newSymNode(b)
# Carry over the original symbol magic, this is necessary in order to ensure
# the semantic pass is correct
s.magic = b.magic
else:
localError(c.config, n.info, errNoSymbolToBorrowFromFound)
@@ -1792,7 +1801,7 @@ proc evalInclude(c: PContext, n: PNode): PNode =
if containsOrIncl(c.includedFiles, f.int):
localError(c.config, n.info, errRecursiveDependencyX % toFilename(c.config, f))
else:
addSon(result, semStmt(c, c.graph.includeFileCallback(c.graph, c.module, f)))
addSon(result, semStmt(c, c.graph.includeFileCallback(c.graph, c.module, f), {}))
excl(c.includedFiles, f.int)
proc setLine(n: PNode, info: TLineInfo) =
@@ -1819,7 +1828,7 @@ proc semStaticStmt(c: PContext, n: PNode): PNode =
#writeStackTrace()
inc c.inStaticContext
openScope(c)
let a = semStmt(c, n.sons[0])
let a = semStmt(c, n.sons[0], {})
closeScope(c)
dec c.inStaticContext
n.sons[0] = a
@@ -1895,11 +1904,11 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
if n.sons[i].typ == c.enforceVoidContext: #or usesResult(n.sons[i]):
voidContext = true
n.typ = c.enforceVoidContext
if i == last and (length == 1 or efWantValue in flags):
if i == last and (length == 1 or ({efWantValue, efInTypeof} * flags != {})):
n.typ = n.sons[i].typ
if not isEmptyType(n.typ): n.kind = nkStmtListExpr
elif i != last or voidContext:
discardCheck(c, n.sons[i])
discardCheck(c, n.sons[i], flags)
else:
n.typ = n.sons[i].typ
if not isEmptyType(n.typ): n.kind = nkStmtListExpr
@@ -1928,6 +1937,8 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
# it is an old-style comment statement: we replace it with 'discard ""':
prettybase.replaceComment(result.info)
proc semStmt(c: PContext, n: PNode): PNode =
# now: simply an alias:
result = semExprNoType(c, n)
proc semStmt(c: PContext, n: PNode; flags: TExprFlags): PNode =
if efInTypeof notin flags:
result = semExprNoType(c, n)
else:
result = semExpr(c, n, flags)

View File

@@ -1161,7 +1161,7 @@ proc semStmtListType(c: PContext, n: PNode, prev: PType): PType =
checkMinSonsLen(n, 1, c.config)
var length = sonsLen(n)
for i in countup(0, length - 2):
n.sons[i] = semStmt(c, n.sons[i])
n.sons[i] = semStmt(c, n.sons[i], {})
if length > 0:
result = semTypeNode(c, n.sons[length - 1], prev)
n.typ = result
@@ -1406,6 +1406,13 @@ proc semStaticType(c: PContext, childNode: PNode, prev: PType): PType =
result.rawAddSon(base)
result.flags.incl tfHasStatic
proc semTypeof(c: PContext; n: PNode; prev: PType): PType =
openScope(c)
let t = semExprWithType(c, n, {efInTypeof})
closeScope(c)
fixupTypeOf(c, prev, t)
result = t.typ
proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
result = nil
inc c.inTypeContext
@@ -1416,9 +1423,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
of nkTypeOfExpr:
# for ``type(countup(1,3))``, see ``tests/ttoseq``.
checkSonsLen(n, 1, c.config)
let typExpr = semExprWithType(c, n.sons[0], {efInTypeof})
fixupTypeOf(c, prev, typExpr)
result = typExpr.typ
result = semTypeof(c, n.sons[0], prev)
if result.kind == tyTypeDesc: result.flags.incl tfExplicit
of nkPar:
if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev)
@@ -1487,9 +1492,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
result = semAnyRef(c, n, tyRef, prev)
elif op.id == ord(wType):
checkSonsLen(n, 2, c.config)
let typExpr = semExprWithType(c, n.sons[1], {efInTypeof})
fixupTypeOf(c, prev, typExpr)
result = typExpr.typ
result = semTypeof(c, n[1], prev)
else:
if c.inGenericContext > 0 and n.kind == nkCall:
result = makeTypeFromExpr(c, n.copyTree)

View File

@@ -624,7 +624,11 @@ proc transformCase(c: PTransf, n: PNode): PTransNode =
case it.kind
of nkElifBranch:
if ifs.PNode == nil:
ifs = newTransNode(nkIfStmt, it.info, 0)
# Generate the right node depending on whether `n` is used as a stmt or
# as an expr
let kind = if n.typ != nil: nkIfExpr else: nkIfStmt
ifs = newTransNode(kind, it.info, 0)
ifs.PNode.typ = n.typ
ifs.add(e)
of nkElse:
if ifs.PNode == nil: result.add(e)

View File

@@ -240,7 +240,7 @@ else: # bootstrapping substitute
when defined(nimHasSymOwnerInMacro):
proc owner*(sym: NimNode): NimNode {.magic: "SymOwner", noSideEffect.}
## accepts node of kind nnkSym and returns its owner's symbol.
## result is also mnde of kind nnkSym if owner exists otherwise
## result is also mnde of kind nnkSym if owner exists otherwise
## nnkNilLit is returned
proc getType*(n: NimNode): NimNode {.magic: "NGetType", noSideEffect.}
@@ -977,7 +977,7 @@ proc newIfStmt*(branches: varargs[tuple[cond, body: NimNode]]):
##
result = newNimNode(nnkIfStmt)
for i in branches:
result.add(newNimNode(nnkElifBranch).add(i.cond, i.body))
result.add(newTree(nnkElifBranch, i.cond, i.body))
proc newEnum*(name: NimNode, fields: openArray[NimNode],
public, pure: bool): NimNode {.compileTime.} =

View File

@@ -1552,7 +1552,7 @@ proc delete*[T](x: var seq[T], i: Natural) {.noSideEffect.} =
defaultImpl()
else:
when defined(js):
{.emit: "`x`[`x`_Idx].splice(`i`, 1);".}
{.emit: "`x`.splice(`i`, 1);".}
else:
defaultImpl()
@@ -1574,7 +1574,7 @@ proc insert*[T](x: var seq[T], item: T, i = 0.Natural) {.noSideEffect.} =
else:
when defined(js):
var it : T
{.emit: "`x`[`x`_Idx].splice(`i`, 0, `it`);".}
{.emit: "`x`.splice(`i`, 0, `it`);".}
else:
defaultImpl()
x[i] = item
@@ -2741,12 +2741,12 @@ type
when defined(JS):
proc add*(x: var string, y: cstring) {.asmNoStackFrame.} =
asm """
var len = `x`.length-1;
if (`x` === null) { `x` = []; }
var off = `x`.length;
`x`.length += `y`.length;
for (var i = 0; i < `y`.length; ++i) {
`x`[len] = `y`.charCodeAt(i);
++len;
`x`[off+i] = `y`.charCodeAt(i);
}
`x`[len] = 0
"""
proc add*(x: var cstring, y: cstring) {.magic: "AppendStrStr".}
@@ -3784,8 +3784,11 @@ template assertImpl(cond: bool, msg = "", enabled: static[bool]) =
bind instantiationInfo
mixin failedAssertImpl
when enabled:
if not cond:
failedAssertImpl(loc & " `" & astToStr(cond) & "` " & msg)
# for stacktrace; fixes #8928 ; Note: `fullPaths = true` is correct
# here, regardless of --excessiveStackTrace
{.line: instantiationInfo(fullPaths = true).}:
if not cond:
failedAssertImpl(loc & " `" & astToStr(cond) & "` " & msg)
template assert*(cond: bool, msg = "") =
## Raises ``AssertionError`` with `msg` if `cond` is false. Note

View File

@@ -11,7 +11,7 @@ when declared(ThisIsSystem):
# we are in system module:
{.pragma: codegenType, compilerproc.}
else:
{.pragma: codegenType, importc.}
{.pragma: codegenType.}
type
# This should be the same as ast.TTypeKind

View File

@@ -182,12 +182,10 @@ proc setConstr() {.varargs, asmNoStackFrame, compilerproc.} =
proc makeNimstrLit(c: cstring): string {.asmNoStackFrame, compilerproc.} =
{.emit: """
var ln = `c`.length;
var result = new Array(ln + 1);
var i = 0;
for (; i < ln; ++i) {
var result = new Array(ln);
for (var i = 0; i < ln; ++i) {
result[i] = `c`.charCodeAt(i);
}
result[i] = 0; // terminating zero
return result;
""".}
@@ -225,13 +223,12 @@ proc cstrToNimstr(c: cstring): string {.asmNoStackFrame, compilerproc.} =
}
++r;
}
result[r] = 0; // terminating zero
return result;
""".}
proc toJSStr(s: string): cstring {.asmNoStackFrame, compilerproc.} =
asm """
var len = `s`.length-1;
var len = `s`.length;
var asciiPart = new Array(len);
var fcc = String.fromCharCode;
var nonAsciiPart = null;
@@ -262,10 +259,7 @@ proc toJSStr(s: string): cstring {.asmNoStackFrame, compilerproc.} =
proc mnewString(len: int): string {.asmNoStackFrame, compilerproc.} =
asm """
var result = new Array(`len`+1);
result[0] = 0;
result[`len`] = 0;
return result;
return new Array(`len`);
"""
proc SetCard(a: int): int {.compilerproc, asmNoStackFrame.} =
@@ -323,7 +317,7 @@ proc cmpStrings(a, b: string): int {.asmNoStackFrame, compilerProc.} =
if (`a` == `b`) return 0;
if (!`a`) return -1;
if (!`b`) return 1;
for (var i = 0; i < `a`.length - 1 && i < `b`.length - 1; i++) {
for (var i = 0; i < `a`.length && i < `b`.length; i++) {
var result = `a`[i] - `b`[i];
if (result != 0) return result;
}
@@ -651,9 +645,7 @@ proc isObj(obj, subclass: PNimType): bool {.compilerproc.} =
return true
proc addChar(x: string, c: char) {.compilerproc, asmNoStackFrame.} =
asm """
`x`[`x`.length-1] = `c`; `x`.push(0);
"""
asm "`x`.push(`c`);"
{.pop.}

View File

@@ -4,6 +4,9 @@ B0
B1
B2
B3
B4
B5
B6
'''
"""
@@ -14,6 +17,14 @@ template crossCheck(ty: untyped, exp: untyped) =
echo "Got ", ct
echo "Expected ", rt
template add1(x: uint8): untyped = x + 1
template add1(x: uint16): untyped = x + 1
template add1(x: uint32): untyped = x + 1
template sub1(x: uint8): untyped = x - 1
template sub1(x: uint16): untyped = x - 1
template sub1(x: uint32): untyped = x - 1
block:
when true:
echo "B0"
@@ -34,10 +45,34 @@ block:
crossCheck(uint64, (-1).uint64 + 5'u64)
echo "B3"
crossCheck(int8, 0'u8 - 5'u8)
crossCheck(int16, 0'u16 - 5'u16)
crossCheck(int32, 0'u32 - 5'u32)
crossCheck(int64, 0'u64 - 5'u64)
doAssert $sub1(0'u8) == "255"
doAssert $sub1(0'u16) == "65535"
doAssert $sub1(0'u32) == "4294967295"
echo "B4"
doAssert $add1(255'u8) == "0"
doAssert $add1(65535'u16) == "0"
doAssert $add1(4294967295'u32) == "0"
echo "B5"
crossCheck(int32, high(int32))
crossCheck(int32, high(int32).int32)
crossCheck(int32, low(int32))
crossCheck(int32, low(int32).int32)
crossCheck(int64, high(int8).int16.int32.int64)
crossCheck(int64, low(int8).int16.int32.int64)
echo "B6"
crossCheck(int64, 0xFFFFFFFFFFFFFFFF'u64)
crossCheck(int32, 0xFFFFFFFFFFFFFFFF'u64)
crossCheck(int16, 0xFFFFFFFFFFFFFFFF'u64)
crossCheck(int8 , 0xFFFFFFFFFFFFFFFF'u64)
# Out of range conversion, caught for `let`s only
# crossCheck(int8, 0'u8 - 5'u8)
# crossCheck(int16, 0'u16 - 5'u16)
# crossCheck(int32, 0'u32 - 5'u32)
# crossCheck(int64, 0'u64 - 5'u64)
# crossCheck(int8, 0'u16 - 129'u16)
# crossCheck(uint8, 0'i16 + 257'i16)

View File

@@ -0,0 +1,19 @@
discard """
output: '''
tfailedassert_stacktrace.nim(16) tfailedassert_stacktrace
tfailedassert_stacktrace.nim(15) foo
system.nim(3778) failedAssertImpl
system.nim(3771) raiseAssert
system.nim(2818) sysFatal
'''
"""
try:
proc foo() =
assert(false)
foo()
except AssertionError:
let e = getCurrentException()
echo e.getStackTrace

View File

@@ -0,0 +1,8 @@
type
Bytes = distinct seq[byte]
proc add(x: var Bytes; b: byte) {.borrow.}
var x = @[].Bytes
x.add(42)
let base = cast[seq[byte]](x)
doAssert base.len == 1 and base[0] == 42

View File

@@ -0,0 +1,8 @@
discard """
targets: "c cpp"
"""
import typeinfo
var x = ""
discard (getPointer(toAny(x)))

7
tests/js/t7534.nim Normal file
View File

@@ -0,0 +1,7 @@
proc f(x: int): int =
result = case x
of 1: 2
elif x == 2: 3
else: 1
doAssert 2 == f(f(f(f(1))))

12
tests/js/t8914.nim Normal file
View File

@@ -0,0 +1,12 @@
discard """
output: '''
@[42]
@[24, 42]
'''
"""
var x = @[42,4242]
x.delete(1)
echo x
x.insert(24)
echo x

4
tests/js/taddnilstr.nim Normal file
View File

@@ -0,0 +1,4 @@
var x = "foo".cstring
var y: string
add(y, x)
doAssert y == "foo"

5
tests/js/tstrconcat.nim Normal file
View File

@@ -0,0 +1,5 @@
var x: string
var y = "foo"
add(x, y)
y[0] = 'm'
doAssert y == "moo" and x == "foo"

63
tests/macros/tcollect.nim Normal file
View File

@@ -0,0 +1,63 @@
discard """
output: '''@[2, 3, 4, 2, 3, 4, 2, 3, 4, 2, 3, 4, 2, 3, 4]
@[0, 1, 2, 3]'''
"""
const data = [1,2,3,4,5,6]
import macros
macro collect(body): untyped =
# analyse the body, find the deepest expression 'it' and replace it via
# 'result.add it'
let res = genSym(nskVar, "collectResult")
when false:
proc detectForLoopVar(n: NimNode): NimNode =
if n.kind == nnkForStmt:
result = n[0]
else:
for x in n:
result = detectForLoopVar(x)
if result != nil: return result
return nil
proc t(n, res: NimNode): NimNode =
case n.kind
of nnkStmtList, nnkStmtListExpr, nnkBlockStmt, nnkBlockExpr,
nnkWhileStmt,
nnkForStmt, nnkIfExpr, nnkIfStmt, nnkTryStmt, nnkCaseStmt,
nnkElifBranch, nnkElse, nnkElifExpr:
result = copyNimTree(n)
if n.len >= 1:
result[^1] = t(n[^1], res)
else:
if true: #n == it:
template adder(res, it) =
res.add it
result = getAst adder(res, n)
else:
result = n
when false:
let it = detectForLoopVar(body)
if it == nil: error("no for loop in body", body)
let v = newTree(nnkVarSection,
newTree(nnkIdentDefs, res, newTree(nnkBracketExpr, bindSym"seq",
newCall(bindSym"type", body)), newEmptyNode()))
result = newTree(nnkStmtListExpr, v, t(body, res), res)
#echo repr result
let stuff = collect:
var i = -1
while i < 4:
inc i
for it in data:
if it < 5 and it > 1:
it
echo stuff
echo collect(for i in 0..3: i)

10
tests/seq/t7346.nim Normal file
View File

@@ -0,0 +1,10 @@
when not defined(nimNewRuntime):
{.error: "This bug could only be reproduced with --newruntime".}
type
Obj = object
a: int
proc `=`(a: var Obj, b: Obj) = discard
let a: seq[Obj] = @[]

7
tests/typerel/t8905.nim Normal file
View File

@@ -0,0 +1,7 @@
type
Foo[T] = distinct seq[T]
Bar[T] = object
proc newFoo[T](): Foo[T] = Foo[T](newSeq[T]())
var x = newFoo[Bar[int]]()

10
tests/types/t6969.nim Normal file
View File

@@ -0,0 +1,10 @@
discard """
errormsg: "invalid type: 'object' for var"
line: 6
"""
var a: object a: int
# or
var b: ref object a: int
# or
var c: ptr object a: int

1
tests/types/t7581.nim Normal file
View File

@@ -0,0 +1 @@
discard int -1