From cf259fbd1c7e2642d00ed6decbceec353b53c84e Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 29 Dec 2017 20:01:49 +0100 Subject: [PATCH 01/23] fixes #6972 --- compiler/renderer.nim | 1 + compiler/sem.nim | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/renderer.nim b/compiler/renderer.nim index d4b401c02e..6735cc1ce2 100644 --- a/compiler/renderer.nim +++ b/compiler/renderer.nim @@ -719,6 +719,7 @@ proc gcase(g: var TSrcGen, n: PNode) = var c: TContext initContext(c) var length = sonsLen(n) + if length == 0: return var last = if n.sons[length-1].kind == nkElse: -2 else: -1 if longMode(g, n, 0, last): incl(c.flags, rfLongMode) putWithSpace(g, tkCase, "case") diff --git a/compiler/sem.nim b/compiler/sem.nim index ababbd303c..d2831827ad 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -74,7 +74,7 @@ proc fitNode(c: PContext, formal: PType, arg: PNode; info: TLineInfo): PNode = localError(arg.info, errExprXHasNoType, renderTree(arg, {renderNoComments})) # error correction: - result = copyNode(arg) + result = copyTree(arg) result.typ = formal else: result = indexTypesMatch(c, formal, arg.typ, arg) @@ -168,9 +168,9 @@ proc commonType*(x, y: PType): PType = proc endsInNoReturn(n: PNode): bool = # check if expr ends in raise exception or call of noreturn proc var it = n - while it.kind in {nkStmtList, nkStmtListExpr} and it.len > 0: + while it.kind in {nkStmtList, nkStmtListExpr} and it.len > 0: it = it.lastSon - result = it.kind == nkRaiseStmt or + result = it.kind == nkRaiseStmt or it.kind in nkCallKinds and it[0].kind == nkSym and sfNoReturn in it[0].sym.flags proc commonType*(x: PType, y: PNode): PType = From 29db57a804e03ac4d9d943ac7cf3966777fa5c8d Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 30 Dec 2017 00:29:53 +0100 Subject: [PATCH 02/23] fixes reported 'proc foo(): int = result' codegen problem --- compiler/semexprs.nim | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index a0f519820b..51e75e91fb 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1425,11 +1425,7 @@ proc semProcBody(c: PContext, n: PNode): PNode = openScope(c) result = semExpr(c, n) if c.p.resultSym != nil and not isEmptyType(result.typ): - # transform ``expr`` to ``result = expr``, but not if the expr is already - # ``result``: - if result.kind == nkSym and result.sym == c.p.resultSym: - discard - elif result.kind == nkNilLit: + if result.kind == nkNilLit: # or ImplicitlyDiscardable(result): # new semantic: 'result = x' triggers the void context result.typ = nil From 3073f08e4857b14a6bd1b0022fe45f461bf88171 Mon Sep 17 00:00:00 2001 From: Ruslan Mustakov Date: Sat, 30 Dec 2017 15:41:41 +0700 Subject: [PATCH 03/23] Add hasPendingOperations check to asyncdispatch.drain --- lib/pure/asyncdispatch.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index b62cf2e9bb..42ffa236c9 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -1487,7 +1487,7 @@ proc drain*(timeout = 500) = ## if there are no pending operations. In contrast to ``poll`` this ## processes as many events as are available. if runOnce(timeout): - while runOnce(0): discard + while hasPendingOperations() and runOnce(0): discard proc poll*(timeout = 500) = ## Waits for completion events and processes them. Raises ``ValueError`` From 41472f0e2827ee3e028db7faa76e368005728231 Mon Sep 17 00:00:00 2001 From: Parashurama Date: Wed, 23 Aug 2017 13:42:40 +0200 Subject: [PATCH 04/23] add support cast[integer] in VM --- compiler/vmgen.nim | 47 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 3790a8392f..17878b656b 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -30,7 +30,7 @@ import strutils, ast, astalgo, types, msgs, renderer, vmdef, trees, intsets, rodread, magicsys, options, lowerings - +import platform from os import splitFile when hasFFI: @@ -761,6 +761,49 @@ proc genCard(c: PCtx; n: PNode; dest: var TDest) = c.gABC(n, opcCard, dest, tmp) c.freeTemp(tmp) +proc genIntCast(c: PCtx; n: PNode; dest: var TDest) = + const allowedIntegers = {tyInt..tyInt64, tyUInt..tyUInt64, tyChar} + var signedIntegers = {tyInt8..tyInt32} + var unsignedIntegers = {tyUInt8..tyUInt32, tyChar} + let src = n.sons[1].typ.skipTypes(abstractRange)#.kind + let dst = n.sons[0].typ.skipTypes(abstractRange)#.kind + let src_size = src.getSize + + if platform.intSize < 8: + signedIntegers.incl(tyInt) + unsignedIntegers.incl(tyUInt) + if src_size == dst.getSize and src.kind in allowedIntegers and + dst.kind in allowedIntegers: + let tmp = c.genx(n.sons[1]) + var tmp2 = c.getTemp(n.sons[1].typ) + let tmp3 = c.getTemp(n.sons[1].typ) + if dest < 0: dest = c.getTemp(n[0].typ) + proc mkIntLit(ival: int): int = + result = genLiteral(c, newIntTypeNode(nkIntLit, ival, getSysType(tyInt))) + if src.kind in unsignedIntegers and dst.kind in signedIntegers: + # cast unsigned to signed integer of same size + # signedVal = (unsignedVal xor offset) -% offset + let offset = 1 shl (src_size * 8 - 1) + c.gABx(n, opcLdConst, tmp2, mkIntLit(offset)) + c.gABC(n, opcBitxorInt, tmp3, tmp, tmp2) + c.gABC(n, opcSubInt, dest, tmp3, tmp2) + elif src.kind in signedIntegers and dst.kind in unsignedIntegers: + # cast signed to unsigned integer of same size + # unsignedVal = (offset +% signedVal +% 1) and offset + let offset = (1 shl (src_size * 8)) - 1 + c.gABx(n, opcLdConst, tmp2, mkIntLit(offset)) + c.gABx(n, opcLdConst, dest, mkIntLit(offset+1)) + c.gABC(n, opcAddu, tmp3, tmp, dest) + c.gABC(n, opcNarrowU, tmp3, TRegister(src_size*8)) + c.gABC(n, opcBitandInt, dest, tmp3, tmp2) + else: + c.gABC(n, opcAsgnInt, dest, tmp) + c.freeTemp(tmp) + c.freeTemp(tmp2) + c.freeTemp(tmp3) + else: + globalError(n.info, errGenerated, "VM is only allowed to 'cast' between integers of same size") + proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) = case m of mAnd: c.genAndOr(n, opcFJmp, dest) @@ -1844,7 +1887,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) = if allowCast in c.features: genConv(c, n, n.sons[1], dest, opcCast) else: - globalError(n.info, errGenerated, "VM is not allowed to 'cast'") + genIntCast(c, n, dest) of nkTypeOfExpr: genTypeLit(c, n.typ, dest) of nkComesFrom: From 26a34d52a089f54ec6b073230742ed9894d8d197 Mon Sep 17 00:00:00 2001 From: Parashurama Date: Wed, 23 Aug 2017 13:44:22 +0200 Subject: [PATCH 05/23] add tests for integer casting in VM. --- tests/vm/tcastint.nim | 120 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 tests/vm/tcastint.nim diff --git a/tests/vm/tcastint.nim b/tests/vm/tcastint.nim new file mode 100644 index 0000000000..7b9ddd7d9f --- /dev/null +++ b/tests/vm/tcastint.nim @@ -0,0 +1,120 @@ +discard """ + file: "tcastint.nim" + output: "OK" +""" + +type + Dollar = distinct int + XCoord = distinct int32 + Digit = range[-9..0] + +# those are necessary for comparisons below. +proc `==`(x, y: Dollar): bool {.borrow.} +proc `==`(x, y: XCoord): bool {.borrow.} + +proc dummy[T](x: T): T = x + +proc test() = + let U8 = 0b1011_0010'u8 + let I8 = 0b1011_0010'i8 + let C8 = 0b1011_0010'u8.char + let C8_1 = 0b1011_0011'u8.char + let U16 = 0b10100111_00101000'u16 + let I16 = 0b10100111_00101000'i16 + let U32 = 0b11010101_10011100_11011010_01010000'u32 + let I32 = 0b11010101_10011100_11011010_01010000'i32 + let U64A = 0b11000100_00111111_01111100_10001010_10011001_01001000_01111010_00010001'u64 + let I64A = 0b11000100_00111111_01111100_10001010_10011001_01001000_01111010_00010001'i64 + let U64B = 0b00110010_11011101_10001111_00101000_00000000_00000000_00000000_00000000'u64 + let I64B = 0b00110010_11011101_10001111_00101000_00000000_00000000_00000000_00000000'i64 + when sizeof(int) == 8: + let UX = U64A.uint + let IX = I64A.int + elif sizeof(int) == 4: + let UX = U32.uint + let IX = I32.int + elif sizeof(int) == 2: + let UX = U16.uint + let IX = I16.int + else: + let UX = U8.uint + let IX = I8.int + + doAssert(cast[char](I8) == C8) + doAssert(cast[uint8](I8) == U8) + doAssert(cast[uint16](I16) == U16) + doAssert(cast[uint32](I32) == U32) + doAssert(cast[uint64](I64A) == U64A) + doAssert(cast[uint64](I64B) == U64B) + doAssert(cast[int8](U8) == I8) + doAssert(cast[int16](U16) == I16) + doAssert(cast[int32](U32) == I32) + doAssert(cast[int64](U64A) == I64A) + doAssert(cast[int64](U64B) == I64B) + doAssert(cast[uint](IX) == UX) + doAssert(cast[int](UX) == IX) + + doAssert(cast[char](I8 + 1) == C8_1) + doAssert(cast[uint8](I8 + 1) == U8 + 1) + doAssert(cast[uint16](I16 + 1) == U16 + 1) + doAssert(cast[uint32](I32 + 1) == U32 + 1) + doAssert(cast[uint64](I64A + 1) == U64A + 1) + doAssert(cast[uint64](I64B + 1) == U64B + 1) + doAssert(cast[int8](U8 + 1) == I8 + 1) + doAssert(cast[int16](U16 + 1) == I16 + 1) + doAssert(cast[int32](U32 + 1) == I32 + 1) + doAssert(cast[int64](U64A + 1) == I64A + 1) + doAssert(cast[int64](U64B + 1) == I64B + 1) + doAssert(cast[uint](IX + 1) == UX + 1) + doAssert(cast[int](UX + 1) == IX + 1) + + doAssert(cast[char](I8.dummy) == C8.dummy) + doAssert(cast[uint8](I8.dummy) == U8.dummy) + doAssert(cast[uint16](I16.dummy) == U16.dummy) + doAssert(cast[uint32](I32.dummy) == U32.dummy) + doAssert(cast[uint64](I64A.dummy) == U64A.dummy) + doAssert(cast[uint64](I64B.dummy) == U64B.dummy) + doAssert(cast[int8](U8.dummy) == I8.dummy) + doAssert(cast[int16](U16.dummy) == I16.dummy) + doAssert(cast[int32](U32.dummy) == I32.dummy) + doAssert(cast[int64](U64A.dummy) == I64A.dummy) + doAssert(cast[int64](U64B.dummy) == I64B.dummy) + doAssert(cast[uint](IX.dummy) == UX.dummy) + doAssert(cast[int](UX.dummy) == IX.dummy) + + + doAssert(cast[int64](if false: U64B else: 0'u64) == (if false: I64B else: 0'i64)) + + block: + let raw = 3 + let money = Dollar(raw) # this must be a variable, is otherwise constant folded. + doAssert(cast[int](money) == raw) + doAssert(cast[Dollar](raw) == money) + block: + let raw = 150'i32 + let position = XCoord(raw) # this must be a variable, is otherwise constant folded. + doAssert(cast[int32](position) == raw) + doAssert(cast[XCoord](raw) == position) + block: + let raw = -2 + let digit = Digit(raw) + doAssert(cast[int](digit) == raw) + doAssert(cast[Digit](raw) == digit) + + when defined nimvm: + doAssert(not compiles(cast[float](I64A))) + doAssert(not compiles(cast[float32](I64A))) + + doAssert(not compiles(cast[char](I64A))) + doAssert(not compiles(cast[uint16](I64A))) + doAssert(not compiles(cast[uint32](I64A))) + + doAssert(not compiles(cast[uint16](I8))) + doAssert(not compiles(cast[uint32](I8))) + doAssert(not compiles(cast[uint64](I8))) + +test() +static: + test() + +echo "OK" From 3714e2f8714e0a1bc1efbafa26696b708fe9a4b5 Mon Sep 17 00:00:00 2001 From: Zach Smith Date: Thu, 28 Dec 2017 14:10:27 -0500 Subject: [PATCH 06/23] Add compile-time paragraph to manual Includes a note in the manual entry for case statements clarifying that the branch values must be known at compile time. --- doc/manual/stmts.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/manual/stmts.txt b/doc/manual/stmts.txt index b24ec3b4a6..721b5cff81 100644 --- a/doc/manual/stmts.txt +++ b/doc/manual/stmts.txt @@ -296,6 +296,10 @@ empty ``discard`` statement should be used. For non ordinal types it is not possible to list every possible value and so these always require an ``else`` part. +As case statements perform compile-time exhaustiveness checks, the value in +every ``of`` branch must be known at compile time. This fact is also exploited +to generate more performant code. + As a special semantic extension, an expression in an ``of`` branch of a case statement may evaluate to a set or array constructor; the set or array is then expanded into a list of its elements: From a521f983921878e613c1b89f40c081eb5393055b Mon Sep 17 00:00:00 2001 From: Daniil Yarancev <21169548+Yardanico@users.noreply.github.com> Date: Sat, 30 Dec 2017 18:15:15 +0300 Subject: [PATCH 07/23] Add warnings about deprecation to times module (#7001) * Add warnings about deprecation to times module I've added warnings about some procedures being deprecated. Also I can't find what is the replacement for `getTimezone` proc, please help with that * Update times.nim * Update times.nim --- lib/pure/times.nim | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/pure/times.nim b/lib/pure/times.nim index 606acbc1c4..85988e5858 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -1352,25 +1352,35 @@ else: proc fromSeconds*(since1970: float): Time {.tags: [], raises: [], benign, deprecated.} = ## Takes a float which contains the number of seconds since the unix epoch and ## returns a time object. + ## + ## **Deprecated since v0.18.0:** use ``Time`` instead Time(since1970) proc fromSeconds*(since1970: int64): Time {.tags: [], raises: [], benign, deprecated.} = ## Takes an int which contains the number of seconds since the unix epoch and ## returns a time object. + ## + ## **Deprecated since v0.18.0:** use ``Time`` instead Time(since1970) proc toSeconds*(time: Time): float {.tags: [], raises: [], benign, deprecated.} = ## Returns the time in seconds since the unix epoch. + ## + ## **Deprecated since v0.18.0:** use ``float`` instead float(time) proc getLocalTime*(time: Time): DateTime {.tags: [], raises: [], benign, deprecated.} = ## Converts the calendar time `time` to broken-time representation, ## expressed relative to the user's specified time zone. + ## + ## **Deprecated since v0.18.0:** use ``local`` instead time.local proc getGMTime*(time: Time): DateTime {.tags: [], raises: [], benign, deprecated.} = ## Converts the calendar time `time` to broken-down time representation, - ## expressed in Coordinated Universal Time (UTC). + ## expressed in Coordinated Universal Time (UTC). + ## + ## **Deprecated since v0.18.0:** use ``utc`` instead time.utc proc getTimezone*(): int {.tags: [TimeEffect], raises: [], benign, deprecated.} = @@ -1468,4 +1478,4 @@ proc getDayOfWeekJulian*(day, month, year: int): WeekDay {.deprecated.} = y = year - a m = month + (12*a) - 2 d = (5 + day + y + (y div 4) + (31*m) div 12) mod 7 - result = d.WeekDay \ No newline at end of file + result = d.WeekDay From d1e10f9aa3e033414fb924e4f90736e46fde8256 Mon Sep 17 00:00:00 2001 From: Yuriy Glukhov Date: Sun, 31 Dec 2017 11:28:51 +0300 Subject: [PATCH 08/23] Fixed mutex usage in SharedList and SharedTable. Closes #6988 (#6990) --- lib/pure/collections/sharedlist.nim | 15 +++++++++++---- lib/pure/collections/sharedtables.nim | 20 +++++++++++++++----- lib/system/gc.nim | 2 +- lib/system/gc2.nim | 2 +- lib/system/gc_ms.nim | 2 +- tests/collections/ttables.nim | 3 ++- 6 files changed, 31 insertions(+), 13 deletions(-) diff --git a/lib/pure/collections/sharedlist.nim b/lib/pure/collections/sharedlist.nim index e93ceb02fc..b3e677b79c 100644 --- a/lib/pure/collections/sharedlist.nim +++ b/lib/pure/collections/sharedlist.nim @@ -73,10 +73,10 @@ proc add*[A](x: var SharedList[A]; y: A) = node.d[node.dataLen] = y inc(node.dataLen) -proc initSharedList*[A](): SharedList[A] = - initLock result.lock - result.head = nil - result.tail = nil +proc init*[A](t: var SharedList[A]) = + initLock t.lock + t.head = nil + t.tail = nil proc clear*[A](t: var SharedList[A]) = withLock(t): @@ -92,4 +92,11 @@ proc deinitSharedList*[A](t: var SharedList[A]) = clear(t) deinitLock t.lock +proc initSharedList*[A](): SharedList[A] {.deprecated.} = + ## Deprecated. Use `init` instead. + ## This is not posix compliant, may introduce undefined behavior. + initLock result.lock + result.head = nil + result.tail = nil + {.pop.} diff --git a/lib/pure/collections/sharedtables.nim b/lib/pure/collections/sharedtables.nim index 211a6ce6ac..4f311af874 100644 --- a/lib/pure/collections/sharedtables.nim +++ b/lib/pure/collections/sharedtables.nim @@ -192,19 +192,29 @@ proc del*[A, B](t: var SharedTable[A, B], key: A) = withLock t: delImpl() -proc initSharedTable*[A, B](initialSize=64): SharedTable[A, B] = +proc init*[A, B](t: var SharedTable[A, B], initialSize=64) = ## creates a new hash table that is empty. ## ## `initialSize` needs to be a power of two. If you need to accept runtime ## values for this you could use the ``nextPowerOfTwo`` proc from the ## `math `_ module or the ``rightSize`` proc from this module. assert isPowerOfTwo(initialSize) - result.counter = 0 - result.dataLen = initialSize - result.data = cast[KeyValuePairSeq[A, B]](allocShared0( + t.counter = 0 + t.dataLen = initialSize + t.data = cast[KeyValuePairSeq[A, B]](allocShared0( sizeof(KeyValuePair[A, B]) * initialSize)) - initLock result.lock + initLock t.lock proc deinitSharedTable*[A, B](t: var SharedTable[A, B]) = deallocShared(t.data) deinitLock t.lock + +proc initSharedTable*[A, B](initialSize=64): SharedTable[A, B] {.deprecated.} = + ## Deprecated. Use `init` instead. + ## This is not posix compliant, may introduce undefined behavior. + assert isPowerOfTwo(initialSize) + result.counter = 0 + result.dataLen = initialSize + result.data = cast[KeyValuePairSeq[A, B]](allocShared0( + sizeof(KeyValuePair[A, B]) * initialSize)) + initLock result.lock diff --git a/lib/system/gc.nim b/lib/system/gc.nim index 68bf5f6c2d..dac06119d9 100644 --- a/lib/system/gc.nim +++ b/lib/system/gc.nim @@ -318,7 +318,7 @@ proc initGC() = init(gch.marked) init(gch.additionalRoots) when hasThreadSupport: - gch.toDispose = initSharedList[pointer]() + init(gch.toDispose) when useMarkForDebug or useBackupGc: type diff --git a/lib/system/gc2.nim b/lib/system/gc2.nim index 4ecf3b2262..d57a01dc75 100644 --- a/lib/system/gc2.nim +++ b/lib/system/gc2.nim @@ -133,7 +133,7 @@ proc initGC() = init(gch.additionalRoots) init(gch.greyStack) when hasThreadSupport: - gch.toDispose = initSharedList[pointer]() + init(gch.toDispose) # Which color to use for new objects is tricky: When we're marking, # they have to be *white* so that everything is marked that is only diff --git a/lib/system/gc_ms.nim b/lib/system/gc_ms.nim index 272047bb7b..5fc48d848b 100644 --- a/lib/system/gc_ms.nim +++ b/lib/system/gc_ms.nim @@ -233,7 +233,7 @@ proc initGC() = init(gch.allocated) init(gch.marked) when hasThreadSupport: - gch.toDispose = initSharedList[pointer]() + init(gch.toDispose) proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: WalkOp) {.benign.} = var d = cast[ByteAddress](dest) diff --git a/tests/collections/ttables.nim b/tests/collections/ttables.nim index 2b8af5bd97..7fe4c79b13 100644 --- a/tests/collections/ttables.nim +++ b/tests/collections/ttables.nim @@ -213,7 +213,8 @@ block clearCountTableTest: assert t.len() == 0 block withKeyTest: - var t = initSharedTable[int, int]() + var t: SharedTable[int, int] + t.init() t.withKey(1) do (k: int, v: var int, pairExists: var bool): assert(v == 0) pairExists = true From 74fb3e6e6e68b45e37c9c0688cc561ef161ff62d Mon Sep 17 00:00:00 2001 From: GULPF Date: Sun, 31 Dec 2017 14:40:46 +0100 Subject: [PATCH 09/23] Improve deprecation comments in times module --- lib/pure/times.nim | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/pure/times.nim b/lib/pure/times.nim index 85988e5858..7df1d01782 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -1353,20 +1353,20 @@ proc fromSeconds*(since1970: float): Time {.tags: [], raises: [], benign, deprec ## Takes a float which contains the number of seconds since the unix epoch and ## returns a time object. ## - ## **Deprecated since v0.18.0:** use ``Time`` instead + ## **Deprecated since v0.18.0:** use ``fromUnix`` instead Time(since1970) proc fromSeconds*(since1970: int64): Time {.tags: [], raises: [], benign, deprecated.} = ## Takes an int which contains the number of seconds since the unix epoch and ## returns a time object. ## - ## **Deprecated since v0.18.0:** use ``Time`` instead + ## **Deprecated since v0.18.0:** use ``fromUnix`` instead Time(since1970) proc toSeconds*(time: Time): float {.tags: [], raises: [], benign, deprecated.} = ## Returns the time in seconds since the unix epoch. ## - ## **Deprecated since v0.18.0:** use ``float`` instead + ## **Deprecated since v0.18.0:** use ``toUnix`` instead float(time) proc getLocalTime*(time: Time): DateTime {.tags: [], raises: [], benign, deprecated.} = @@ -1385,6 +1385,9 @@ proc getGMTime*(time: Time): DateTime {.tags: [], raises: [], benign, deprecated proc getTimezone*(): int {.tags: [TimeEffect], raises: [], benign, deprecated.} = ## Returns the offset of the local (non-DST) timezone in seconds west of UTC. + ## + ## **Deprecated since v0.18.0:** use ``now().utcOffset`` to get the current + ## utc offset (including DST). when defined(JS): return newDate().getTimezoneOffset() * 60 elif defined(freebsd) or defined(netbsd) or defined(openbsd): From 42cff6e0c5d9a818ed2a788b2c4207ac389d3092 Mon Sep 17 00:00:00 2001 From: oltolm Date: Sun, 31 Dec 2017 14:49:42 +0100 Subject: [PATCH 10/23] add support for building GUI applications with TCC (#7003) --- compiler/extccomp.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index 5299b2dbf6..62990593d0 100644 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -253,7 +253,7 @@ compiler tcc: compilerExe: "tcc", cppCompiler: "", compileTmpl: "-c $options $include -o $objfile $file", - buildGui: "UNAVAILABLE!", + buildGui: "-Wl,-subsystem=gui", buildDll: " -shared", buildLib: "", # XXX: not supported yet linkerExe: "tcc", From 3f2636c76580c8a086df4255a17b077622434d7d Mon Sep 17 00:00:00 2001 From: Sergey Avseyev Date: Mon, 1 Jan 2018 02:39:55 +0300 Subject: [PATCH 11/23] Remove obsolete method analyzeAndConsolidateOutput (#6998) After the change, when stacktraces rendered in reversed order (most recent call first), this method removed all stacktraces in the test failures. --- tests/testament/tester.nim | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/tests/testament/tester.nim b/tests/testament/tester.nim index 69b640fa28..870f9f8656 100644 --- a/tests/testament/tester.nim +++ b/tests/testament/tester.nim @@ -290,20 +290,6 @@ proc compilerOutputTests(test: TTest, target: TTarget, given: var TSpec, if given.err == reSuccess: inc(r.passed) r.addResult(test, target, expectedmsg, givenmsg, given.err) -proc analyzeAndConsolidateOutput(s: string): string = - result = "" - let rows = s.splitLines - for i in 0 ..< rows.len: - if (let pos = find(rows[i], "Traceback (most recent call last)"); pos != -1): - result = substr(rows[i], pos) & "\n" - for i in i+1 ..< rows.len: - result.add rows[i] & "\n" - if not (rows[i] =~ peg"['(']+ '(' \d+ ')' \s+"): - return - elif (let pos = find(rows[i], "SIGSEGV: Illegal storage access."); pos != -1): - result = substr(rows[i], pos) - return - proc testSpec(r: var TResults, test: TTest, target = targetC) = let tname = test.name.addFileExt(".nim") #echo "TESTING ", tname @@ -376,8 +362,7 @@ proc testSpec(r: var TResults, test: TTest, target = targetC) = if exitCode != expected.exitCode: r.addResult(test, target, "exitcode: " & $expected.exitCode, "exitcode: " & $exitCode & "\n\nOutput:\n" & - analyzeAndConsolidateOutput(bufB), - reExitCodesDiffer) + bufB, reExitCodesDiffer) continue if bufB != expectedOut and expected.action != actionRunNoSpec: From 37dde55f8d4c4d9fd7a3968756aa4885c9dbda9a Mon Sep 17 00:00:00 2001 From: data-man Date: Tue, 2 Jan 2018 01:44:45 +0300 Subject: [PATCH 12/23] Add a shared collections to the docs --- doc/lib.rst | 4 ++++ web/website.ini | 1 + 2 files changed, 5 insertions(+) diff --git a/doc/lib.rst b/doc/lib.rst index 58dedc49c3..755c11899f 100644 --- a/doc/lib.rst +++ b/doc/lib.rst @@ -92,6 +92,10 @@ Collections and algorithms * `sequtils `_ This module implements operations for the built-in seq type which were inspired by functional programming languages. +* `sharedtables `_ + Nim shared hash table support. Contains shared tables. +* `sharedlist `_ + Nim shared linked list support. Contains shared singly linked list. String handling diff --git a/web/website.ini b/web/website.ini index 32b1936d56..273c3223d3 100644 --- a/web/website.ini +++ b/web/website.ini @@ -51,6 +51,7 @@ srcdoc2: "pure/ropes;pure/unidecode/unidecode;pure/xmldom;pure/xmldomparser" srcdoc2: "pure/xmlparser;pure/htmlparser;pure/xmltree;pure/colors;pure/mimetypes" srcdoc2: "pure/json;pure/base64;pure/scgi" srcdoc2: "pure/collections/tables;pure/collections/sets;pure/collections/lists" +srcdoc2: "pure/collections/sharedlist;pure/collections/sharedtables" srcdoc2: "pure/collections/intsets;pure/collections/queues;pure/collections/deques;pure/encodings" srcdoc2: "pure/events;pure/collections/sequtils;pure/cookies" srcdoc2: "pure/memfiles;pure/subexes;pure/collections/critbits" From 720c73e6d5c8b21a2d6d528a3a8947e498e9d1ad Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 3 Jan 2018 02:36:29 +0100 Subject: [PATCH 13/23] symbol files: fixes the logic for multi-methods --- compiler/cgen.nim | 8 ++++---- compiler/passes.nim | 4 ++-- compiler/sem.nim | 4 ++++ compiler/transf.nim | 2 +- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 217138dd04..573a14927a 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -1258,7 +1258,7 @@ proc resetModule*(m: BModule) = # indicate that this is now cached module # the cache will be invalidated by nullifying gModules - m.fromCache = true + #m.fromCache = true m.g = nil # we keep only the "merge info" information for the module @@ -1390,7 +1390,7 @@ proc writeModule(m: BModule, pending: bool) = # generate code for the init statements of the module: let cfile = getCFile(m) - if not m.fromCache or optForceFullMake in gGlobalOptions: + if m.rd == nil or optForceFullMake in gGlobalOptions: genInitCode(m) finishTypeDescriptions(m) if sfMainModule in m.module.flags: @@ -1465,10 +1465,10 @@ proc cgenWriteModules*(backend: RootRef, config: ConfigRef) = if g.generatedHeader != nil: finishModule(g.generatedHeader) while g.forwardedProcsCounter > 0: for m in cgenModules(g): - if not m.fromCache: + if m.rd == nil: finishModule(m) for m in cgenModules(g): - if m.fromCache: + if m.rd != nil: m.updateCachedModule else: m.writeModule(pending=true) diff --git a/compiler/passes.nim b/compiler/passes.nim index b84fe2f4d7..29b27627d3 100644 --- a/compiler/passes.nim +++ b/compiler/passes.nim @@ -18,7 +18,7 @@ import type TPassContext* = object of RootObj # the pass's context - fromCache*: bool # true if created by "openCached" + rd*: PRodReader # != nil if created by "openCached" PPassContext* = ref TPassContext @@ -118,7 +118,7 @@ proc openPassesCached(g: ModuleGraph; a: var TPassContextArray, module: PSym, if not isNil(gPasses[i].openCached): a[i] = gPasses[i].openCached(g, module, rd) if a[i] != nil: - a[i].fromCache = true + a[i].rd = rd else: a[i] = nil diff --git a/compiler/sem.nim b/compiler/sem.nim index d2831827ad..1098e9961f 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -501,6 +501,8 @@ proc myOpen(graph: ModuleGraph; module: PSym; cache: IdentCache): PPassContext = proc myOpenCached(graph: ModuleGraph; module: PSym; rd: PRodReader): PPassContext = result = myOpen(graph, module, rd.cache) + +proc replayMethodDefs(graph: ModuleGraph; rd: PRodReader) = for m in items(rd.methods): methodDef(graph, m, true) proc isImportSystemStmt(n: PNode): bool = @@ -607,6 +609,8 @@ proc myClose(graph: ModuleGraph; context: PPassContext, n: PNode): PNode = addCodeForGenerics(c, result) if c.module.ast != nil: result.add(c.module.ast) + if c.rd != nil: + replayMethodDefs(graph, c.rd) popOwner(c) popProcCon(c) if c.runnableExamples != nil: testExamples(c) diff --git a/compiler/transf.nim b/compiler/transf.nim index 6bc809fd20..f8f7f87464 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -914,7 +914,7 @@ proc processTransf(c: PTransf, n: PNode, owner: PSym): PNode = # Note: For interactive mode we cannot call 'passes.skipCodegen' and skip # this step! We have to rely that the semantic pass transforms too errornous # nodes into an empty node. - if c.fromCache or nfTransf in n.flags: return n + if c.rd != nil or nfTransf in n.flags: return n pushTransCon(c, newTransCon(owner)) result = PNode(transform(c, n)) popTransCon(c) From d5f539dc874ef3b7781eba465d382fd2dce58943 Mon Sep 17 00:00:00 2001 From: qqquinta Date: Wed, 3 Jan 2018 13:40:19 +0200 Subject: [PATCH 14/23] jsgen: bool genConv generates boolean values instead of numeric (#7016) --- compiler/jsgen.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 65a6a5dae9..dac2de7464 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -2051,10 +2051,10 @@ proc genConv(p: PProc, n: PNode, r: var TCompRes) = return case dest.kind: of tyBool: - r.res = "(($1)? 1:0)" % [r.res] + r.res = "(!!($1))" % [r.res] r.kind = resExpr of tyInt: - r.res = "($1|0)" % [r.res] + r.res = "(($1)|0)" % [r.res] else: # TODO: What types must we handle here? discard From 8941f5bd9c3f90f4879647fe86d875e46598ecbd Mon Sep 17 00:00:00 2001 From: Sergey Avseyev Date: Wed, 3 Jan 2018 14:41:10 +0300 Subject: [PATCH 15/23] Use safe limit for toRational(float, int) (#7021) Current limit `high(int32)` is not safe for 32-bit platforms and it will overflow (even when running its own test suite). Similar behaviour would be when try to set limit to `high(int64)` on 64-bit platforms. This change selects safe maximum value based on platform size of int. Safe maximum considered half of int size (for backward compatiblity). --- lib/pure/rationals.nim | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/pure/rationals.nim b/lib/pure/rationals.nim index 7fb24c26f3..7907b4e6c0 100644 --- a/lib/pure/rationals.nim +++ b/lib/pure/rationals.nim @@ -39,7 +39,7 @@ proc toRational*[T:SomeInteger](x: T): Rational[T] = result.num = x result.den = 1 -proc toRational*(x: float, n: int = high(int32)): Rational[int] = +proc toRational*(x: float, n: int = high(int) shr (sizeof(int) div 2 * 8)): Rational[int] = ## Calculates the best rational numerator and denominator ## that approximates to `x`, where the denominator is ## smaller than `n` (default is the largest possible @@ -323,8 +323,13 @@ when isMainModule: assert abs(toFloat(y) - 0.4814814814814815) < 1.0e-7 assert toInt(z) == 0 - assert toRational(0.98765432) == 2111111029 // 2137499919 - assert toRational(PI) == 817696623 // 260280919 + when sizeof(int) == 8: + assert toRational(0.98765432) == 2111111029 // 2137499919 + assert toRational(PI) == 817696623 // 260280919 + when sizeof(int) == 4: + assert toRational(0.98765432) == 80 // 81 + assert toRational(PI) == 355 // 113 + assert toRational(0.1) == 1 // 10 assert toRational(0.9) == 9 // 10 From ce983383fc1c22e4ade4cbfb591f86723ada51fc Mon Sep 17 00:00:00 2001 From: Dmitry Atamanov Date: Wed, 3 Jan 2018 14:42:09 +0300 Subject: [PATCH 16/23] Add a notes about integer casting to the changelog (#6996) --- changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/changelog.md b/changelog.md index 1c5848ce89..21ab2b87aa 100644 --- a/changelog.md +++ b/changelog.md @@ -187,3 +187,6 @@ let mySeq = @[1, 2, 1, 3, 1, 4] myCounter = mySeq.toCountTable() ``` + +- Added support for casting between integers of same bitsize in VM (compile time and nimscript). + This allow to among other things to reinterpret signed integers as unsigned. From 23c77ffa3aac532175ec289c5e8c31f4a28f1b2c Mon Sep 17 00:00:00 2001 From: Mathias Stearn Date: Wed, 3 Jan 2018 06:42:39 -0500 Subject: [PATCH 17/23] Faster nimgrep (#6983) * compile nimgrep with -d:release * nimgrep: only parse pattern once at startup --- koch.nim | 2 +- tools/nimgrep.nim | 46 +++++++++++++++++++--------------------------- 2 files changed, 20 insertions(+), 28 deletions(-) diff --git a/koch.nim b/koch.nim index 3ef9a340ab..7bb7ea4024 100644 --- a/koch.nim +++ b/koch.nim @@ -260,7 +260,7 @@ proc buildTools(latest: bool) = " nimsuggest/nimsuggest.nim" let nimgrepExe = "bin/nimgrep".exe - nimexec "c -o:" & nimgrepExe & " tools/nimgrep.nim" + nimexec "c -d:release -o:" & nimgrepExe & " tools/nimgrep.nim" when defined(windows): buildVccTool() #nimexec "c -o:" & ("bin/nimresolve".exe) & " tools/nimresolve.nim" diff --git a/tools/nimgrep.nim b/tools/nimgrep.nim index 8dff722ec0..e9c1b26fac 100644 --- a/tools/nimgrep.nim +++ b/tools/nimgrep.nim @@ -45,6 +45,9 @@ type TOptions = set[TOption] TConfirmEnum = enum ceAbort, ceYes, ceAll, ceNo, ceNone + Pattern = Regex | Peg + +using pattern: Pattern var filenames: seq[string] = @[] @@ -118,7 +121,7 @@ proc highlight(s, match, repl: string, t: tuple[first, last: int], stdout.write("\n") stdout.flushFile() -proc processFile(filename: string) = +proc processFile(pattern; filename: string) = var filenameShown = false template beforeHighlight = if not filenameShown and optVerbose notin options: @@ -135,18 +138,8 @@ proc processFile(filename: string) = if optVerbose in options: stdout.writeLine(filename) stdout.flushFile() - var pegp: Peg - var rep: Regex var result: string - if optRegex in options: - if {optIgnoreCase, optIgnoreStyle} * options != {}: - rep = re(pattern, {reExtended, reIgnoreCase}) - else: - rep = re(pattern) - else: - pegp = peg(pattern) - if optReplace in options: result = newStringOfCap(buffer.len) @@ -156,11 +149,7 @@ proc processFile(filename: string) = for j in 0..high(matches): matches[j] = "" var reallyReplace = true while i < buffer.len: - var t: tuple[first, last: int] - if optRegex notin options: - t = findBounds(buffer, pegp, matches, i) - else: - t = findBounds(buffer, rep, matches, i) + let t = findBounds(buffer, pattern, matches, i) if t.first < 0: break inc(line, countLines(buffer, i, t.first-1)) @@ -170,11 +159,7 @@ proc processFile(filename: string) = if optReplace notin options: highlight(buffer, wholeMatch, "", t, line, showRepl=false) else: - var r: string - if optRegex notin options: - r = replace(wholeMatch, pegp, replacement % matches) - else: - r = replace(wholeMatch, rep, replacement % matches) + let r = replace(wholeMatch, pattern, replacement % matches) if optConfirm in options: highlight(buffer, wholeMatch, r, t, line, showRepl=true) case confirm() @@ -246,17 +231,17 @@ proc styleInsensitive(s: string): string = addx() else: addx() -proc walker(dir: string) = +proc walker(pattern; dir: string) = for kind, path in walkDir(dir): case kind of pcFile: if extensions.len == 0 or path.hasRightExt(extensions): - processFile(path) + processFile(pattern, path) of pcDir: if optRecursive in options: - walker(path) + walker(pattern, path) else: discard - if existsFile(dir): processFile(dir) + if existsFile(dir): processFile(pattern, dir) proc writeHelp() = stdout.write(Usage) @@ -332,11 +317,18 @@ else: pattern = "\\y " & pattern elif optIgnoreCase in options: pattern = "\\i " & pattern + let pegp = peg(pattern) + for f in items(filenames): + walker(pegp, f) else: + var reflags = {reStudy, reExtended} if optIgnoreStyle in options: pattern = styleInsensitive(pattern) if optWord in options: pattern = r"\b (:?" & pattern & r") \b" - for f in items(filenames): - walker(f) + if {optIgnoreCase, optIgnoreStyle} * options != {}: + reflags.incl reIgnoreCase + let rep = re(pattern, reflags) + for f in items(filenames): + walker(rep, f) From 22cc7c62e5f1c22e0eda1037a6587153ffa6badf Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Wed, 3 Jan 2018 11:46:55 +0000 Subject: [PATCH 18/23] Fixes `times` module compilation on cpp backend. (#7004) --- lib/posix/posix_other.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/posix/posix_other.nim b/lib/posix/posix_other.nim index e552bf807e..01bc1c1e5e 100644 --- a/lib/posix/posix_other.nim +++ b/lib/posix/posix_other.nim @@ -34,7 +34,7 @@ type {.deprecated: [TSocketHandle: SocketHandle].} type - Time* {.importc: "time_t", header: "".} = distinct int + Time* {.importc: "time_t", header: "".} = distinct clong Timespec* {.importc: "struct timespec", header: "", final, pure.} = object ## struct timespec From bbfe6e81ad9a09fc57710809d5325e13a8c95cbe Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Wed, 3 Jan 2018 09:56:35 -0200 Subject: [PATCH 19/23] Add newSeqUninitialized, closes #6401 (#6402) --- lib/system.nim | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/system.nim b/lib/system.nim index 85643891ba..4d86107372 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -743,6 +743,18 @@ proc newSeqOfCap*[T](cap: Natural): seq[T] {. ## ``cap``. discard +when not defined(JS): + proc newSeqUninitialized*[T: SomeNumber](len: Natural): seq[T] = + ## creates a new sequence of type ``seq[T]`` with length ``len``. + ## + ## Only available for numbers types. Note that the sequence will be + ## uninitialized. After the creation of the sequence you should assign + ## entries to the sequence instead of adding them. + + result = newSeqOfCap[T](len) + var s = cast[PGenericSeq](result) + s.len = len + proc len*[TOpenArray: openArray|varargs](x: TOpenArray): int {. magic: "LengthOpenArray", noSideEffect.} proc len*(x: string): int {.magic: "LengthStr", noSideEffect.} From e593fef3206c359344c93bf7a3716da644f1906f Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 3 Jan 2018 13:24:20 +0100 Subject: [PATCH 20/23] memfiles: better error checking for Windows; refs #6361 --- lib/pure/memfiles.nim | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim index 9b2d252675..5c73381ffb 100644 --- a/lib/pure/memfiles.nim +++ b/lib/pure/memfiles.nim @@ -257,10 +257,13 @@ proc close*(f: var MemFile) = when defined(windows): if f.wasOpened: error = unmapViewOfFile(f.mem) == 0 - lastErr = osLastError() - error = (closeHandle(f.mapHandle) == 0) or error - if f.fHandle != INVALID_HANDLE_VALUE: - error = (closeHandle(f.fHandle) == 0) or error + if not error: + error = closeHandle(f.mapHandle) == 0 + if not error and f.fHandle != INVALID_HANDLE_VALUE: + discard closeHandle(f.fHandle) + f.fHandle = INVALID_HANDLE_VALUE + if error: + lastErr = osLastError() else: error = munmap(f.mem, f.size) != 0 lastErr = osLastError() From 8bcaadc9e4c10aad17339f9cea69418dd5d2bdf8 Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 3 Jan 2018 13:31:03 +0100 Subject: [PATCH 21/23] memfiles: enable test; refs #6361 --- tests/stdlib/tmemfiles2.nim | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/stdlib/tmemfiles2.nim b/tests/stdlib/tmemfiles2.nim index 665e92e8a2..7ea94cffc5 100644 --- a/tests/stdlib/tmemfiles2.nim +++ b/tests/stdlib/tmemfiles2.nim @@ -1,10 +1,8 @@ discard """ file: "tmemfiles2.nim" - disabled: true output: '''Full read size: 20 Half read size: 10 Data: Hello''' """ -# doesn't work on windows. fmReadWrite doesn't create a file. import memfiles, os var mm, mm_full, mm_half: MemFile From 30d182e5d6a8a64f637b486e507e7e5e4a1662d9 Mon Sep 17 00:00:00 2001 From: GULPF Date: Wed, 3 Jan 2018 23:54:36 +0100 Subject: [PATCH 22/23] Unexport epochday procs (#7024) --- lib/pure/times.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pure/times.nim b/lib/pure/times.nim index 7df1d01782..42e89e7cee 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -176,7 +176,7 @@ proc assertValidDate(monthday: MonthdayRange, month: Month, year: int) {.inline. assert monthday <= getDaysInMonth(month, year), $year & "-" & $ord(month) & "-" & $monthday & " is not a valid date" -proc toEpochDay*(monthday: MonthdayRange, month: Month, year: int): int64 = +proc toEpochDay(monthday: MonthdayRange, month: Month, year: int): int64 = ## Get the epoch day from a year/month/day date. ## The epoch day is the number of days since 1970/01/01 (it might be negative). assertValidDate monthday, month, year @@ -191,7 +191,7 @@ proc toEpochDay*(monthday: MonthdayRange, month: Month, year: int): int64 = let doe = yoe * 365 + yoe div 4 - yoe div 100 + doy return era * 146097 + doe - 719468 -proc fromEpochDay*(epochday: int64): tuple[monthday: MonthdayRange, month: Month, year: int] = +proc fromEpochDay(epochday: int64): tuple[monthday: MonthdayRange, month: Month, year: int] = ## Get the year/month/day date from a epoch day. ## The epoch day is the number of days since 1970/01/01 (it might be negative). # Based on http://howardhinnant.github.io/date_algorithms.html From 05e3a06b6e33f96b0a7a102270d3493eea9ebc1f Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 4 Jan 2018 00:19:04 +0100 Subject: [PATCH 23/23] nimbase.h: make 'endif' nesting correct --- lib/nimbase.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/nimbase.h b/lib/nimbase.h index b12d8e34dd..31075bbd2f 100644 --- a/lib/nimbase.h +++ b/lib/nimbase.h @@ -400,11 +400,11 @@ typedef struct TStringDesc* string; // NAN definition copied from math.h included in the Windows SDK version 10.0.14393.0 #ifndef NAN -#ifndef _HUGE_ENUF -#define _HUGE_ENUF 1e+300 // _HUGE_ENUF*_HUGE_ENUF must overflow -#endif -#define NAN_INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF)) -#define NAN ((float)(NAN_INFINITY * 0.0F)) +# ifndef _HUGE_ENUF +# define _HUGE_ENUF 1e+300 // _HUGE_ENUF*_HUGE_ENUF must overflow +# endif +# define NAN_INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF)) +# define NAN ((float)(NAN_INFINITY * 0.0F)) #endif #ifndef INF @@ -482,7 +482,6 @@ static inline void GCGuard (void *ptr) { asm volatile ("" :: "X" (ptr)); } On disagreement, your C compiler will say something like: "error: 'Nim_and_C_compiler_disagree_on_target_architecture' declared as an array with a negative size" */ typedef int Nim_and_C_compiler_disagree_on_target_architecture[sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8 ? 1 : -1]; -#endif #ifdef __cplusplus # define NIM_EXTERNC extern "C" @@ -509,3 +508,5 @@ extern Libc::Env *genodeEnv; /* Compile with -d:checkAbi and a sufficiently C11:ish compiler to enable */ #define NIM_CHECK_SIZE(typ, sz) \ _Static_assert(sizeof(typ) == sz, "Nim & C disagree on type size") + +#endif /* NIMBASE_H */