Merge branch 'devel' into araq-better-codegen

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

View file

@ -631,7 +631,7 @@ type
mPointer, mEmptySet, mIntSetBaseType, mNil, mExpr, mStmt, mTypeDesc, mPointer, mEmptySet, mIntSetBaseType, mNil, mExpr, mStmt, mTypeDesc,
mVoidType, mPNimrodNode, mShared, mGuarded, mLock, mSpawn, mDeepCopy, mVoidType, mPNimrodNode, mShared, mGuarded, mLock, mSpawn, mDeepCopy,
mIsMainModule, mCompileDate, mCompileTime, mProcCall, mIsMainModule, mCompileDate, mCompileTime, mProcCall,
mCpuEndian, mHostOS, mHostCPU, mAppType, mCpuEndian, mHostOS, mHostCPU, mBuildOS, mBuildCPU, mAppType,
mNaN, mInf, mNegInf, mNaN, mInf, mNegInf,
mCompileOption, mCompileOptionArg, mCompileOption, mCompileOptionArg,
mNLen, mNChild, mNSetChild, mNAdd, mNAddMultiple, mNDel, mNKind, 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 mCpuEndian: result = newIntNodeT(ord(CPU[targetCPU].endian), n)
of mHostOS: result = newStrNodeT(toLowerAscii(platform.OS[targetOS].name), n) of mHostOS: result = newStrNodeT(toLowerAscii(platform.OS[targetOS].name), n)
of mHostCPU: result = newStrNodeT(platform.CPU[targetCPU].name.toLowerAscii, 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 mAppType: result = getAppType(n)
of mNaN: result = newFloatNodeT(NaN, n) of mNaN: result = newFloatNodeT(NaN, n)
of mInf: result = newFloatNodeT(Inf, 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 Symbol lookup in generics
------------------------- -------------------------
Open and Closed symbols
~~~~~~~~~~~~~~~~~~~~~~~
The symbol binding rules in generics are slightly subtle: There are "open" and 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 "closed" symbols. A "closed" symbol cannot be re-bound in the instantiation
context, an "open" symbol can. Per default overloaded symbols are open 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 compiles as the instantiation takes the currently defined symbols into account
too. too.
Mixin statement
---------------
A symbol can be forced to be open by a `mixin`:idx: declaration: A symbol can be forced to be open by a `mixin`:idx: declaration:
.. code-block:: nim .. code-block:: nim

View file

@ -287,8 +287,6 @@ proc exclImpl[A](s: var HashSet[A], key: A) : bool {. inline .} =
if i >= 0: if i >= 0:
result = false result = false
s.data[i].hcode = 0
s.data[i].key = default(type(s.data[i].key))
dec(s.counter) dec(s.counter)
while true: # KnuthV3 Algo6.4R adapted for i=i+1 instead of i=i-1 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 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 if isEmpty(s.data[i].hcode): # end of collision cluster; So all done
return return
r = s.data[i].hcode and msk # "home" location of key@i 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 = proc missingOrExcl*[A](s: var HashSet[A], key: A): bool =
## Excludes `key` in the set `s` and tells if `key` was removed from `s`. ## 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.} = template forAllOrderedPairs(yieldStmt: untyped) {.dirty.} =
var h = s.first var h = s.first
var idx = 0
while h >= 0: while h >= 0:
var nxt = s.data[h].next var nxt = s.data[h].next
if isFilled(s.data[h].hcode): yieldStmt if isFilled(s.data[h].hcode):
yieldStmt
inc(idx)
h = nxt h = nxt
iterator items*[A](s: OrderedSet[A]): A = iterator items*[A](s: OrderedSet[A]): A =
@ -689,6 +690,11 @@ iterator items*[A](s: OrderedSet[A]): A =
forAllOrderedPairs: forAllOrderedPairs:
yield s.data[h].key 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.} = proc rawGetKnownHC[A](s: OrderedSet[A], key: A, hc: Hash): int {.inline.} =
rawGetKnownHCImpl() 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." assert other.isValid, "The set `other` needs to be initialized."
for item in other: incl(s, item) 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 = proc containsOrIncl*[A](s: var OrderedSet[A], key: A): bool =
## Includes `key` in the set `s` and tells if `key` was added to `s`. ## 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 == b.card
assert a.len == 2 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: #block orderedSetIterator:
# var a = initOrderedSet[int]() # var a = initOrderedSet[int]()
# for value in [9, 2, 1, 5, 1, 8, 4, 2]: # 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): if s <= i or mustRehash(s, i):
echo "performance issue: rightSize() will not elide enlarge() at ", 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): when not defined(testing):
echo "Micro tests run successfully." 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. # Cannot use INET6_ADDRSTRLEN here, because it's a C define.
var buf: array[64, char] var buf: array[64, char]
if inet_ntop(name.sin6_family.cint, 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()) raiseOSError(osLastError())
result = ($buf, Port(nativesockets.ntohs(name.sin6_port))) result = ($buf, Port(nativesockets.ntohs(name.sin6_port)))
else: else:
@ -534,7 +534,7 @@ proc getPeerAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
# Cannot use INET6_ADDRSTRLEN here, because it's a C define. # Cannot use INET6_ADDRSTRLEN here, because it's a C define.
var buf: array[64, char] var buf: array[64, char]
if inet_ntop(name.sin6_family.cint, 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()) raiseOSError(osLastError())
result = ($buf, Port(nativesockets.ntohs(name.sin6_port))) result = ($buf, Port(nativesockets.ntohs(name.sin6_port)))
else: else:

View file

@ -717,7 +717,7 @@ proc len*[TOpenArray: openArray|varargs](x: TOpenArray): int {.
magic: "LengthOpenArray", noSideEffect.} magic: "LengthOpenArray", noSideEffect.}
proc len*(x: string): int {.magic: "LengthStr", noSideEffect.} proc len*(x: string): int {.magic: "LengthStr", noSideEffect.}
proc len*(x: cstring): 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.} proc len*[T](x: seq[T]): int {.magic: "LengthSeq", noSideEffect.}
## returns the length of an array, an openarray, a sequence or a string. ## 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 ## 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 # Nim's configuration system now uses Nim for scripting. This module provides
# a few things that are required for this to work. # 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 template builtin = discard
# We know the effects better than the compiler: # 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)