Merge branch 'devel' into uint-range-checks

This commit is contained in:
Andreas Rumpf 2019-09-02 22:03:10 +02:00
commit ac6fcab7a4
18 changed files with 123 additions and 51 deletions

View file

@ -608,7 +608,6 @@ type
mAddF64, mSubF64, mMulF64, mDivF64, mAddF64, mSubF64, mMulF64, mDivF64,
mShrI, mShlI, mAshrI, mBitandI, mBitorI, mBitxorI, mShrI, mShlI, mAshrI, mBitandI, mBitorI, mBitxorI,
mMinI, mMaxI, mMinI, mMaxI,
mMinF64, mMaxF64,
mAddU, mSubU, mMulU, mDivU, mModU, mAddU, mSubU, mMulU, mDivU, mModU,
mEqI, mLeI, mLtI, mEqI, mLeI, mLtI,
mEqF64, mLeF64, mLtF64, mEqF64, mLeF64, mLtF64,
@ -621,7 +620,7 @@ type
mXor, mEqCString, mEqProc, mXor, mEqCString, mEqProc,
mUnaryMinusI, mUnaryMinusI64, mAbsI, mNot, mUnaryMinusI, mUnaryMinusI64, mAbsI, mNot,
mUnaryPlusI, mBitnotI, mUnaryPlusI, mBitnotI,
mUnaryPlusF64, mUnaryMinusF64, mAbsF64, mUnaryPlusF64, mUnaryMinusF64,
mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr, mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr,
mStrToStr, mEnumToStr, mStrToStr, mEnumToStr,
mAnd, mOr, mAnd, mOr,
@ -678,7 +677,6 @@ const
mAddF64, mSubF64, mMulF64, mDivF64, mAddF64, mSubF64, mMulF64, mDivF64,
mShrI, mShlI, mBitandI, mBitorI, mBitxorI, mShrI, mShlI, mBitandI, mBitorI, mBitxorI,
mMinI, mMaxI, mMinI, mMaxI,
mMinF64, mMaxF64,
mAddU, mSubU, mMulU, mDivU, mModU, mAddU, mSubU, mMulU, mDivU, mModU,
mEqI, mLeI, mLtI, mEqI, mLeI, mLtI,
mEqF64, mLeF64, mLtF64, mEqF64, mLeF64, mLtF64,
@ -689,7 +687,7 @@ const
mEqB, mLeB, mLtB, mEqB, mLeB, mLtB,
mEqRef, mEqProc, mEqUntracedRef, mLePtr, mLtPtr, mEqCString, mXor, mEqRef, mEqProc, mEqUntracedRef, mLePtr, mLtPtr, mEqCString, mXor,
mUnaryMinusI, mUnaryMinusI64, mAbsI, mNot, mUnaryPlusI, mBitnotI, mUnaryMinusI, mUnaryMinusI64, mAbsI, mNot, mUnaryPlusI, mBitnotI,
mUnaryPlusF64, mUnaryMinusF64, mAbsF64, mUnaryPlusF64, mUnaryMinusF64,
mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr, mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr,
mStrToStr, mEnumToStr, mStrToStr, mEnumToStr,
mAnd, mOr, mAnd, mOr,

View file

@ -77,7 +77,6 @@ proc idNodeTablePut*(t: var TIdNodeTable, key: PIdObj, val: PNode)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
proc getSymFromList*(list: PNode, ident: PIdent, start: int = 0): PSym
proc lookupInRecord*(n: PNode, field: PIdent): PSym proc lookupInRecord*(n: PNode, field: PIdent): PSym
proc mustRehash*(length, counter: int): bool proc mustRehash*(length, counter: int): bool
proc nextTry*(h, maxHash: Hash): Hash {.inline.} proc nextTry*(h, maxHash: Hash): Hash {.inline.}
@ -174,7 +173,7 @@ proc getModule*(s: PSym): PSym =
assert((result.kind == skModule) or (result.owner != result)) assert((result.kind == skModule) or (result.owner != result))
while result != nil and result.kind != skModule: result = result.owner while result != nil and result.kind != skModule: result = result.owner
proc getSymFromList(list: PNode, ident: PIdent, start: int = 0): PSym = proc getSymFromList*(list: PNode, ident: PIdent, start: int = 0): PSym =
for i in start ..< sonsLen(list): for i in start ..< sonsLen(list):
if list.sons[i].kind == nkSym: if list.sons[i].kind == nkSym:
result = list.sons[i].sym result = list.sons[i].sym
@ -182,6 +181,45 @@ proc getSymFromList(list: PNode, ident: PIdent, start: int = 0): PSym =
else: return nil else: return nil
result = nil result = nil
proc sameIgnoreBacktickGensymInfo(a, b: string): bool =
if a[0] != b[0]: return false
var last = a.len - 1
while last > 0 and a[last] != '`': dec(last)
var i = 1
var j = 1
while true:
while i < last and a[i] == '_': inc i
while j < b.len and b[j] == '_': inc j
var aa = if i < last: toLowerAscii(a[i]) else: '\0'
var bb = if j < b.len: toLowerAscii(b[j]) else: '\0'
if aa != bb: return false
# the characters are identical:
if i >= last:
# both cursors at the end:
if j >= b.len: return true
# not yet at the end of 'b':
return false
elif j >= b.len:
return false
inc i
inc j
proc getNamedParamFromList*(list: PNode, ident: PIdent): PSym =
## Named parameters are special because a named parameter can be
## gensym'ed and then they have '`<number>' suffix that we need to
## ignore, see compiler / evaltempl.nim, snippet:
##
## .. code-block:: nim
##
## result.add newIdentNode(getIdent(c.ic, x.name.s & "`gensym" & $x.id),
## if c.instLines: actual.info else: templ.info)
for i in 1 ..< len(list):
let it = list[i].sym
if it.name.id == ident.id or
sameIgnoreBacktickGensymInfo(it.name.s, ident.s): return it
proc hashNode(p: RootRef): Hash = proc hashNode(p: RootRef): Hash =
result = hash(cast[pointer](p)) result = hash(cast[pointer](p))

View file

@ -588,8 +588,6 @@ proc binaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mBitxorI: applyFormat("($4)($1 ^ $2)") of mBitxorI: applyFormat("($4)($1 ^ $2)")
of mMinI: applyFormat("(($1 <= $2) ? $1 : $2)") of mMinI: applyFormat("(($1 <= $2) ? $1 : $2)")
of mMaxI: applyFormat("(($1 >= $2) ? $1 : $2)") of mMaxI: applyFormat("(($1 >= $2) ? $1 : $2)")
of mMinF64: applyFormat("(($1 <= $2) ? $1 : $2)")
of mMaxF64: applyFormat("(($1 >= $2) ? $1 : $2)")
of mAddU: applyFormat("($4)((NU$3)($1) + (NU$3)($2))") of mAddU: applyFormat("($4)((NU$3)($1) + (NU$3)($2))")
of mSubU: applyFormat("($4)((NU$3)($1) - (NU$3)($2))") of mSubU: applyFormat("($4)((NU$3)($1) - (NU$3)($2))")
of mMulU: applyFormat("($4)((NU$3)($1) * (NU$3)($2))") of mMulU: applyFormat("($4)((NU$3)($1) * (NU$3)($2))")
@ -663,9 +661,6 @@ proc unaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
applyFormat("$1") applyFormat("$1")
of mUnaryMinusF64: of mUnaryMinusF64:
applyFormat("-($1)") applyFormat("-($1)")
of mAbsF64:
applyFormat("($1 < 0? -($1) : ($1))")
# BUGFIX: fabs() makes problems for Tiny C
else: else:
assert false, $op assert false, $op
@ -2086,7 +2081,7 @@ proc genEnumToStr(p: BProc, e: PNode, d: var TLoc) =
proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
case op case op
of mOr, mAnd: genAndOr(p, e, d, op) of mOr, mAnd: genAndOr(p, e, d, op)
of mNot..mAbsF64: unaryArith(p, e, d, op) of mNot..mUnaryMinusF64: unaryArith(p, e, d, op)
of mUnaryMinusI..mAbsI: unaryArithOverflow(p, e, d, op) of mUnaryMinusI..mAbsI: unaryArithOverflow(p, e, d, op)
of mAddF64..mDivF64: binaryFloatArith(p, e, d, op) of mAddF64..mDivF64: binaryFloatArith(p, e, d, op)
of mShrI..mXor: binaryArith(p, e, d, op) of mShrI..mXor: binaryArith(p, e, d, op)

View file

@ -35,8 +35,8 @@ const
someMul = {mMulI, mMulF64} someMul = {mMulI, mMulF64}
someDiv = {mDivI, mDivF64} someDiv = {mDivI, mDivF64}
someMod = {mModI} someMod = {mModI}
someMax = {mMaxI, mMaxF64} someMax = {mMaxI}
someMin = {mMinI, mMinF64} someMin = {mMinI}
someBinaryOp = someAdd+someSub+someMul+someMax+someMin someBinaryOp = someAdd+someSub+someMul+someMax+someMin
proc isValue(n: PNode): bool = n.kind in {nkCharLit..nkNilLit} proc isValue(n: PNode): bool = n.kind in {nkCharLit..nkNilLit}

View file

@ -389,8 +389,6 @@ const # magic checked op; magic unchecked op;
["", ""], # BitxorI ["", ""], # BitxorI
["nimMin", "nimMin"], # MinI ["nimMin", "nimMin"], # MinI
["nimMax", "nimMax"], # MaxI ["nimMax", "nimMax"], # MaxI
["nimMin", "nimMin"], # MinF64
["nimMax", "nimMax"], # MaxF64
["", ""], # addU ["", ""], # addU
["", ""], # subU ["", ""], # subU
["", ""], # mulU ["", ""], # mulU
@ -430,7 +428,6 @@ const # magic checked op; magic unchecked op;
["", ""], # BitnotI ["", ""], # BitnotI
["", ""], # UnaryPlusF64 ["", ""], # UnaryPlusF64
["", ""], # UnaryMinusF64 ["", ""], # UnaryMinusF64
["", ""], # AbsF64
["nimCharToStr", "nimCharToStr"], ["nimCharToStr", "nimCharToStr"],
["nimBoolToStr", "nimBoolToStr"], ["nimBoolToStr", "nimBoolToStr"],
["cstrToNimstr", "cstrToNimstr"], ["cstrToNimstr", "cstrToNimstr"],
@ -566,8 +563,6 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
of mBitxorI: applyFormat("($1 ^ $2)", "($1 ^ $2)") of mBitxorI: applyFormat("($1 ^ $2)", "($1 ^ $2)")
of mMinI: applyFormat("nimMin($1, $2)", "nimMin($1, $2)") of mMinI: applyFormat("nimMin($1, $2)", "nimMin($1, $2)")
of mMaxI: applyFormat("nimMax($1, $2)", "nimMax($1, $2)") of mMaxI: applyFormat("nimMax($1, $2)", "nimMax($1, $2)")
of mMinF64: applyFormat("nimMin($1, $2)", "nimMin($1, $2)")
of mMaxF64: applyFormat("nimMax($1, $2)", "nimMax($1, $2)")
of mAddU: applyFormat("", "") of mAddU: applyFormat("", "")
of mSubU: applyFormat("", "") of mSubU: applyFormat("", "")
of mMulU: applyFormat("", "") of mMulU: applyFormat("", "")
@ -607,7 +602,6 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
of mBitnotI: applyFormat("~($1)", "~($1)") of mBitnotI: applyFormat("~($1)", "~($1)")
of mUnaryPlusF64: applyFormat("+($1)", "+($1)") of mUnaryPlusF64: applyFormat("+($1)", "+($1)")
of mUnaryMinusF64: applyFormat("-($1)", "-($1)") of mUnaryMinusF64: applyFormat("-($1)", "-($1)")
of mAbsF64: applyFormat("Math.abs($1)", "Math.abs($1)")
of mCharToStr: applyFormat("nimCharToStr($1)", "nimCharToStr($1)") of mCharToStr: applyFormat("nimCharToStr($1)", "nimCharToStr($1)")
of mBoolToStr: applyFormat("nimBoolToStr($1)", "nimBoolToStr($1)") of mBoolToStr: applyFormat("nimBoolToStr($1)", "nimBoolToStr($1)")
of mIntToStr: applyFormat("cstrToNimstr(($1)+\"\")", "cstrToNimstr(($1)+\"\")") of mIntToStr: applyFormat("cstrToNimstr(($1)+\"\")", "cstrToNimstr(($1)+\"\")")

View file

@ -224,14 +224,14 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult
result = arLocalLValue result = arLocalLValue
else: else:
result = arLValue result = arLValue
elif n.sym.kind == skParam and n.sym.typ.kind == tyVar: elif n.sym.kind == skParam and n.sym.typ.kind in {tyVar, tySink}:
result = arLValue result = arLValue
elif n.sym.kind == skType: elif n.sym.kind == skType:
let t = n.sym.typ.skipTypes({tyTypeDesc}) let t = n.sym.typ.skipTypes({tyTypeDesc})
if t.kind == tyVar: result = arStrange if t.kind == tyVar: result = arStrange
of nkDotExpr: of nkDotExpr:
let t = skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}) let t = skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc})
if t.kind in {tyVar, tyPtr, tyRef}: if t.kind in {tyVar, tySink, tyPtr, tyRef}:
result = arLValue result = arLValue
elif isUnsafeAddr and t.kind == tyLent: elif isUnsafeAddr and t.kind == tyLent:
result = arLValue result = arLValue
@ -242,7 +242,7 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult
result = arDiscriminant result = arDiscriminant
of nkBracketExpr: of nkBracketExpr:
let t = skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}) let t = skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc})
if t.kind in {tyVar, tyPtr, tyRef}: if t.kind in {tyVar, tySink, tyPtr, tyRef}:
result = arLValue result = arLValue
elif isUnsafeAddr and t.kind == tyLent: elif isUnsafeAddr and t.kind == tyLent:
result = arLValue result = arLValue

View file

@ -197,7 +197,6 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
result = newIntNodeT(toInt128(sonsLen(a)), n, g) result = newIntNodeT(toInt128(sonsLen(a)), n, g)
of mUnaryPlusI, mUnaryPlusF64: result = a # throw `+` away of mUnaryPlusI, mUnaryPlusF64: result = a # throw `+` away
# XXX: Hides overflow/underflow # XXX: Hides overflow/underflow
of mAbsF64: result = newFloatNodeT(abs(getFloat(a)), n, g)
of mAbsI: result = foldAbs(getInt(a), n, g) of mAbsI: result = foldAbs(getInt(a), n, g)
of mUnaryLt: result = foldSub(getOrdValue(a), One, n, g) of mUnaryLt: result = foldSub(getOrdValue(a), One, n, g)
of mSucc: result = foldAdd(getOrdValue(a), getInt(b), n, g) of mSucc: result = foldAdd(getOrdValue(a), getInt(b), n, g)
@ -277,12 +276,6 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
of mMulF64: result = newFloatNodeT(getFloat(a) * getFloat(b), n, g) of mMulF64: result = newFloatNodeT(getFloat(a) * getFloat(b), n, g)
of mDivF64: of mDivF64:
result = newFloatNodeT(getFloat(a) / getFloat(b), n, g) result = newFloatNodeT(getFloat(a) / getFloat(b), n, g)
of mMaxF64:
if getFloat(a) > getFloat(b): result = newFloatNodeT(getFloat(a), n, g)
else: result = newFloatNodeT(getFloat(b), n, g)
of mMinF64:
if getFloat(a) > getFloat(b): result = newFloatNodeT(getFloat(b), n, g)
else: result = newFloatNodeT(getFloat(a), n, g)
of mIsNil: result = newIntNodeT(ord(a.kind == nkNilLit), n, g) of mIsNil: result = newIntNodeT(ord(a.kind == nkNilLit), n, g)
of mLtI, mLtB, mLtEnum, mLtCh: of mLtI, mLtB, mLtEnum, mLtCh:
result = newIntNodeT(ord(getOrdValue(a) < getOrdValue(b)), n, g) result = newIntNodeT(ord(getOrdValue(a) < getOrdValue(b)), n, g)

View file

@ -80,6 +80,7 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule;
while a != nil: while a != nil:
if a.kind != skModule and (not isField or sfGenSym notin s.flags): if a.kind != skModule and (not isField or sfGenSym notin s.flags):
incl(a.flags, sfUsed) incl(a.flags, sfUsed)
markOwnerModuleAsUsed(c, a)
addSon(result, newSymNode(a, info)) addSon(result, newSymNode(a, info))
onUse(info, a) onUse(info, a)
a = nextOverloadIter(o, c, n) a = nextOverloadIter(o, c, n)

View file

@ -108,6 +108,7 @@ const
isNilConversion = isConvertible # maybe 'isIntConv' fits better? isNilConversion = isConvertible # maybe 'isIntConv' fits better?
proc markUsed*(c: PContext; info: TLineInfo, s: PSym) proc markUsed*(c: PContext; info: TLineInfo, s: PSym)
proc markOwnerModuleAsUsed*(c: PContext; s: PSym)
template hasFauxMatch*(c: TCandidate): bool = c.fauxMatch != tyNone template hasFauxMatch*(c: TCandidate): bool = c.fauxMatch != tyNone
@ -380,7 +381,7 @@ proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation =
isIntLit(ab) and getInt(ab.n) >= firstOrd(nil, f) and isIntLit(ab) and getInt(ab.n) >= firstOrd(nil, f) and
getInt(ab.n) <= lastOrd(nil, f): getInt(ab.n) <= lastOrd(nil, f):
# passing 'nil' to firstOrd/lastOrd here as type checking rules should # passing 'nil' to firstOrd/lastOrd here as type checking rules should
# not depent on the target integer size configurations! # not depend on the target integer size configurations!
# integer literal in the proper range; we want ``i16 + 4`` to stay an # integer literal in the proper range; we want ``i16 + 4`` to stay an
# ``int16`` operation so we declare the ``4`` pseudo-equal to int16 # ``int16`` operation so we declare the ``4`` pseudo-equal to int16
result = isFromIntLit result = isFromIntLit
@ -396,7 +397,7 @@ proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation =
f.kind in {tyUInt8..tyUInt32} and a[0].kind in {tyUInt8..tyInt32}) and f.kind in {tyUInt8..tyUInt32} and a[0].kind in {tyUInt8..tyInt32}) and
a.n[0].intVal >= firstOrd(nil, f) and a.n[1].intVal <= lastOrd(nil, f): a.n[0].intVal >= firstOrd(nil, f) and a.n[1].intVal <= lastOrd(nil, f):
# passing 'nil' to firstOrd/lastOrd here as type checking rules should # passing 'nil' to firstOrd/lastOrd here as type checking rules should
# not depent on the target integer size configurations! # not depend on the target integer size configurations!
result = isConvertible result = isConvertible
else: result = isNone else: result = isNone
@ -408,13 +409,13 @@ proc isConvertibleToRange(f, a: PType): bool =
of tyInt16: result = isIntLit(a) or a.kind in {tyInt8, tyInt16} of tyInt16: result = isIntLit(a) or a.kind in {tyInt8, tyInt16}
of tyInt32: result = isIntLit(a) or a.kind in {tyInt8, tyInt16, tyInt32} of tyInt32: result = isIntLit(a) or a.kind in {tyInt8, tyInt16, tyInt32}
# This is wrong, but seems like there's a lot of code that relies on it :( # This is wrong, but seems like there's a lot of code that relies on it :(
of tyInt: result = true of tyInt, tyUInt, tyUInt64: result = true
of tyInt64: result = isIntLit(a) or a.kind in {tyInt8, tyInt16, tyInt32, tyInt, tyInt64} of tyInt64: result = isIntLit(a) or a.kind in {tyInt8, tyInt16, tyInt32, tyInt, tyInt64}
of tyUInt8: result = isIntLit(a) or a.kind in {tyUInt8} of tyUInt8: result = isIntLit(a) or a.kind in {tyUInt8}
of tyUInt16: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16} of tyUInt16: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16}
of tyUInt32: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32} of tyUInt32: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32}
of tyUInt: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32, tyUInt} #of tyUInt: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32, tyUInt}
of tyUInt64: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32, tyUInt, tyUInt64} #of tyUInt64: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32, tyUInt, tyUInt64}
else: result = false else: result = false
elif f.kind in {tyFloat..tyFloat128}: elif f.kind in {tyFloat..tyFloat128}:
# `isIntLit` is correct and should be used above as well, see PR: # `isIntLit` is correct and should be used above as well, see PR:
@ -2362,7 +2363,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
localError(c.config, n.sons[a].info, "named parameter has to be an identifier") localError(c.config, n.sons[a].info, "named parameter has to be an identifier")
noMatch() noMatch()
return return
formal = getSymFromList(m.callee.n, n.sons[a].sons[0].ident, 1) formal = getNamedParamFromList(m.callee.n, n.sons[a].sons[0].ident)
if formal == nil: if formal == nil:
# no error message! # no error message!
noMatch() noMatch()

View file

@ -1309,7 +1309,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
tyNone, tyForward, tyFromExpr: tyNone, tyForward, tyFromExpr:
result = t result = t
of tyNil: of tyNil:
if kind != skConst and kind != skParam and kind != skResult: result = t if kind != skConst and kind != skParam: result = t
of tyString, tyBool, tyChar, tyEnum, tyInt..tyUInt64, tyCString, tyPointer: of tyString, tyBool, tyChar, tyEnum, tyInt..tyUInt64, tyCString, tyPointer:
result = nil result = nil
of tyOrdinal: of tyOrdinal:

View file

@ -1288,7 +1288,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
if dest < 0: dest = c.getTemp(n.typ) if dest < 0: dest = c.getTemp(n.typ)
c.gABC(n, opcCallSite, dest) c.gABC(n, opcCallSite, dest)
of mNGenSym: genBinaryABC(c, n, dest, opcGenSym) of mNGenSym: genBinaryABC(c, n, dest, opcGenSym)
of mMinI, mMaxI, mAbsF64, mMinF64, mMaxF64, mAbsI, mDotDot: of mMinI, mMaxI, mAbsI, mDotDot:
c.genCall(n, dest) c.genCall(n, dest)
of mExpandToAst: of mExpandToAst:
if n.len != 2: if n.len != 2:

View file

@ -14,6 +14,9 @@
when not defined(profiler) and not defined(memProfiler): when not defined(profiler) and not defined(memProfiler):
{.error: "Profiling support is turned off! Enable profiling by passing `--profiler:on --stackTrace:on` to the compiler (see the Nim Compiler User Guide for more options).".} {.error: "Profiling support is turned off! Enable profiling by passing `--profiler:on --stackTrace:on` to the compiler (see the Nim Compiler User Guide for more options).".}
when defined(nimHasUsed):
{.used.}
# We don't want to profile the profiling code ... # We don't want to profile the profiling code ...
{.push profiler: off.} {.push profiler: off.}

View file

@ -2880,17 +2880,21 @@ proc max*[T](x: openArray[T]): T =
for i in 1..high(x): for i in 1..high(x):
if result < x[i]: result = x[i] if result < x[i]: result = x[i]
proc abs*(x: float): float {.magic: "AbsF64", noSideEffect.} = proc abs*(x: float64): float64 {.noSideEffect, inline.} =
if x < 0.0: -x else: x if x < 0.0: -x else: x
proc min*(x, y: float): float {.magic: "MinF64", noSideEffect.} = proc abs*(x: float32): float32 {.noSideEffect, inline.} =
if x < 0.0: -x else: x
proc min*(x, y: float32): float32 {.noSideEffect, inline.} =
if x <= y or y != y: x else: y
proc min*(x, y: float64): float64 {.noSideEffect, inline.} =
if x <= y or y != y: x else: y
proc max*(x, y: float32): float32 {.noSideEffect, inline.} =
if y <= x or y != y: x else: y
proc max*(x, y: float64): float64 {.noSideEffect, inline.} =
if y <= x or y != y: x else: y
proc min*[T: not SomeFloat](x, y: T): T {.inline.} =
if x <= y: x else: y if x <= y: x else: y
proc max*(x, y: float): float {.magic: "MaxF64", noSideEffect.} = proc max*[T: not SomeFloat](x, y: T): T {.inline.} =
if y <= x: x else: y
proc min*[T](x, y: T): T {.inline.}=
if x <= y: x else: y
proc max*[T](x, y: T): T {.inline.}=
if y <= x: x else: y if y <= x: x else: y
{.pop.} {.pop.}

View file

@ -13,6 +13,3 @@ f3(typeof(nil))
proc f4[T](_: T) = discard proc f4[T](_: T) = discard
f4(nil) f4(nil)
proc f5(): typeof(nil) = nil
discard f5()

View file

@ -85,3 +85,16 @@ testWrongAt()
let (a, d) = allocCounters() let (a, d) = allocCounters()
discard cprintf("%ld new: %ld\n", a - unpairedEnvAllocs() - d, allocs) discard cprintf("%ld new: %ld\n", a - unpairedEnvAllocs() - d, allocs)
#-------------------------------------------------
type
Table[A, B] = object
x: seq[(A, B)]
proc toTable[A,B](p: sink openArray[(A, B)]): Table[A, B] =
for zz in mitems(p):
result.x.add move(zz)
let table = {"a": new(int)}.toTable()

View file

@ -136,3 +136,9 @@ block:
const x11: range[0'f..1'f] = 2'f const x11: range[0'f..1'f] = 2'f
reject: reject:
const x12: range[0'f..1'f] = 2 const x12: range[0'f..1'f] = 2
# ensure unsigned array indexing is remains lenient:
var a: array[4'u, string]
for i in 0..<a.len:
a[i] = "foo"

View file

@ -160,7 +160,6 @@ block: # `$`*[T: tuple|object](x: T)
doAssert $Foo(x:2) == "(x: 2, x2: 0.0)" doAssert $Foo(x:2) == "(x: 2, x2: 0.0)"
doAssert $() == "()" doAssert $() == "()"
# this is a call indirection to prevent `toInt` to be resolved at compile time. # this is a call indirection to prevent `toInt` to be resolved at compile time.
proc testToInt(arg: float64, a: int, b: BiggestInt) = proc testToInt(arg: float64, a: int, b: BiggestInt) =
doAssert toInt(arg) == a doAssert toInt(arg) == a
@ -174,3 +173,14 @@ testToInt(13.37, 13, 13) # should round towards 0
testToInt(-13.37, -13, -13) # should round towards 0 testToInt(-13.37, -13, -13) # should round towards 0
testToInt(7.8, 8, 8) # should round away from 0 testToInt(7.8, 8, 8) # should round away from 0
testToInt(-7.8, -8, -8) # should round away from 0 testToInt(-7.8, -8, -8) # should round away from 0
# test min/max for correct NaN handling
proc testMinMax(a,b: float32) =
doAssert max(float32(a),float32(b)) == 0'f32
doAssert min(float32(a),float32(b)) == 0'f32
doAssert max(float64(a),float64(b)) == 0'f64
doAssert min(float64(a),float64(b)) == 0'f64
testMinMax(0.0, NaN)
testMinMax(NaN, 0.0)

View file

@ -9,6 +9,11 @@ output: '''
2 2
3 3
wth wth
3
2
1
0
(total: 6)
''' '''
""" """
# bug #1915 # bug #1915
@ -145,3 +150,17 @@ macro m(): untyped =
let meh = m() let meh = m()
meh("wth") meh("wth")
macro foo(body: untyped): untyped =
result = body
template baz(): untyped =
foo:
proc bar2(b: int): int =
echo b
if b > 0: b + bar2(b = b - 1)
else: 0
echo (total: bar2(3))
baz()