mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-17 16:38:33 +00:00
Merge branch 'devel' into araq-better-docgen
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.} =
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
19
tests/assert/tfailedassert_stacktrace.nim
Normal file
19
tests/assert/tfailedassert_stacktrace.nim
Normal 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
|
||||
8
tests/ccgbugs/tborrowmagic.nim
Normal file
8
tests/ccgbugs/tborrowmagic.nim
Normal 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
|
||||
8
tests/ccgbugs/thtiobj.nim
Normal file
8
tests/ccgbugs/thtiobj.nim
Normal file
@@ -0,0 +1,8 @@
|
||||
discard """
|
||||
targets: "c cpp"
|
||||
"""
|
||||
|
||||
import typeinfo
|
||||
|
||||
var x = ""
|
||||
discard (getPointer(toAny(x)))
|
||||
7
tests/js/t7534.nim
Normal file
7
tests/js/t7534.nim
Normal 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
12
tests/js/t8914.nim
Normal 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
4
tests/js/taddnilstr.nim
Normal 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
5
tests/js/tstrconcat.nim
Normal 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
63
tests/macros/tcollect.nim
Normal 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
10
tests/seq/t7346.nim
Normal 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
7
tests/typerel/t8905.nim
Normal 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
10
tests/types/t6969.nim
Normal 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
1
tests/types/t7581.nim
Normal file
@@ -0,0 +1 @@
|
||||
discard int -1
|
||||
Reference in New Issue
Block a user