diff options
-rw-r--r-- | compiler/ast.nim | 2 | ||||
-rw-r--r-- | compiler/semfold.nim | 2 | ||||
-rw-r--r-- | doc/manual/generics.txt | 6 | ||||
-rw-r--r-- | lib/pure/collections/sets.nim | 98 | ||||
-rw-r--r-- | lib/pure/nativesockets.nim | 4 | ||||
-rw-r--r-- | lib/system.nim | 2 | ||||
-rw-r--r-- | lib/system/nimscript.nim | 9 | ||||
-rw-r--r-- | tests/array/tarraylen.nim | 18 |
8 files changed, 133 insertions, 8 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index e3caa5d86..6e87959bf 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -631,7 +631,7 @@ type mPointer, mEmptySet, mIntSetBaseType, mNil, mExpr, mStmt, mTypeDesc, mVoidType, mPNimrodNode, mShared, mGuarded, mLock, mSpawn, mDeepCopy, mIsMainModule, mCompileDate, mCompileTime, mProcCall, - mCpuEndian, mHostOS, mHostCPU, mAppType, + mCpuEndian, mHostOS, mHostCPU, mBuildOS, mBuildCPU, mAppType, mNaN, mInf, mNegInf, mCompileOption, mCompileOptionArg, mNLen, mNChild, mNSetChild, mNAdd, mNAddMultiple, mNDel, mNKind, diff --git a/compiler/semfold.nim b/compiler/semfold.nim index 84cb0071f..9733564e7 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -616,6 +616,8 @@ proc getConstExpr(m: PSym, n: PNode): PNode = of mCpuEndian: result = newIntNodeT(ord(CPU[targetCPU].endian), n) of mHostOS: result = newStrNodeT(toLowerAscii(platform.OS[targetOS].name), n) of mHostCPU: result = newStrNodeT(platform.CPU[targetCPU].name.toLowerAscii, n) + of mBuildOS: result = newStrNodeT(toLowerAscii(platform.OS[platform.hostOS].name), n) + of mBuildCPU: result = newStrNodeT(platform.CPU[platform.hostCPU].name.toLowerAscii, n) of mAppType: result = getAppType(n) of mNaN: result = newFloatNodeT(NaN, n) of mInf: result = newFloatNodeT(Inf, n) diff --git a/doc/manual/generics.txt b/doc/manual/generics.txt index 87fcb7828..cceea33c0 100644 --- a/doc/manual/generics.txt +++ b/doc/manual/generics.txt @@ -633,6 +633,9 @@ the ``vtptr`` magic produced types bound to ``ptr`` types. Symbol lookup in generics ------------------------- +Open and Closed symbols +~~~~~~~~~~~~~~~~~~~~~~~ + The symbol binding rules in generics are slightly subtle: There are "open" and "closed" symbols. A "closed" symbol cannot be re-bound in the instantiation context, an "open" symbol can. Per default overloaded symbols are open @@ -658,6 +661,9 @@ the ``Index`` type is defined *after* the ``==`` for tuples; yet the example compiles as the instantiation takes the currently defined symbols into account too. +Mixin statement +--------------- + A symbol can be forced to be open by a `mixin`:idx: declaration: .. code-block:: nim diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim index d51a5c388..dbdf17514 100644 --- a/lib/pure/collections/sets.nim +++ b/lib/pure/collections/sets.nim @@ -287,8 +287,6 @@ proc exclImpl[A](s: var HashSet[A], key: A) : bool {. inline .} = if i >= 0: result = false - s.data[i].hcode = 0 - s.data[i].key = default(type(s.data[i].key)) dec(s.counter) while true: # KnuthV3 Algo6.4R adapted for i=i+1 instead of i=i-1 var j = i # The correctness of this depends on (h+1) in nextTry, @@ -300,7 +298,7 @@ proc exclImpl[A](s: var HashSet[A], key: A) : bool {. inline .} = if isEmpty(s.data[i].hcode): # end of collision cluster; So all done return r = s.data[i].hcode and msk # "home" location of key@i - shallowCopy(s.data[j], s.data[i]) # data[j] will be marked EMPTY next loop + shallowCopy(s.data[j], s.data[i]) # data[i] will be marked EMPTY next loop proc missingOrExcl*[A](s: var HashSet[A], key: A): bool = ## Excludes `key` in the set `s` and tells if `key` was removed from `s`. @@ -662,9 +660,12 @@ proc card*[A](s: OrderedSet[A]): int {.inline.} = template forAllOrderedPairs(yieldStmt: untyped) {.dirty.} = var h = s.first + var idx = 0 while h >= 0: var nxt = s.data[h].next - if isFilled(s.data[h].hcode): yieldStmt + if isFilled(s.data[h].hcode): + yieldStmt + inc(idx) h = nxt iterator items*[A](s: OrderedSet[A]): A = @@ -689,6 +690,11 @@ iterator items*[A](s: OrderedSet[A]): A = forAllOrderedPairs: yield s.data[h].key +iterator pairs*[A](s: OrderedSet[A]): tuple[a: int, b: A] = + assert s.isValid, "The set needs to be initialized" + forAllOrderedPairs: + yield (idx, s.data[h].key) + proc rawGetKnownHC[A](s: OrderedSet[A], key: A, hc: Hash): int {.inline.} = rawGetKnownHCImpl() @@ -760,6 +766,67 @@ proc incl*[A](s: var HashSet[A], other: OrderedSet[A]) = assert other.isValid, "The set `other` needs to be initialized." for item in other: incl(s, item) +proc exclImpl[A](s: var OrderedSet[A], key: A) : bool {. inline .} = + assert s.isValid, "The set needs to be initialized." + var hc: Hash + var i = rawGet(s, key, hc) + var msk = high(s.data) + result = true + + if i >= 0: + result = false + # Fix ordering + if s.first == i: + s.first = s.data[i].next + else: + var itr = s.first + while true: + if (s.data[itr].next == i): + s.data[itr].next = s.data[i].next + if s.last == i: + s.last = itr + break + itr = s.data[itr].next + + dec(s.counter) + while true: # KnuthV3 Algo6.4R adapted for i=i+1 instead of i=i-1 + var j = i # The correctness of this depends on (h+1) in nextTry, + var r = j # though may be adaptable to other simple sequences. + s.data[i].hcode = 0 # mark current EMPTY + s.data[i].key = default(type(s.data[i].key)) + s.data[i].next = 0 + doWhile((i >= r and r > j) or (r > j and j > i) or (j > i and i >= r)): + i = (i + 1) and msk # increment mod table size + if isEmpty(s.data[i].hcode): # end of collision cluster; So all done + return + r = s.data[i].hcode and msk # "home" location of key@i + shallowCopy(s.data[j], s.data[i]) # data[i] will be marked EMPTY next loop + +proc missingOrExcl*[A](s: var OrderedSet[A], key: A): bool = + ## Excludes `key` in the set `s` and tells if `key` was removed from `s`. Efficiency: O(n). + ## + ## The difference with regards to the `excl() <#excl,TOrderedSet[A],A>`_ proc is + ## that this proc returns `true` if `key` was not present in `s`. Example: + ## + ## .. code-block:: + ## var s = toOrderedSet([2, 3, 6, 7]) + ## assert s.missingOrExcl(4) == true + ## assert s.missingOrExcl(6) == false + exclImpl(s, key) + + +proc excl*[A](s: var OrderedSet[A], key: A) = + ## Excludes `key` from the set `s`. Efficiency: O(n). + ## + ## This doesn't do anything if `key` is not found in `s`. Example: + ## + ## .. code-block:: + ## var s = toOrderedSet([2, 3, 6, 7]) + ## s.excl(2) + ## s.excl(2) + ## assert s.len == 3 + discard exclImpl(s, key) + proc containsOrIncl*[A](s: var OrderedSet[A], key: A): bool = ## Includes `key` in the set `s` and tells if `key` was added to `s`. ## @@ -986,6 +1053,24 @@ when isMainModule and not defined(release): assert a.len == b.card assert a.len == 2 + block setPairsIterator: + var s = toOrderedSet([1, 3, 5, 7]) + var items = newSeq[tuple[a: int, b: int]]() + for idx, item in s: items.add((idx, item)) + assert items == @[(0, 1), (1, 3), (2, 5), (3, 7)] + + block exclusions: + var s = toOrderedSet([1, 2, 3, 6, 7, 4]) + + s.excl(3) + s.excl(3) + s.excl(1) + s.excl(4) + + var items = newSeq[int]() + for item in s: items.add item + assert items == @[2, 6, 7] + #block orderedSetIterator: # var a = initOrderedSet[int]() # for value in [9, 2, 1, 5, 1, 8, 4, 2]: @@ -1030,6 +1115,11 @@ when isMainModule and not defined(release): if s <= i or mustRehash(s, i): echo "performance issue: rightSize() will not elide enlarge() at ", i + block missingOrExcl: + var s = toOrderedSet([2, 3, 6, 7]) + assert s.missingOrExcl(4) == true + assert s.missingOrExcl(6) == false + when not defined(testing): echo "Micro tests run successfully." diff --git a/lib/pure/nativesockets.nim b/lib/pure/nativesockets.nim index 1a62c0bf6..98fc62a3b 100644 --- a/lib/pure/nativesockets.nim +++ b/lib/pure/nativesockets.nim @@ -498,7 +498,7 @@ proc getLocalAddr*(socket: SocketHandle, domain: Domain): (string, Port) = # Cannot use INET6_ADDRSTRLEN here, because it's a C define. var buf: array[64, char] if inet_ntop(name.sin6_family.cint, - addr name, buf.cstring, sizeof(buf).int32).isNil: + addr name.sin6_addr, buf.cstring, sizeof(buf).int32).isNil: raiseOSError(osLastError()) result = ($buf, Port(nativesockets.ntohs(name.sin6_port))) else: @@ -534,7 +534,7 @@ proc getPeerAddr*(socket: SocketHandle, domain: Domain): (string, Port) = # Cannot use INET6_ADDRSTRLEN here, because it's a C define. var buf: array[64, char] if inet_ntop(name.sin6_family.cint, - addr name, buf.cstring, sizeof(buf).int32).isNil: + addr name.sin6_addr, buf.cstring, sizeof(buf).int32).isNil: raiseOSError(osLastError()) result = ($buf, Port(nativesockets.ntohs(name.sin6_port))) else: diff --git a/lib/system.nim b/lib/system.nim index cc5ef9810..61d79bac3 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -717,7 +717,7 @@ proc len*[TOpenArray: openArray|varargs](x: TOpenArray): int {. magic: "LengthOpenArray", noSideEffect.} proc len*(x: string): int {.magic: "LengthStr", noSideEffect.} proc len*(x: cstring): int {.magic: "LengthStr", noSideEffect.} -proc len*[I, T](x: array[I, T]): int {.magic: "LengthArray", noSideEffect.} +proc len*(x: (type array)|array): int {.magic: "LengthArray", noSideEffect.} proc len*[T](x: seq[T]): int {.magic: "LengthSeq", noSideEffect.} ## returns the length of an array, an openarray, a sequence or a string. ## This is roughly the same as ``high(T)-low(T)+1``, but its resulting type is diff --git a/lib/system/nimscript.nim b/lib/system/nimscript.nim index 73bb91fef..f5b9cf3ed 100644 --- a/lib/system/nimscript.nim +++ b/lib/system/nimscript.nim @@ -11,6 +11,15 @@ # Nim's configuration system now uses Nim for scripting. This module provides # a few things that are required for this to work. +const + buildOS* {.magic: "BuildOS".}: string = "" + ## The OS this build is running on. Can be different from ``system.hostOS`` + ## for cross compilations. + + buildCPU* {.magic: "BuildCPU".}: string = "" + ## The CPU this build is running on. Can be different from ``system.hostCPU`` + ## for cross compilations. + template builtin = discard # We know the effects better than the compiler: diff --git a/tests/array/tarraylen.nim b/tests/array/tarraylen.nim new file mode 100644 index 000000000..e9612de58 --- /dev/null +++ b/tests/array/tarraylen.nim @@ -0,0 +1,18 @@ +discard """ + output: "" +""" +var a: array[0, int] +doAssert a.len == 0 +doAssert array[0..0, int].len == 1 +doAssert array[0..0, int]([1]).len == 1 +doAssert array[1..1, int].len == 1 +doAssert array[1..1, int]([1]).len == 1 +doAssert array[2, int].len == 2 +doAssert array[2, int]([1, 2]).len == 2 +doAssert array[1..3, int].len == 3 +doAssert array[1..3, int]([1, 2, 3]).len == 3 +doAssert array[0..2, int].len == 3 +doAssert array[0..2, int]([1, 2, 3]).len == 3 +doAssert array[-2 .. -2, int].len == 1 +doAssert([1, 2, 3].len == 3) +doAssert([42].len == 1) \ No newline at end of file |