Merge branch 'devel' into araq-better-codegen

This commit is contained in:
Andreas Rumpf
2017-09-23 20:07:30 +02:00
8 changed files with 133 additions and 8 deletions

View File

@@ -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,

View File

@@ -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)

View File

@@ -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

View File

@@ -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."

View File

@@ -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:

View File

@@ -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

View File

@@ -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:

18
tests/array/tarraylen.nim Normal file
View File

@@ -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)