Merge branch 'devel' of github.com:nim-lang/Nim into devel
This commit is contained in:
commit
af94946517
32 changed files with 488 additions and 150 deletions
|
|
@ -678,7 +678,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
|
|||
n[0] = ex
|
||||
result.add(n)
|
||||
|
||||
of nkCast, nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
||||
of nkCast, nkHiddenStdConv, nkHiddenSubConv, nkConv, nkObjDownConv:
|
||||
var ns = false
|
||||
for i in 0 ..< n.len:
|
||||
n[i] = ctx.lowerStmtListExprs(n[i], ns)
|
||||
|
|
@ -687,9 +687,9 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
|
|||
needsSplit = true
|
||||
result = newNodeI(nkStmtListExpr, n.info)
|
||||
result.typ = n.typ
|
||||
let (st, ex) = exprToStmtList(n[1])
|
||||
let (st, ex) = exprToStmtList(n[^1])
|
||||
result.add(st)
|
||||
n[1] = ex
|
||||
n[^1] = ex
|
||||
result.add(n)
|
||||
|
||||
of nkAsgn, nkFastAsgn:
|
||||
|
|
@ -712,6 +712,25 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
|
|||
|
||||
result.add(n)
|
||||
|
||||
of nkBracketExpr:
|
||||
var lhsNeedsSplit = false
|
||||
var rhsNeedsSplit = false
|
||||
n[0] = ctx.lowerStmtListExprs(n[0], lhsNeedsSplit)
|
||||
n[1] = ctx.lowerStmtListExprs(n[1], rhsNeedsSplit)
|
||||
if lhsNeedsSplit or rhsNeedsSplit:
|
||||
needsSplit = true
|
||||
result = newNodeI(nkStmtListExpr, n.info)
|
||||
if lhsNeedsSplit:
|
||||
let (st, ex) = exprToStmtList(n[0])
|
||||
result.add(st)
|
||||
n[0] = ex
|
||||
|
||||
if rhsNeedsSplit:
|
||||
let (st, ex) = exprToStmtList(n[1])
|
||||
result.add(st)
|
||||
n[1] = ex
|
||||
result.add(n)
|
||||
|
||||
of nkWhileStmt:
|
||||
var ns = false
|
||||
|
||||
|
|
|
|||
|
|
@ -658,15 +658,16 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) =
|
|||
line(p, "}\L")
|
||||
|
||||
proc genRaiseStmt(p: PProc, n: PNode) =
|
||||
genLineDir(p, n)
|
||||
if n.sons[0].kind != nkEmpty:
|
||||
var a: TCompRes
|
||||
gen(p, n.sons[0], a)
|
||||
let typ = skipTypes(n.sons[0].typ, abstractPtrs)
|
||||
genLineDir(p, n)
|
||||
useMagic(p, "raiseException")
|
||||
lineF(p, "raiseException($1, $2);$n",
|
||||
[a.rdLoc, makeJSString(typ.sym.name.s)])
|
||||
else:
|
||||
genLineDir(p, n)
|
||||
useMagic(p, "reraiseException")
|
||||
line(p, "reraiseException();\L")
|
||||
|
||||
|
|
@ -764,11 +765,22 @@ proc genAsmOrEmitStmt(p: PProc, n: PNode) =
|
|||
of nkSym:
|
||||
let v = it.sym
|
||||
# for backwards compatibility we don't deref syms here :-(
|
||||
if v.kind in {skVar, skLet, skTemp, skConst, skResult, skParam, skForVar}:
|
||||
p.body.add mangleName(p.module, v)
|
||||
if false:
|
||||
discard
|
||||
else:
|
||||
var r: TCompRes
|
||||
gen(p, it, r)
|
||||
|
||||
if it.typ.kind == tyPointer:
|
||||
# A fat pointer is disguised as an array
|
||||
r.res = r.address
|
||||
r.address = nil
|
||||
elif r.typ == etyBaseIndex:
|
||||
# Deference first
|
||||
r.res = "$1[$2]" % [r.address, r.res]
|
||||
r.address = nil
|
||||
r.typ = etyNone
|
||||
|
||||
p.body.add(r.rdLoc)
|
||||
else:
|
||||
var r: TCompRes
|
||||
|
|
@ -845,6 +857,7 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) =
|
|||
else:
|
||||
gen(p, x, a)
|
||||
|
||||
genLineDir(p, y)
|
||||
gen(p, y, b)
|
||||
|
||||
# we don't care if it's an etyBaseIndex (global) of a string, it's
|
||||
|
|
@ -881,11 +894,9 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) =
|
|||
lineF(p, "$1 = $2;$n", [a.res, b.res])
|
||||
|
||||
proc genAsgn(p: PProc, n: PNode) =
|
||||
genLineDir(p, n)
|
||||
genAsgnAux(p, n.sons[0], n.sons[1], noCopyNeeded=false)
|
||||
|
||||
proc genFastAsgn(p: PProc, n: PNode) =
|
||||
genLineDir(p, n)
|
||||
# 'shallowCopy' always produced 'noCopyNeeded = true' here but this is wrong
|
||||
# for code like
|
||||
# while j >= pos:
|
||||
|
|
@ -1529,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])
|
||||
|
||||
|
|
@ -1647,13 +1658,13 @@ 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:
|
||||
if skipTypes(n.sons[1].typ, abstractVarRange).kind == tyCString:
|
||||
binaryExpr(p, n, r, "", "if ($1 != null) { $1 += $2; } else { $1 = $2; }")
|
||||
else:
|
||||
binaryExpr(p, n, r, "",
|
||||
"if ($1 != null) { $1 = ($1.slice(0, -1)).concat($2); } else { $1 = $2;}")
|
||||
"if ($1 != null) { $1 = ($1).concat($2); } else { $1 = $2;}")
|
||||
# XXX: make a copy of $2, because of Javascript's sucking semantics
|
||||
of mAppendSeqElem:
|
||||
var x, y: TCompRes
|
||||
|
|
@ -1683,20 +1694,15 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
|
|||
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")
|
||||
unaryExpr(p, n, r, "", "($1 != null ? $1.length : 0)")
|
||||
of mXLenStr:
|
||||
unaryExpr(p, n, r, "", "$1.length")
|
||||
of mLengthSeq, mLengthOpenArray, mLengthArray:
|
||||
unaryExpr(p, n, r, "", "($1 != null ? $1.length : 0)")
|
||||
of 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)
|
||||
|
|
@ -1710,7 +1716,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)
|
||||
|
|
@ -1739,8 +1745,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)")
|
||||
|
|
@ -2065,8 +2069,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
|
||||
|
|
|
|||
|
|
@ -884,6 +884,42 @@ proc getOperator(L: var TLexer, tok: var TToken) =
|
|||
if buf[pos] in {CR, LF, nimlexbase.EndOfFile}:
|
||||
tok.strongSpaceB = -1
|
||||
|
||||
proc getPrecedence*(tok: TToken, strongSpaces: bool): int =
|
||||
## Calculates the precedence of the given token.
|
||||
template considerStrongSpaces(x): untyped =
|
||||
x + (if strongSpaces: 100 - tok.strongSpaceA.int*10 else: 0)
|
||||
|
||||
case tok.tokType
|
||||
of tkOpr:
|
||||
let L = tok.ident.s.len
|
||||
let relevantChar = tok.ident.s[0]
|
||||
|
||||
# arrow like?
|
||||
if L > 1 and tok.ident.s[L-1] == '>' and
|
||||
tok.ident.s[L-2] in {'-', '~', '='}: return considerStrongSpaces(1)
|
||||
|
||||
template considerAsgn(value: untyped) =
|
||||
result = if tok.ident.s[L-1] == '=': 1 else: value
|
||||
|
||||
case relevantChar
|
||||
of '$', '^': considerAsgn(10)
|
||||
of '*', '%', '/', '\\': considerAsgn(9)
|
||||
of '~': result = 8
|
||||
of '+', '-', '|': considerAsgn(8)
|
||||
of '&': considerAsgn(7)
|
||||
of '=', '<', '>', '!': result = 5
|
||||
of '.': considerAsgn(6)
|
||||
of '?': result = 2
|
||||
else: considerAsgn(2)
|
||||
of tkDiv, tkMod, tkShl, tkShr: result = 9
|
||||
of tkIn, tkNotin, tkIs, tkIsnot, tkNot, tkOf, tkAs: result = 5
|
||||
of tkDotDot: result = 6
|
||||
of tkAnd: result = 4
|
||||
of tkOr, tkXor, tkPtr, tkRef: result = 3
|
||||
else: return -10
|
||||
result = considerStrongSpaces(result)
|
||||
|
||||
|
||||
proc newlineFollows*(L: TLexer): bool =
|
||||
var pos = L.bufpos
|
||||
var buf = L.buf
|
||||
|
|
@ -1249,3 +1285,14 @@ proc getIndentWidth*(fileIdx: FileIndex, inputstream: PLLStream;
|
|||
result = tok.indent
|
||||
if result > 0 or tok.tokType == tkEof: break
|
||||
closeLexer(lex)
|
||||
|
||||
proc getPrecedence*(ident: PIdent): int =
|
||||
## assumes ident is binary operator already
|
||||
var tok: TToken
|
||||
initToken(tok)
|
||||
tok.ident = ident
|
||||
tok.tokType =
|
||||
if tok.ident.id in ord(tokKeywordLow) - ord(tkSymbol) .. ord(tokKeywordHigh) - ord(tkSymbol):
|
||||
TTokType(tok.ident.id + ord(tkSymbol))
|
||||
else: tkOpr
|
||||
getPrecedence(tok, false)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -252,41 +252,6 @@ proc isRightAssociative(tok: TToken): bool {.inline.} =
|
|||
result = tok.tokType == tkOpr and tok.ident.s[0] == '^'
|
||||
# or (let L = tok.ident.s.len; L > 1 and tok.ident.s[L-1] == '>'))
|
||||
|
||||
proc getPrecedence(tok: TToken, strongSpaces: bool): int =
|
||||
## Calculates the precedence of the given token.
|
||||
template considerStrongSpaces(x): untyped =
|
||||
x + (if strongSpaces: 100 - tok.strongSpaceA.int*10 else: 0)
|
||||
|
||||
case tok.tokType
|
||||
of tkOpr:
|
||||
let L = tok.ident.s.len
|
||||
let relevantChar = tok.ident.s[0]
|
||||
|
||||
# arrow like?
|
||||
if L > 1 and tok.ident.s[L-1] == '>' and
|
||||
tok.ident.s[L-2] in {'-', '~', '='}: return considerStrongSpaces(1)
|
||||
|
||||
template considerAsgn(value: untyped) =
|
||||
result = if tok.ident.s[L-1] == '=': 1 else: value
|
||||
|
||||
case relevantChar
|
||||
of '$', '^': considerAsgn(10)
|
||||
of '*', '%', '/', '\\': considerAsgn(9)
|
||||
of '~': result = 8
|
||||
of '+', '-', '|': considerAsgn(8)
|
||||
of '&': considerAsgn(7)
|
||||
of '=', '<', '>', '!': result = 5
|
||||
of '.': considerAsgn(6)
|
||||
of '?': result = 2
|
||||
else: considerAsgn(2)
|
||||
of tkDiv, tkMod, tkShl, tkShr: result = 9
|
||||
of tkIn, tkNotin, tkIs, tkIsnot, tkNot, tkOf, tkAs: result = 5
|
||||
of tkDotDot: result = 6
|
||||
of tkAnd: result = 4
|
||||
of tkOr, tkXor, tkPtr, tkRef: result = 3
|
||||
else: return -10
|
||||
result = considerStrongSpaces(result)
|
||||
|
||||
proc isOperator(tok: TToken): bool =
|
||||
## Determines if the given token is an operator type token.
|
||||
tok.tokType in {tkOpr, tkDiv, tkMod, tkShl, tkShr, tkIn, tkNotin, tkIs,
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ const
|
|||
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
|
||||
wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader,
|
||||
wDeprecated, wExtern, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame,
|
||||
wRaises, wLocks, wTags, wGcSafe}
|
||||
wRaises, wLocks, wTags, wGcSafe, wCodegenDecl}
|
||||
typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl,
|
||||
wPure, wHeader, wCompilerProc, wCore, wFinal, wSize, wExtern, wShallow,
|
||||
wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef,
|
||||
|
|
|
|||
|
|
@ -307,14 +307,19 @@ proc lsub(g: TSrcGen; n: PNode): int
|
|||
proc litAux(g: TSrcGen; n: PNode, x: BiggestInt, size: int): string =
|
||||
proc skip(t: PType): PType =
|
||||
result = t
|
||||
while result.kind in {tyGenericInst, tyRange, tyVar, tyLent, tyDistinct,
|
||||
while result != nil and result.kind in {tyGenericInst, tyRange, tyVar, tyLent, tyDistinct,
|
||||
tyOrdinal, tyAlias, tySink}:
|
||||
result = lastSon(result)
|
||||
if n.typ != nil and n.typ.skip.kind in {tyBool, tyEnum}:
|
||||
let enumfields = n.typ.skip.n
|
||||
let typ = n.typ.skip
|
||||
if typ != nil and typ.kind in {tyBool, tyEnum}:
|
||||
if sfPure in typ.sym.flags:
|
||||
result = typ.sym.name.s & '.'
|
||||
let enumfields = typ.n
|
||||
# we need a slow linear search because of enums with holes:
|
||||
for e in items(enumfields):
|
||||
if e.sym.position == x: return e.sym.name.s
|
||||
if e.sym.position == x:
|
||||
result &= e.sym.name.s
|
||||
return
|
||||
|
||||
if nfBase2 in n.flags: result = "0b" & toBin(x, size * 8)
|
||||
elif nfBase8 in n.flags: result = "0o" & toOct(x, size * 3)
|
||||
|
|
@ -861,6 +866,47 @@ proc isBracket*(n: PNode): bool =
|
|||
of nkSym: result = n.sym.name.s == "[]"
|
||||
else: result = false
|
||||
|
||||
proc skipHiddenNodes(n: PNode): PNode =
|
||||
result = n
|
||||
while result != nil:
|
||||
if result.kind in {nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv} and result.len > 1:
|
||||
result = result[1]
|
||||
elif result.kind in {nkCheckedFieldExpr, nkHiddenAddr, nkHiddenDeref, nkStringToCString, nkCStringToString} and
|
||||
result.len > 0:
|
||||
result = result[0]
|
||||
else: break
|
||||
|
||||
proc accentedName(g: var TSrcGen, n: PNode) =
|
||||
if n == nil: return
|
||||
let isOperator =
|
||||
if n.kind == nkIdent and n.ident.s.len > 0 and n.ident.s[0] in OpChars: true
|
||||
elif n.kind == nkSym and n.sym.name.s.len > 0 and n.sym.name.s[0] in OpChars: true
|
||||
else: false
|
||||
|
||||
if isOperator:
|
||||
put(g, tkAccent, "`")
|
||||
gident(g, n)
|
||||
put(g, tkAccent, "`")
|
||||
else:
|
||||
gsub(g, n)
|
||||
|
||||
proc infixArgument(g: var TSrcGen, n: PNode, i: int) =
|
||||
if i >= n.len: return
|
||||
|
||||
var needsParenthesis = false
|
||||
let n_next = n[i].skipHiddenNodes
|
||||
if n_next.kind == nkInfix:
|
||||
if n_next[0].kind in {nkSym, nkIdent} and n[0].kind in {nkSym, nkIdent}:
|
||||
let nextId = if n_next[0].kind == nkSym: n_next[0].sym.name else: n_next[0].ident
|
||||
let nnId = if n[0].kind == nkSym: n[0].sym.name else: n[0].ident
|
||||
if getPrecedence(nextId) < getPrecedence(nnId):
|
||||
needsParenthesis = true
|
||||
if needsParenthesis:
|
||||
put(g, tkParLe, "(")
|
||||
gsub(g, n, i)
|
||||
if needsParenthesis:
|
||||
put(g, tkParRi, ")")
|
||||
|
||||
proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||
if isNil(n): return
|
||||
var
|
||||
|
|
@ -896,7 +942,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
|||
gcomma(g, n, 2)
|
||||
put(g, tkBracketRi, "]")
|
||||
elif n.len > 1 and n.lastSon.kind == nkStmtList:
|
||||
gsub(g, n[0])
|
||||
accentedName(g, n[0])
|
||||
if n.len > 2:
|
||||
put(g, tkParLe, "(")
|
||||
gcomma(g, n, 1, -2)
|
||||
|
|
@ -904,16 +950,16 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
|||
put(g, tkColon, ":")
|
||||
gsub(g, n, n.len-1)
|
||||
else:
|
||||
if sonsLen(n) >= 1: gsub(g, n.sons[0])
|
||||
if sonsLen(n) >= 1: accentedName(g, n[0])
|
||||
put(g, tkParLe, "(")
|
||||
gcomma(g, n, 1)
|
||||
put(g, tkParRi, ")")
|
||||
of nkCallStrLit:
|
||||
gsub(g, n, 0)
|
||||
if n.len > 0: accentedName(g, n[0])
|
||||
if n.len > 1 and n.sons[1].kind == nkRStrLit:
|
||||
put(g, tkRStrLit, '\"' & replace(n[1].strVal, "\"", "\"\"") & '\"')
|
||||
else:
|
||||
gsub(g, n.sons[1])
|
||||
gsub(g, n, 1)
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv:
|
||||
if n.len >= 2:
|
||||
gsub(g, n.sons[1])
|
||||
|
|
@ -951,7 +997,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
|||
gsub(g, n, 0)
|
||||
gcomma(g, n, 1)
|
||||
of nkCommand:
|
||||
gsub(g, n, 0)
|
||||
accentedName(g, n[0])
|
||||
put(g, tkSpaces, Space)
|
||||
gcomma(g, n, 1)
|
||||
of nkExprEqExpr, nkAsgn, nkFastAsgn:
|
||||
|
|
@ -1064,14 +1110,14 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
|||
putWithSpace(g, tkColon, ":")
|
||||
gsub(g, n, 1)
|
||||
of nkInfix:
|
||||
gsub(g, n, 1)
|
||||
infixArgument(g, n, 1)
|
||||
put(g, tkSpaces, Space)
|
||||
gsub(g, n, 0) # binary operator
|
||||
if not fits(g, lsub(g, n.sons[2]) + lsub(g, n.sons[0]) + 1):
|
||||
optNL(g, g.indent + longIndentWid)
|
||||
else:
|
||||
put(g, tkSpaces, Space)
|
||||
gsub(g, n, 2)
|
||||
infixArgument(g, n, 2)
|
||||
of nkPrefix:
|
||||
gsub(g, n, 0)
|
||||
if n.len > 1:
|
||||
|
|
@ -1079,10 +1125,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
|||
elif n[0].kind == nkSym: n[0].sym.name
|
||||
elif n[0].kind in {nkOpenSymChoice, nkClosedSymChoice}: n[0][0].sym.name
|
||||
else: nil
|
||||
var n_next = n[1]
|
||||
while n_next.kind in {nkCheckedFieldExpr, nkHiddenAddr, nkHiddenDeref,
|
||||
nkStringToCString, nkCStringToString} and n_next.len > 0:
|
||||
n_next = n_next[0]
|
||||
let n_next = skipHiddenNodes(n[1])
|
||||
if n_next.kind == nkPrefix or (opr != nil and renderer.isKeyword(opr)):
|
||||
put(g, tkSpaces, Space)
|
||||
if n_next.kind == nkInfix:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue