Compare commits

..

29 Commits

Author SHA1 Message Date
narimiran
c6f601d48e bump version to 0.19.6 2019-05-10 13:35:12 +02:00
Miran
d353c20c03 fixes #7569, all credit to @vincentvidal (#11213)
(cherry picked from commit e54546bcff)
2019-05-10 09:41:27 +02:00
Clyybber
b85cc17998 Fix #9844 (#11216)
(cherry picked from commit 6be9b98e35)
2019-05-10 09:39:03 +02:00
genotrance
8c4c3464e1 Fix 105, few fixes for 101 (#11148)
(cherry picked from commit 45759b5e90)
2019-05-07 17:38:00 +02:00
Jasper Jenkins
f575cdc1ae Add len check for newIfStmt to avoid segfault (#11032)
(cherry picked from commit a68c5662f2)
2019-05-07 17:36:49 +02:00
Andy Davidoff
15c526c298 render urls correctly (#11022)
(cherry picked from commit 485d5448fa)
2019-05-07 17:36:17 +02:00
Miran
a62685372f json: add '\v' support, fixes #10541 (#10987)
(cherry picked from commit 2608bc369e)
2019-05-07 17:35:55 +02:00
genotrance
8b7cd2e19f Fix #10907 - remove unused typedef string (#10908)
(cherry picked from commit 0378bfa402)
2019-05-07 17:35:33 +02:00
Andreas Rumpf
80e9270580 macros: typo
(cherry picked from commit 802ecbc49e)
2019-05-07 17:34:45 +02:00
Araq
d92f322faa backport sane ast.isException implementation 2019-04-30 09:30:35 +02:00
cooldome
dbca89730b Fixes #7845 (Cannot raise generic exception)
(cherry picked from commit 541c2a3fec)
2019-04-29 13:35:45 +02:00
narimiran
f1c297e439 fix duplicate definition 2019-04-12 09:38:22 +02:00
cooldome
3cf038027b fixes #10765 (#10993) [backport]
(cherry picked from commit de02fd0b89)
2019-04-11 15:15:43 +02:00
narimiran
0e34258749 remove the test for stuff that is not backported 2019-03-24 21:37:32 +01:00
Andreas Rumpf
897b63e5cd stats.nim: bugfix: use min in '+' [backport]
(cherry picked from commit 1332f649b2)
2019-03-24 19:07:33 +01:00
Andreas Rumpf
c9c5abcdc1 fixes #10886 [backport] (#10897)
(cherry picked from commit 0b2a3f6f7f)
2019-03-24 19:07:08 +01:00
Andreas Rumpf
541b8df315 multi-methods: remove hack, make tmethod_various compile under strict C++ [backport]
(cherry picked from commit 4181baf400)
2019-03-24 19:04:57 +01:00
narimiran
2d1dea9484 keep only the relevant part of tbasics test 2019-02-21 08:56:43 +01:00
Araq
aa2dfd1cef fixes a critical strutils bug [backport]
(cherry picked from commit 68ce92d4eb)
2019-02-20 19:47:02 +01:00
Araq
32780acc61 fixes 10697 [backport]
(cherry picked from commit 257965e105)
2019-02-20 19:46:19 +01:00
LemonBoy
3aeaa90bd8 Fix edge case in type hashing (#10601) [backport]
Empty types introduced by a template produced the same hash of the
"clean" type sharing the same name.

(cherry picked from commit 631a8ab57f)
2019-02-20 19:34:16 +01:00
Andreas Rumpf
99fc4029e0 fixes #10584 [backport]
(cherry picked from commit 65f3e390e8)
2019-02-20 19:25:33 +01:00
Matt Haggard
37ff8753a1 Add non-interactive installer flag (-y) to finish.nim (#10603) [backport]
(cherry picked from commit fd62d24c4c)
2019-02-08 09:39:36 +01:00
narimiran
f1a78b8b4c tbitops: remove unavailable tests 2019-02-07 09:35:06 +01:00
Araq
12bc7c9882 koch winrelease: also bundle c2nim for Windows 2019-02-06 18:23:17 +01:00
Arne Döring
c9441c6f79 Vm bitops fixes (#10520) 2019-02-05 15:51:08 +01:00
Arne Döring
eb42853ff4 Fix vm signed xor (#10519)
* fix #10482

* undo changes

* fix for bitwise not

* remove dead opcode

(cherry picked from commit b80dbdb77d)
2019-02-05 15:41:40 +01:00
cooldome
c366a8e386 vm fix for bitwise signed ints (#10507)
* fixes #10482

* add missing file

* bug fix

(cherry picked from commit 1d5437e9d2)
2019-02-05 15:41:25 +01:00
narimiran
56d213ca9b bump version number to 0.19.5 2019-02-05 15:41:00 +01:00
36 changed files with 335 additions and 150 deletions

View File

@@ -181,9 +181,16 @@ proc isPartOf*(a, b: PNode): TAnalysisResult =
else: discard
of nkObjConstr:
result = arNo
for i in 1..<b.len:
for i in 1 ..< b.len:
let res = isPartOf(a, b[i][1])
if res != arNo:
result = res
if res == arYes: break
of nkCall:
result = arNo
for i in 1 ..< b.len:
let res = isPartOf(a, b[i])
if res != arNo:
result = res
if res == arYes: break
else: discard

View File

@@ -990,7 +990,7 @@ const
miscPos* = 5 # used for undocumented and hacky stuff
bodyPos* = 6 # position of body; use rodread.getBody() instead!
resultPos* = 7
dispatcherPos* = 8 # caution: if method has no 'result' it can be position 7!
dispatcherPos* = 8
nkCallKinds* = {nkCall, nkInfix, nkPrefix, nkPostfix,
nkCommand, nkCallStrLit, nkHiddenCallConv}
@@ -1711,8 +1711,7 @@ proc toVar*(typ: PType): PType =
proc toRef*(typ: PType): PType =
## If ``typ`` is a tyObject then it is converted into a `ref <typ>` and
## returned. Otherwise ``typ`` is simply returned as-is.
result = typ
if typ.kind == tyObject:
if typ.skipTypes({tyAlias, tyGenericInst}).kind == tyObject:
result = newType(tyRef, typ.owner)
rawAddSon(result, typ)
@@ -1720,19 +1719,19 @@ proc toObject*(typ: PType): PType =
## If ``typ`` is a tyRef then its immediate son is returned (which in many
## cases should be a ``tyObject``).
## Otherwise ``typ`` is simply returned as-is.
result = typ
if result.kind == tyRef:
result = result.lastSon
let t = typ.skipTypes({tyAlias, tyGenericInst})
if t.kind == tyRef: t.lastSon
else: typ
proc isException*(t: PType): bool =
# check if `y` is object type and it inherits from Exception
assert(t != nil)
if t.kind != tyObject:
if t.kind notin {tyObject, tyGenericInst}:
return false
var base = t
while base != nil:
while base != nil and base.kind in {tyRef, tyObject, tyGenericInst}:
if base.sym != nil and base.sym.magic == mException:
return true
base = base.lastSon

View File

@@ -165,7 +165,6 @@ proc mapType(conf: ConfigRef; typ: PType): TCTypeKind =
of tySet:
if mapSetType(conf, base) == ctArray: result = ctPtrToArray
else: result = ctPtr
# XXX for some reason this breaks the pegs module
else: result = ctPtr
of tyPointer: result = ctPtr
of tySequence: result = ctNimSeq

View File

@@ -37,10 +37,9 @@ proc genConv(n: PNode, d: PType, downcast: bool; conf: ConfigRef): PNode =
proc getDispatcher*(s: PSym): PSym =
## can return nil if is has no dispatcher.
let dispn = lastSon(s.ast)
if dispn.kind == nkSym:
let disp = dispn.sym
if sfDispatcher in disp.flags: result = disp
if dispatcherPos < s.ast.len:
result = s.ast[dispatcherPos].sym
doAssert sfDispatcher in result.flags
proc methodCall*(n: PNode; conf: ConfigRef): PNode =
result = n
@@ -99,13 +98,14 @@ proc sameMethodBucket(a, b: PSym): MethodResult =
return No
proc attachDispatcher(s: PSym, dispatcher: PNode) =
var L = s.ast.len-1
var x = s.ast.sons[L]
if x.kind == nkSym and sfDispatcher in x.sym.flags:
if dispatcherPos < s.ast.len:
# we've added a dispatcher already, so overwrite it
s.ast.sons[L] = dispatcher
s.ast.sons[dispatcherPos] = dispatcher
else:
s.ast.add(dispatcher)
setLen(s.ast.sons, dispatcherPos+1)
if s.ast[resultPos] == nil:
s.ast[resultPos] = newNodeI(nkEmpty, s.info)
s.ast.sons[dispatcherPos] = dispatcher
proc createDispatcher(s: PSym): PSym =
var disp = copySym(s)
@@ -165,7 +165,7 @@ proc methodDef*(g: ModuleGraph; s: PSym, fromCache: bool) =
case sameMethodBucket(disp, s)
of Yes:
add(g.methods[i].methods, s)
attachDispatcher(s, lastSon(disp.ast))
attachDispatcher(s, disp.ast[dispatcherPos])
fixupDispatcher(s, disp, g.config)
#echo "fixup ", disp.name.s, " ", disp.id
when useEffectSystem: checkMethodEffects(g, disp, s)

View File

@@ -48,14 +48,14 @@ const
"Copyright (c) 2006-" & copyrightYear & " by Andreas Rumpf\n"
const
Usage = slurp"../doc/basicopt.txt".replace("//", "")
Usage = slurp"../doc/basicopt.txt".replace(" //", " ")
FeatureDesc = block:
var x = ""
for f in low(Feature)..high(Feature):
if x.len > 0: x.add "|"
x.add $f
x
AdvancedUsage = slurp"../doc/advopt.txt".replace("//", "") % FeatureDesc
AdvancedUsage = slurp"../doc/advopt.txt".replace(" //", " ") % FeatureDesc
proc getCommandLineDesc(conf: ConfigRef): string =
result = (HelpMessage % [VersionAsString, platform.OS[conf.target.hostOS].name,

View File

@@ -92,6 +92,7 @@ proc importSymbol(c: PContext, n: PNode, fromMod: PSym) =
rawImportSymbol(c, e)
e = nextIdentIter(it, fromMod.tab)
else: rawImportSymbol(c, s)
suggestSym(c.config, n.info, s, c.graph.usageSym, false)
proc importAllSymbolsExcept(c: PContext, fromMod: PSym, exceptSet: IntSet) =
var i: TTabIter

View File

@@ -476,6 +476,7 @@ proc binaryUintExpr(p: PProc, n: PNode, r: var TCompRes, op: string,
r.res = "$1 = (($1 $2 $3) $4)" % [x.rdLoc, rope op, y.rdLoc, trimmer]
else:
r.res = "(($1 $2 $3) $4)" % [x.rdLoc, rope op, y.rdLoc, trimmer]
r.kind = resExpr
proc ternaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
var x, y, z: TCompRes
@@ -1706,13 +1707,13 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
of mHigh:
unaryExpr(p, n, r, "", "($1 != null ? ($1.length-1) : -1)")
of mInc:
if n[1].typ.skipTypes(abstractRange).kind in tyUInt .. tyUInt64:
if n[1].typ.skipTypes(abstractRange).kind in {tyUInt..tyUInt64}:
binaryUintExpr(p, n, r, "+", true)
else:
if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 += $2")
else: binaryExpr(p, n, r, "addInt", "$1 = addInt($1, $2)")
of ast.mDec:
if n[1].typ.skipTypes(abstractRange).kind in tyUInt .. tyUInt64:
if n[1].typ.skipTypes(abstractRange).kind in {tyUInt..tyUInt64}:
binaryUintExpr(p, n, r, "-", true)
else:
if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 -= $2")

View File

@@ -823,11 +823,12 @@ proc semRaise(c: PContext, n: PNode): PNode =
checkSonsLen(n, 1, c.config)
if n[0].kind != nkEmpty:
n[0] = semExprWithType(c, n[0])
let typ = n[0].typ
var typ = n[0].typ
if not isImportedException(typ, c.config):
if typ.kind != tyRef or typ.lastSon.kind != tyObject:
typ = typ.skipTypes({tyAlias, tyGenericInst})
if typ.kind != tyRef:
localError(c.config, n.info, errExprCannotBeRaised)
if typ.len > 0 and not isException(typ.lastSon):
if not isException(typ.lastSon):
localError(c.config, n.info, "raised object of type $1 does not inherit from Exception",
[typeToString(typ)])

View File

@@ -725,8 +725,8 @@ proc addInheritedFieldsAux(c: PContext, check: var IntSet, pos: var int,
of nkOfBranch, nkElse:
addInheritedFieldsAux(c, check, pos, lastSon(n.sons[i]))
else: internalError(c.config, n.info, "addInheritedFieldsAux(record case branch)")
of nkRecList:
for i in countup(0, sonsLen(n) - 1):
of nkRecList, nkRecWhen, nkElifBranch, nkElse:
for i in 0 ..< sonsLen(n):
addInheritedFieldsAux(c, check, pos, n.sons[i])
of nkSym:
incl(check, n.sym.name.id)
@@ -972,7 +972,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
if lifted != nil: paramType.sons[i] = lifted
let body = paramType.base
if body.kind == tyForward:
if body.kind in {tyForward, tyError}:
# this may happen for proc type appearing in a type section
# before one of its param types
return

View File

@@ -67,11 +67,10 @@ proc cacheTypeInst*(inst: PType) =
# update the refcount
let gt = inst.sons[0]
let t = if gt.kind == tyGenericBody: gt.lastSon else: gt
if t.kind in {tyStatic, tyGenericParam} + tyTypeClasses:
if t.kind in {tyStatic, tyError, tyGenericParam} + tyTypeClasses:
return
gt.sym.typeInstCache.safeAdd(inst)
type
LayeredIdTable* = object
topLayer*: TIdTable
@@ -336,6 +335,9 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
# but we already raised an error!
rawAddSon(result, header.sons[i])
if body.kind == tyError:
return
let bbody = lastSon body
var newbody = replaceTypeVarsT(cl, bbody)
let bodyIsNew = newbody != bbody

View File

@@ -196,18 +196,23 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
else:
c.hashSym(t.sym)
if {sfAnon, sfGenSym} * t.sym.flags != {}:
# generated object names can be identical, so we need to
# disambiguate furthermore by hashing the field types and names:
# mild hack to prevent endless recursions (makes nimforum compile again):
let oldFlags = t.sym.flags
t.sym.flags = t.sym.flags - {sfAnon, sfGenSym}
let n = t.n
for i in 0 ..< n.len:
assert n[i].kind == nkSym
let s = n[i].sym
c.hashSym s
c.hashType s.typ, flags
t.sym.flags = oldFlags
# Generated object names can be identical, so we need to
# disambiguate furthermore by hashing the field types and names.
if t.n.len > 0:
let oldFlags = t.sym.flags
# Mild hack to prevent endless recursion.
t.sym.flags = t.sym.flags - {sfAnon, sfGenSym}
for n in t.n:
assert(n.kind == nkSym)
let s = n.sym
c.hashSym s
c.hashType s.typ, flags
t.sym.flags = oldFlags
else:
# The object has no fields: we _must_ add something here in order to
# make the hash different from the one we produce by hashing only the
# type name.
c &= ".empty"
else:
c &= t.id
if t.len > 0 and t.sons[0] != nil:

View File

@@ -130,6 +130,7 @@ proc elemType*(t: PType): PType =
case t.kind
of tyGenericInst, tyDistinct, tyAlias, tySink: result = elemType(lastSon(t))
of tyArray: result = t.sons[1]
of tyError: result = t
else: result = t.lastSon
assert(result != nil)

View File

@@ -1211,6 +1211,11 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
of opcNarrowU:
decodeB(rkInt)
regs[ra].intVal = regs[ra].intVal and ((1'i64 shl rb)-1)
of opcSignExtend:
# like opcNarrowS, but no out of range possible
decodeB(rkInt)
let imm = 64 - rb
regs[ra].intVal = ashr(regs[ra].intVal shl imm, imm)
of opcIsNil:
decodeB(rkInt)
let node = regs[rb].node

View File

@@ -71,6 +71,7 @@ type
opcSubStr, opcParseFloat, opcConv, opcCast,
opcQuit,
opcNarrowS, opcNarrowU,
opcSignExtend,
opcAddStrCh,
opcAddStrStr,

View File

@@ -361,16 +361,28 @@ proc genIf(c: PCtx, n: PNode; dest: var TDest) =
for endPos in endings: c.patch(endPos)
c.clearDest(n, dest)
proc isTemp(c: PCtx; dest: TDest): bool =
result = dest >= 0 and c.prc.slots[dest].kind >= slotTempUnknown
proc genAndOr(c: PCtx; n: PNode; opc: TOpcode; dest: var TDest) =
# asgn dest, a
# tjmp|fjmp L1
# asgn dest, b
# L1:
if dest < 0: dest = getTemp(c, n.typ)
c.gen(n.sons[1], dest)
let L1 = c.xjmp(n, opc, dest)
c.gen(n.sons[2], dest)
let copyBack = dest < 0 or not isTemp(c, dest)
let tmp = if copyBack:
getTemp(c, n.typ)
else:
TRegister dest
c.gen(n.sons[1], tmp)
let L1 = c.xjmp(n, opc, tmp)
c.gen(n.sons[2], tmp)
c.patch(L1)
if dest < 0:
dest = tmp
elif copyBack:
c.gABC(n, opcAsgnInt, dest, tmp)
freeTemp(c, tmp)
proc canonValue*(n: PNode): PNode =
result = n
@@ -938,11 +950,18 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
c.freeTemp(tmp)
c.freeTemp(tmp2)
of mShlI: genBinaryABCnarrowU(c, n, dest, opcShlInt)
of mAshrI: genBinaryABCnarrow(c, n, dest, opcAshrInt)
of mBitandI: genBinaryABCnarrowU(c, n, dest, opcBitandInt)
of mBitorI: genBinaryABCnarrowU(c, n, dest, opcBitorInt)
of mBitxorI: genBinaryABCnarrowU(c, n, dest, opcBitxorInt)
of mShlI:
genBinaryABC(c, n, dest, opcShlInt)
# genNarrowU modified
let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})
if t.kind in {tyUInt8..tyUInt32} or (t.kind == tyUInt and t.size < 8):
c.gABC(n, opcNarrowU, dest, TRegister(t.size*8))
elif t.kind in {tyInt8..tyInt32} or (t.kind == tyInt and t.size < 8):
c.gABC(n, opcSignExtend, dest, TRegister(t.size*8))
of mAshrI: genBinaryABC(c, n, dest, opcAshrInt)
of mBitandI: genBinaryABC(c, n, dest, opcBitandInt)
of mBitorI: genBinaryABC(c, n, dest, opcBitorInt)
of mBitxorI: genBinaryABC(c, n, dest, opcBitxorInt)
of mAddU: genBinaryABCnarrowU(c, n, dest, opcAddu)
of mSubU: genBinaryABCnarrowU(c, n, dest, opcSubu)
of mMulU: genBinaryABCnarrowU(c, n, dest, opcMulu)
@@ -961,7 +980,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
of mLtPtr, mLtU, mLtU64: genBinaryABC(c, n, dest, opcLtu)
of mEqProc, mEqRef, mEqUntracedRef:
genBinaryABC(c, n, dest, opcEqRef)
of mXor: genBinaryABCnarrowU(c, n, dest, opcXor)
of mXor: genBinaryABC(c, n, dest, opcXor)
of mNot: genUnaryABC(c, n, dest, opcNot)
of mUnaryMinusI, mUnaryMinusI64:
genUnaryABC(c, n, dest, opcUnaryMinusInt)
@@ -970,7 +989,10 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
of mUnaryPlusI, mUnaryPlusF64: gen(c, n.sons[1], dest)
of mBitnotI:
genUnaryABC(c, n, dest, opcBitnotInt)
genNarrowU(c, n, dest)
#genNarrowU modified, do not narrow signed types
let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})
if t.kind in {tyUInt8..tyUInt32} or (t.kind == tyUInt and t.size < 8):
c.gABC(n, opcNarrowU, dest, TRegister(t.size*8))
of mToFloat, mToBiggestFloat, mToInt,
mToBiggestInt, mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr,
mFloatToStr, mCStrToStr, mStrToStr, mEnumToStr:
@@ -1386,9 +1408,6 @@ proc checkCanEval(c: PCtx; n: PNode) =
skIterator} and sfForward in s.flags:
cannotEval(c, n)
proc isTemp(c: PCtx; dest: TDest): bool =
result = dest >= 0 and c.prc.slots[dest].kind >= slotTempUnknown
template needsAdditionalCopy(n): untyped =
not c.isTemp(dest) and not fitsRegister(n.typ)

View File

@@ -74,7 +74,7 @@ template withDir(dir, body) =
setCurrentDir(dir)
body
finally:
setCurrentdir(old)
setCurrentDir(old)
proc tryExec(cmd: string): bool =
echo(cmd)
@@ -110,6 +110,11 @@ proc bundleNimbleSrc(latest: bool) =
exec("git checkout -f stable")
exec("git pull")
proc bundleC2nim() =
if not dirExists("dist/c2nim/.git"):
exec("git clone https://github.com/nim-lang/c2nim.git dist/c2nim")
nimCompile("dist/c2nim/c2nim", options = "--noNimblePath --path:.")
proc bundleNimbleExe(latest: bool) =
bundleNimbleSrc(latest)
# now compile Nimble and copy it to $nim/bin for the installer.ini
@@ -160,6 +165,7 @@ proc bundleWinTools() =
buildVccTool()
nimexec("c -o:bin/nimgrab.exe -d:ssl tools/nimgrab.nim")
nimexec("c -o:bin/nimgrep.exe tools/nimgrep.nim")
bundleC2nim()
when false:
# not yet a tool worth including
nimexec(r"c --cc:vcc --app:gui -o:bin\downloader.exe -d:ssl --noNimblePath " &
@@ -548,6 +554,7 @@ when isMainModule:
else: buildTools(existsDir(".git") or latest)
of "pushcsource", "pushcsources": pushCsources()
of "valgrind": valgrind(op.cmdLineRest)
of "c2nim": bundleC2nim()
else: showHelp()
break
of cmdEnd: break

View File

@@ -649,7 +649,7 @@ proc newLit*(f: float64): NimNode {.compileTime.} =
result = newNimNode(nnkFloat64Lit)
result.floatVal = f
when compiles(float128):
when declared(float128):
proc newLit*(f: float128): NimNode {.compileTime.} =
## produces a new float literal node.
result = newNimNode(nnkFloat128Lit)
@@ -976,6 +976,8 @@ proc newIfStmt*(branches: varargs[tuple[cond, body: NimNode]]):
## )
##
result = newNimNode(nnkIfStmt)
if len(branches) < 1:
error("If statement must have at least one branch")
for i in branches:
result.add(newTree(nnkElifBranch, i.cond, i.body))

View File

@@ -389,8 +389,6 @@ static N_INLINE(NI32, float32ToInt32)(float x) {
NIM_CHAR data[(length) + 1]; \
} name = {{length, (NI) ((NU)length | NIM_STRLIT_FLAG)}, str}
typedef struct TStringDesc* string;
/* declared size of a sequence/variable length array: */
#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER)
# define SEQ_DECL_SIZE /* empty is correct! */

View File

@@ -32,6 +32,18 @@ const useICC_builtins = defined(icc) and useBuiltins
const useVCC_builtins = defined(vcc) and useBuiltins
const arch64 = sizeof(int) == 8
template forwardImpl(impl, arg) {.dirty.} =
when sizeof(x) <= 4:
when x is SomeSignedInt:
impl(cast[uint32](x.int32))
else:
impl(x.uint32)
else:
when x is SomeSignedInt:
impl(cast[uint64](x.int64))
else:
impl(x.uint64)
# #### Pure Nim version ####
proc firstSetBit_nim(x: uint32): int {.inline, nosideeffect.} =
@@ -185,8 +197,7 @@ proc countSetBits*(x: SomeInteger): int {.inline, nosideeffect.} =
# TODO: figure out if ICC support _popcnt32/_popcnt64 on platform without POPCNT.
# like GCC and MSVC
when nimvm:
when sizeof(x) <= 4: result = countSetBits_nim(x.uint32)
else: result = countSetBits_nim(x.uint64)
result = forwardImpl(countSetBits_nim, x)
else:
when useGCC_builtins:
when sizeof(x) <= 4: result = builtin_popcount(x.cuint).int
@@ -216,8 +227,7 @@ proc parityBits*(x: SomeInteger): int {.inline, nosideeffect.} =
# Can be used a base if creating ASM version.
# https://stackoverflow.com/questions/21617970/how-to-check-if-value-has-even-parity-of-bits-or-odd
when nimvm:
when sizeof(x) <= 4: result = parity_impl(x.uint32)
else: result = parity_impl(x.uint64)
result = forwardImpl(parity_impl, x)
else:
when useGCC_builtins:
when sizeof(x) <= 4: result = builtin_parity(x.uint32).int
@@ -235,8 +245,7 @@ proc firstSetBit*(x: SomeInteger): int {.inline, nosideeffect.} =
when noUndefined:
if x == 0:
return 0
when sizeof(x) <= 4: result = firstSetBit_nim(x.uint32)
else: result = firstSetBit_nim(x.uint64)
result = forwardImpl(firstSetBit_nim, x)
else:
when noUndefined and not useGCC_builtins:
if x == 0:
@@ -270,8 +279,7 @@ proc fastLog2*(x: SomeInteger): int {.inline, nosideeffect.} =
if x == 0:
return -1
when nimvm:
when sizeof(x) <= 4: result = fastlog2_nim(x.uint32)
else: result = fastlog2_nim(x.uint64)
result = forwardImpl(fastlog2_nim, x)
else:
when useGCC_builtins:
when sizeof(x) <= 4: result = 31 - builtin_clz(x.uint32).int
@@ -302,8 +310,7 @@ proc countLeadingZeroBits*(x: SomeInteger): int {.inline, nosideeffect.} =
if x == 0:
return 0
when nimvm:
when sizeof(x) <= 4: result = sizeof(x)*8 - 1 - fastlog2_nim(x.uint32)
else: result = sizeof(x)*8 - 1 - fastlog2_nim(x.uint64)
result = sizeof(x)*8 - 1 - forwardImpl(fastlog2_nim, x)
else:
when useGCC_builtins:
when sizeof(x) <= 4: result = builtin_clz(x.uint32).int - (32 - sizeof(x)*8)

View File

@@ -320,6 +320,10 @@ gSomeReady.initSemaphore()
proc slave(w: ptr Worker) {.thread.} =
isSlave = true
while true:
if w.shutdown:
w.shutdown = false
atomicDec currentPoolSize
break
when declared(atomicStoreN):
atomicStoreN(addr(w.ready), true, ATOMIC_SEQ_CST)
else:
@@ -340,9 +344,6 @@ proc slave(w: ptr Worker) {.thread.} =
dec numSlavesRunning
if w.q.len != 0: w.cleanFlowVars
if w.shutdown:
w.shutdown = false
atomicDec currentPoolSize
proc distinguishedSlave(w: ptr Worker) {.thread.} =
while true:

View File

@@ -600,6 +600,7 @@ proc escapeJsonUnquoted*(s: string; result: var string) =
of '\b': result.add("\\b")
of '\f': result.add("\\f")
of '\t': result.add("\\t")
of '\v': result.add("\\v")
of '\r': result.add("\\r")
of '"': result.add("\\\"")
of '\0'..'\7': result.add("\\u000" & $ord(c))

View File

@@ -218,6 +218,9 @@ proc parseString(my: var JsonParser): TokKind =
of 't':
add(my.a, '\t')
inc(pos, 2)
of 'v':
add(my.a, '\v')
inc(pos, 2)
of 'u':
if my.rawStringLiterals:
add(my.a, 'u')

View File

@@ -175,7 +175,7 @@ proc `+`*(a, b: RunningStat): RunningStat =
(n*n) +
4.0*delta*(a.n.float*b.mom3 - b.n.float*a.mom3) / n
result.max = max(a.max, b.max)
result.min = max(a.min, b.min)
result.min = min(a.min, b.min)
proc `+=`*(a: var RunningStat, b: RunningStat) {.inline.} =
## add a second RunningStats `b` to `a`

View File

@@ -435,7 +435,7 @@ proc isNilOrWhitespace*(s: string): bool {.noSideEffect, procvar, rtl, extern: "
proc substrEq(s: string, pos: int, substr: string): bool =
var i = 0
var length = substr.len
while i < length and s[pos+i] == substr[i]:
while i < length and pos+i < s.len and s[pos+i] == substr[i]:
inc i
return i == length

View File

@@ -2023,7 +2023,7 @@ const
NimMinor* {.intdefine.}: int = 19
## is the minor number of Nim's version.
NimPatch* {.intdefine.}: int = 4
NimPatch* {.intdefine.}: int = 6
## is the patch number of Nim's version.
NimVersion*: string = $NimMajor & "." & $NimMinor & "." & $NimPatch
@@ -4321,25 +4321,6 @@ template doAssertRaises*(exception, code: untyped): typed =
if wrong:
raiseAssert(astToStr(exception) & " wasn't raised by:\n" & astToStr(code))
when defined(cpp) and appType != "lib" and
not defined(js) and not defined(nimscript) and
hostOS != "standalone" and not defined(noCppExceptions):
proc setTerminate(handler: proc() {.noconv.})
{.importc: "std::set_terminate", header: "<exception>".}
setTerminate proc() {.noconv.} =
# Remove ourself as a handler, reinstalling the default handler.
setTerminate(nil)
let ex = getCurrentException()
let trace = ex.getStackTrace()
when defined(genode):
# stderr not available by default, use the LOG session
echo trace & "Error: unhandled exception: " & ex.msg &
" [" & $ex.name & "]\n"
else:
stderr.write trace & "Error: unhandled exception: " & ex.msg &
" [" & $ex.name & "]\n"
quit 1
when not defined(js):
proc toOpenArray*[T](x: seq[T]; first, last: int): openarray[T] {.

View File

@@ -466,6 +466,41 @@ when defined(endb):
var
dbgAborting: bool # whether the debugger wants to abort
when defined(cpp) and appType != "lib" and
not defined(js) and not defined(nimscript) and
hostOS != "standalone" and not defined(noCppExceptions):
type
StdException {.importcpp: "std::exception", header: "<exception>".} = object
proc what(ex: StdException): cstring {.importcpp: "((char *)#.what())".}
proc setTerminate(handler: proc() {.noconv.})
{.importc: "std::set_terminate", header: "<exception>".}
setTerminate proc() {.noconv.} =
# Remove ourself as a handler, reinstalling the default handler.
setTerminate(nil)
var msg = "Unknown error in unexpected exception handler"
try:
raise
except Exception:
msg = currException.getStackTrace() & "Error: unhandled exception: " &
currException.msg & " [" & $currException.name & "]"
except StdException as e:
msg = "Error: unhandled cpp exception: " & $e.what()
except:
msg = "Error: unhandled unknown cpp exception"
when defined(genode):
# stderr not available by default, use the LOG session
echo msg
else:
writeToStdErr msg & "\n"
quit 1
when not defined(noSignalHandler) and not defined(useNimRtl):
proc signalHandler(sign: cint) {.exportc: "signalHandler", noconv.} =
template processSignal(s, action: untyped) {.dirty.} =

View File

@@ -1,5 +1,6 @@
discard """
output: '''(10, (20, ))'''
output: '''(10, (20, ))
42'''
"""
import strutils, sequtils
@@ -22,5 +23,17 @@ proc dosomething(): seq[TThing] =
result = @[TThing(data: 10, children: result)]
when isMainModule:
echo($dosomething()[0])
echo($dosomething()[0])
# bug #9844
proc f(v: int): int = v
type X = object
v: int
var x = X(v: 42)
x = X(v: f(x.v))
echo x.v

View File

@@ -8,3 +8,18 @@ proc foo[T](t: T) =
foo(123)
foo("baz")
# Empty type in template is correctly disambiguated
block:
template foo() =
type M = object
discard
var y = M()
foo()
type M = object
x: int
var x = M(x: 1)
doAssert(x.x == 1)

View File

@@ -0,0 +1,9 @@
discard """
targets: "cpp"
outputsub: "Error: unhandled unknown cpp exception"
exitcode: 1
"""
type Crap {.importcpp: "int".} = object
var c: Crap
raise c

View File

@@ -4,6 +4,8 @@ discard """
type
ESomething = object of Exception
ESomeOtherErr = object of Exception
ESomethingGen[T] = object of Exception
ESomethingGenRef[T] = ref object of Exception
proc genErrors(s: string) =
if s == "error!":
@@ -27,4 +29,17 @@ proc blah(): int =
echo blah()
# Issue #7845, raise generic exception
var x: ref ESomethingGen[int]
new(x)
try:
raise x
except ESomethingGen[int] as e:
discard
try:
raise new(ESomethingGenRef[int])
except ESomethingGenRef[int] as e:
discard
except:
discard

13
tests/js/tbasics.nim Normal file
View File

@@ -0,0 +1,13 @@
discard """
output: '''1'''
"""
# bug #10697
proc test2 =
var val = uint16(0)
var i = 0
if i < 2:
val += uint16(1)
echo int(val)
test2()

View File

@@ -1,10 +1,5 @@
discard """
file: "tbitops.nim"
output: "OK"
"""
import bitops
proc main() =
const U8 = 0b0011_0010'u8
const I8 = 0b0011_0010'i8
@@ -80,25 +75,6 @@ proc main() =
doAssert( U8.rotateLeftBits(3) == 0b10010001'u8)
doAssert( U8.rotateRightBits(3) == 0b0100_0110'u8)
static :
# test bitopts at compile time with vm
doAssert( U8.fastLog2 == 5)
doAssert( I8.fastLog2 == 5)
doAssert( U8.countLeadingZeroBits == 2)
doAssert( I8.countLeadingZeroBits == 2)
doAssert( U8.countTrailingZeroBits == 1)
doAssert( I8.countTrailingZeroBits == 1)
doAssert( U8.firstSetBit == 2)
doAssert( I8.firstSetBit == 2)
doAssert( U8.parityBits == 1)
doAssert( I8.parityBits == 1)
doAssert( U8.countSetBits == 3)
doAssert( I8.countSetBits == 3)
doAssert( U8.rotateLeftBits(3) == 0b10010001'u8)
doAssert( U8.rotateRightBits(3) == 0b0100_0110'u8)
template test_undefined_impl(ffunc: untyped; expected: int; is_static: bool) =
doAssert( ffunc(0'u8) == expected)
doAssert( ffunc(0'i8) == expected)
@@ -143,26 +119,8 @@ proc main() =
doAssert( U64A.rotateLeftBits(64) == U64A)
doAssert( U64A.rotateRightBits(64) == U64A)
static: # check for undefined behavior with rotate by zero.
doAssert( U8.rotateLeftBits(0) == U8)
doAssert( U8.rotateRightBits(0) == U8)
doAssert( U16.rotateLeftBits(0) == U16)
doAssert( U16.rotateRightBits(0) == U16)
doAssert( U32.rotateLeftBits(0) == U32)
doAssert( U32.rotateRightBits(0) == U32)
doAssert( U64A.rotateLeftBits(0) == U64A)
doAssert( U64A.rotateRightBits(0) == U64A)
# check for undefined behavior with rotate by integer width.
doAssert( U8.rotateLeftBits(8) == U8)
doAssert( U8.rotateRightBits(8) == U8)
doAssert( U16.rotateLeftBits(16) == U16)
doAssert( U16.rotateRightBits(16) == U16)
doAssert( U32.rotateLeftBits(32) == U32)
doAssert( U32.rotateRightBits(32) == U32)
doAssert( U64A.rotateLeftBits(64) == U64A)
doAssert( U64A.rotateRightBits(64) == U64A)
echo "OK"
main()
static:
# test everything on vm as well
main()

45
tests/vm/tbitops.nim Normal file
View File

@@ -0,0 +1,45 @@
discard """
output: ""
"""
import strutils
const x = [1'i32, -1, -10, 10, -10, 10, -20, 30, -40, 50, 7 shl 28, -(7 shl 28), 7 shl 28, -(7 shl 28)]
const y = [-1'i32, 1, -10, -10, 10, 10, -20, -30, 40, 50, 1 shl 30, 1 shl 30, -(1 shl 30), -(1 shl 30)]
const res_xor = block:
var tmp: seq[int64]
for i in 0 ..< x.len:
tmp.add(int64(x[i] xor y[i]))
tmp
const res_and = block:
var tmp: seq[int64]
for i in 0 ..< x.len:
tmp.add(int64(x[i] and y[i]))
tmp
const res_or = block:
var tmp: seq[int64]
for i in 0 ..< x.len:
tmp.add(int64(x[i] or y[i]))
tmp
const res_not = block:
var tmp: seq[int64]
for i in 0 ..< x.len:
tmp.add(not x[i])
tmp
let xx = x
let yy = y
for i in 0..<xx.len:
let z_xor = int64(xx[i] xor yy[i])
let z_and = int64(xx[i] and yy[i])
let z_or = int64(xx[i] or yy[i])
let z_not = int64(not xx[i])
doAssert(z_xor == res_xor[i], $i & ": " & $res_xor[i] & " " & $z_xor)
doAssert(z_and == res_and[i], $i & ": " & $res_and[i] & " " & $z_and)
doAssert(z_or == res_or[i], $i & ": " & $res_or[i] & " " & $z_or)
doAssert(z_not == res_not[i], $i & ": " & $res_not[i] & " " & $z_not)

View File

@@ -31,7 +31,7 @@ static:
assert str == "abc"
# #6086
import math, sequtils, future
import math, sequtils, sugar
block:
proc f: int =
@@ -148,3 +148,22 @@ static:
static:
doAssert foo().i == 1
# #10886
proc tor(): bool =
result = true
result = false or result
proc tand(): bool =
result = false
result = true and result
const
ctor = tor()
ctand = not tand()
static:
doAssert ctor
doAssert ctand

View File

@@ -8,6 +8,9 @@ const
mingw = "mingw$1-6.3.0.7z" % arch
url = r"https://nim-lang.org/download/" & mingw
var
interactive = true
type
DownloadResult = enum
Failure,
@@ -38,19 +41,28 @@ proc downloadMingw(): DownloadResult =
if cmd.len > 0:
if execShellCmd(cmd) != 0:
echo "download failed! ", cmd
openDefaultBrowser(url)
result = Manual
if interactive:
openDefaultBrowser(url)
result = Manual
else:
result = Failure
else:
if unzip(): result = Success
else:
openDefaultBrowser(url)
result = Manual
if interactive:
openDefaultBrowser(url)
result = Manual
else:
result = Failure
when defined(windows):
import registry
proc askBool(m: string): bool =
stdout.write m
if not interactive:
stdout.writeLine "y (non-interactive mode)"
return true
while true:
try:
let answer = stdin.readLine().normalize
@@ -67,6 +79,9 @@ when defined(windows):
proc askNumber(m: string; a, b: int): int =
stdout.write m
stdout.write " [" & $a & ".." & $b & "] "
if not interactive:
stdout.writeLine $a & " (non-interactive mode)"
return a
while true:
let answer = stdin.readLine()
try:
@@ -291,4 +306,6 @@ when isMainModule:
when defined(testdownload):
discard downloadMingw()
else:
if "-y" in commandLineParams():
interactive = false
main()

View File

@@ -54,6 +54,11 @@ proc execCleanPath*(cmd: string,
proc nimexec*(cmd: string) =
exec findNim() & " " & cmd
proc nimCompile*(input: string, outputDir = "bin", mode = "c", options = "") =
let output = outputDir / input.splitFile.name.exe
let cmd = findNim() & " " & mode & " -o:" & output & " " & options & " " & input
exec cmd
const
pdf = """
doc/manual.rst